1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2012 David Hoeppner. All rights reserved. 29 */ 30 31 /* 32 * Functions related to the output path. 33 */ 34 35 #include <sys/types.h> 36 #include <sys/stream.h> 37 #include <sys/strsun.h> 38 #include <sys/strsubr.h> 39 #include <sys/stropts.h> 40 #include <sys/strlog.h> 41 #define _SUN_TPI_VERSION 2 42 #include <sys/tihdr.h> 43 #include <sys/suntpi.h> 44 #include <sys/xti_inet.h> 45 #include <sys/squeue_impl.h> 46 #include <sys/squeue.h> 47 #include <sys/tsol/tnet.h> 48 49 #include <inet/common.h> 50 #include <inet/dccp_impl.h> 51 #include <inet/dccp_stack.h> 52 #include <inet/ip.h> 53 #include <inet/ipsec_impl.h> 54 55 #include <sys/cmn_err.h> 56 57 static void dccp_xmit_early_reset(char *, mblk_t *, uint32_t, uint32_t, 58 int, ip_recv_attr_t *, ip_stack_t *, conn_t *); 59 static boolean_t dccp_send_rst_chk(dccp_stack_t *); 60 static int dccp_xmit_end(dccp_t *); 61 static mblk_t *dccp_generate_common(conn_t *, uint8_t, uint_t); 62 63 /* 64 * STREAMS 65 */ 66 void 67 dccp_wput(queue_t *q, mblk_t *mp) 68 { 69 cmn_err(CE_NOTE, "dccp_output.c: dccp_wput"); 70 } 71 72 /* 73 * Fast path write put. 74 */ 75 void 76 dccp_wput_data(dccp_t *dccp, mblk_t *mp, boolean_t urgent) 77 { 78 cmn_err(CE_NOTE, "dccp_output.c: dccp_wput_data"); 79 } 80 81 /* 82 * 83 */ 84 void 85 dccp_wput_sock(queue_t *wq, mblk_t *mp) 86 { 87 conn_t *connp = Q_TO_CONN(wq); 88 dccp_t *dccp = connp->conn_dccp; 89 struct T_capability_req *car = (struct T_capability_req *)mp->b_rptr; 90 91 cmn_err(CE_NOTE, "dccp_wput_sock"); 92 93 ASSERT(wq->q_qinfo == &dccp_sock_winit); 94 wq->q_qinfo = &dccp_winit; 95 96 ASSERT(IPCL_IS_TCP(connp)); 97 ASSERT(DCCP_IS_SOCKET(dccp)); 98 99 if (DB_TYPE(mp) == M_PCPROTO && 100 MBLKL(mp) == sizeof (struct T_capability_req) && 101 car->PRIM_type == T_CAPABILITY_REQ) { 102 dccp_capability_req(dccp, mp); 103 return; 104 } 105 106 dccp_wput(wq, mp); 107 } 108 109 /* ARGSUSED */ 110 void 111 dccp_wput_fallback(queue_t *eq, mblk_t *mp) 112 { 113 cmn_err(CE_NOTE, "dccp_output.c: dccp_wput_fallback"); 114 115 #ifdef DEBUG 116 cmn_err(CE_CONT, "tcp_wput_fallback: Message during fallback \n"); 117 #endif /* DEBUG */ 118 119 freemsg(mp); 120 } 121 122 /* 123 * Initiate closedown sequence on an active connection. 124 */ 125 static int 126 dccp_xmit_end(dccp_t *dccp) 127 { 128 conn_t *connp = dccp->dccp_connp; 129 mblk_t *mp; 130 131 /* XXX */ 132 133 return (0); 134 } 135 136 /* 137 * Output fast path. 138 */ 139 void 140 dccp_output(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy) 141 { 142 conn_t *connp = (conn_t *)arg; 143 dccp_t *dccp = connp->conn_dccp; 144 dccp_stack_t *dccps = dccp->dccp_dccps; 145 dccpha_t *dccpha; 146 mblk_t *mp1; 147 ip_xmit_attr_t *ixa; 148 struct datab *db; 149 uchar_t *rptr; 150 uint32_t msize; 151 uint32_t sum; 152 int len; 153 int plen; 154 155 cmn_err(CE_NOTE, "dccp_output.c: dccp_output"); 156 157 ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) || 158 (connp->conn_fanout == NULL && connp->conn_ref >= 3)); 159 160 ASSERT(DB_TYPE(mp) == M_DATA); 161 msize = (mp->b_cont == NULL) ? MBLKL(mp) : msgdsize(mp); 162 163 ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX); 164 len = (int)(mp->b_wptr - mp->b_rptr); 165 166 if ((mp->b_cont != NULL) || 167 (dccp->dccp_state != DCCPS_OPEN) || 168 (len == 0)) { 169 dccp_wput_data(dccp, mp, B_FALSE); 170 return; 171 } 172 173 mp1 = dupb(mp); 174 if (mp1 == NULL) { 175 goto no_memory; 176 } 177 178 /* Adjust header information */ 179 dccpha = dccp->dccp_dccpha; 180 181 sum = len + connp->conn_ht_ulp_len + connp->conn_sum; 182 sum = (sum >> 16) + (sum & 0xffff); 183 dccpha->dha_sum = htons(sum); 184 185 DCCPS_BUMP_MIB(dccps, dccpOutDataSegs); 186 DCCPS_UPDATE_MIB(dccps, dccpOutDataBytes, len); 187 BUMP_LOCAL(dccp->dccp_obsegs); 188 189 plen = len + connp->conn_ht_iphc_len; 190 191 ixa = connp->conn_ixa; 192 ixa->ixa_pktlen = plen; 193 194 if (ixa->ixa_flags & IXAF_IS_IPV4) { 195 dccp->dccp_ipha->ipha_length = htons(plen); 196 } else { 197 dccp->dccp_ip6h->ip6_plen = htons(plen - IPV6_HDR_LEN); 198 } 199 200 rptr = mp1->b_rptr; 201 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 202 203 dccp_send_data(dccp, mp1); 204 205 return; 206 207 no_memory: 208 return; 209 } 210 211 void 212 dccp_output_urgent(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy) 213 { 214 cmn_err(CE_NOTE, "dccp_output.c: dccp_output_urgent"); 215 } 216 217 void 218 dccp_close_output(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy) 219 { 220 conn_t *connp = (conn_t *)arg; 221 dccp_t *dccp = connp->conn_dccp; 222 dccp_stack_t *dccps = dccp->dccp_dccps; 223 char *msg; 224 225 cmn_err(CE_NOTE, "dccp_output.c: dccp_close_output"); 226 227 /* 228 * When a non-STREAMS socket is being closed, it does not always 229 * stick around waiting for tcp_close_output to run and can therefore 230 * have dropped a reference already. So adjust the asserts accordingly. 231 */ 232 ASSERT((connp->conn_fanout != NULL && 233 connp->conn_ref >= (IPCL_IS_NONSTR(connp) ? 3 : 4)) || 234 (connp->conn_fanout == NULL && 235 connp->conn_ref >= (IPCL_IS_NONSTR(connp) ? 2 : 3))); 236 237 msg = NULL; 238 switch (dccp->dccp_state) { 239 case DCCPS_CLOSED: 240 break; 241 case DCCPS_BOUND: 242 break; 243 case DCCPS_REQUEST: 244 msg = "dccp_close, during connect"; 245 break; 246 case DCCPS_RESPOND: 247 /* FALLTHRU */ 248 default: 249 /* 250 * If SO_LINGER has set a zero linger time, abort the 251 * connection with a reset. 252 */ 253 if (connp->conn_linger && connp->conn_lingertime == 0) { 254 msg = "dccp_close, zero lingertime"; 255 break; 256 } 257 } 258 } 259 260 /* ARGSUSED */ 261 void 262 dccp_shutdown_output(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy) 263 { 264 conn_t *connp = (conn_t *)arg; 265 dccp_t *dccp = connp->conn_dccp; 266 267 freemsg(mp); 268 269 if (dccp_xmit_end(dccp) != 0) { 270 /* 271 * We were crossing FINs and got a reset from 272 * the other side. Just ignore it. 273 */ 274 if (connp->conn_debug) { 275 (void) strlog(DCCP_MOD_ID, 0, 1, 276 SL_ERROR|SL_TRACE, 277 "dccp_shutdown_output() out of state %s", 278 dccp_display(dccp, NULL, DISP_ADDR_AND_PORT)); 279 } 280 } 281 } 282 283 #pragma inline(dccp_send_data) 284 285 void 286 dccp_send_data(dccp_t *dccp, mblk_t *mp) 287 { 288 conn_t *connp = dccp->dccp_connp; 289 int error; 290 291 cmn_err(CE_NOTE, "dccp_output.c: dccp_sent_data"); 292 293 /* XXX zcopy aware */ 294 295 DTRACE_DCCP5(send, mblk_t *, NULL, ip_xmit_attr_t *, connp->conn_ixa, 296 __dtrace_dccp_void_ip_t *, mp->b_rptr, dccp_t *, dccp, 297 __dtrace_dccp_dccph_t *, 298 &mp->b_rptr[connp->conn_ixa->ixa_ip_hdr_length]); 299 300 ASSERT(connp->conn_ixa->ixa_notify_cookie == connp->conn_tcp); 301 error = conn_ip_output(mp, connp->conn_ixa); 302 if (error != 0) { 303 cmn_err(CE_NOTE, "conn_ip_output failed with code %d\n", error); 304 } 305 } 306 307 /* 308 * Send a reset as response to an incoming packet or 309 * reset a connection. 310 */ 311 void 312 dccp_xmit_listeners_reset(mblk_t *mp, ip_recv_attr_t *ira, ip_stack_t *ipst, 313 conn_t *connp) 314 { 315 netstack_t *ns = ipst->ips_netstack; 316 dccp_stack_t *dccps = ns->netstack_dccp; 317 ipsec_stack_t *ipss = dccps->dccps_netstack->netstack_ipsec; 318 dccpha_t *dccpha; 319 ipha_t *ipha; 320 ip6_t *ip6h; 321 uchar_t *rptr; 322 uint32_t seq_len; 323 uint_t ip_hdr_len = ira->ira_ip_hdr_length; 324 boolean_t policy_present; 325 326 cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_listeners_reset"); 327 328 DCCP_STAT(dccps, dccp_no_listener); 329 330 if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) { 331 policy_present = ipss->ipsec_inbound_v4_policy_present; 332 ipha = (ipha_t *)mp->b_rptr; 333 ip6h = NULL; 334 } else { 335 policy_present = ipss->ipsec_inbound_v6_policy_present; 336 ipha = NULL; 337 ip6h = (ip6_t *)mp->b_rptr; 338 } 339 340 if (policy_present) { 341 mp = ipsec_check_global_policy(mp, (conn_t *)NULL, ipha, ip6h, 342 ira, ns); 343 if (mp == NULL) { 344 return; 345 } 346 } 347 348 rptr = mp->b_rptr; 349 350 dccpha = (dccpha_t *)&rptr[ip_hdr_len]; 351 352 seq_len = msgdsize(mp) - (ip_hdr_len); 353 354 dccp_xmit_early_reset("no dccp, reset", mp, 0, 355 0, 0, ira, ipst, connp); 356 } 357 358 /* 359 * RFC 4340, Section 8.1.3 360 */ 361 static void 362 dccp_xmit_early_reset(char *str, mblk_t *mp, uint32_t seq, uint32_t ack, int ctl, 363 ip_recv_attr_t *ira, ip_stack_t *ipst, conn_t *connp) 364 { 365 dccpha_t *dccpha; 366 dccpha_t *nmp_dccpha; 367 dccpha_ack_t *nmp_dccpha_ack; 368 dccpha_reset_t *dccpha_reset; 369 dccpha_reset_t *nmp_dccpha_reset; 370 dccpha_ext_t *dccpha_ext; 371 dccpha_ext_t *nmp_dccpha_ext; 372 netstack_t *ns = ipst->ips_netstack; 373 dccp_stack_t *dccps = ns->netstack_dccp; 374 ip6_t *ip6h; 375 ipha_t *ipha; 376 ipha_t *nmp_ipha; 377 ip_xmit_attr_t ixas; 378 ip_xmit_attr_t *ixa; 379 in6_addr_t v6addr; 380 ipaddr_t v4addr; 381 mblk_t *nmp; 382 uint64_t pkt_ack; 383 uint_t ip_hdr_len = ira->ira_ip_hdr_length; 384 ushort_t port; 385 ushort_t len; 386 387 cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_early_reset"); 388 389 if (!dccp_send_rst_chk(dccps)) { 390 cmn_err(CE_NOTE, "dccp_output.c: not sending reset packet"); 391 DCCP_STAT(dccps, dccp_rst_unsent); 392 freemsg(mp); 393 return; 394 } 395 396 bzero(&ixas, sizeof (ixas)); 397 ixa = &ixas; 398 399 ixa->ixa_flags |= IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE; 400 ixa->ixa_protocol = IPPROTO_DCCP; 401 ixa->ixa_zoneid = ira->ira_zoneid; 402 ixa->ixa_ifindex = 0; 403 ixa->ixa_ipst = ipst; 404 ixa->ixa_cred = kcred; 405 ixa->ixa_cpid = NOPID; 406 407 if (str && dccps->dccps_dbg) { 408 (void) strlog(DCCP_MOD_ID, 0, 1, SL_TRACE, 409 "dccp_xmit_early_reset: '%s', seq 0x%x, ack 0x%x, " 410 "flags 0x%x", 411 str, seq, ack, ctl); 412 } 413 414 if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) { 415 ipha = (ipha_t *)mp->b_rptr; 416 417 } else { 418 /* XXX */ 419 } 420 421 /* 422 * Allocate a new DCCP reset message 423 */ 424 len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t); 425 nmp = allocb(len, BPRI_MED); 426 if (nmp == NULL) { 427 cmn_err(CE_NOTE, "alloc failed"); 428 return; 429 } 430 bcopy(mp->b_rptr, nmp->b_wptr, ip_hdr_len + sizeof (dccpha_t)); 431 432 nmp_dccpha = (dccpha_t *)&nmp->b_rptr[ip_hdr_len]; 433 nmp_dccpha->dha_offset = 7; 434 435 if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) { 436 nmp_ipha = (ipha_t *)nmp->b_rptr; 437 438 nmp_ipha->ipha_length = htons(len); 439 nmp_ipha->ipha_src = ipha->ipha_dst; 440 nmp_ipha->ipha_dst = ipha->ipha_src; 441 442 ixa->ixa_flags |= IXAF_IS_IPV4; 443 ixa->ixa_ip_hdr_length = ip_hdr_len; 444 } else { 445 cmn_err(CE_NOTE, "not v4"); 446 } 447 448 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len]; 449 450 nmp->b_wptr = &nmp->b_rptr[len]; 451 452 ixa->ixa_pktlen = len; // ? 453 454 nmp_dccpha->dha_fport = dccpha->dha_lport; 455 nmp_dccpha->dha_lport = dccpha->dha_fport; 456 nmp_dccpha->dha_type = DCCP_PKT_RESET; 457 nmp_dccpha->dha_x = 1; 458 nmp_dccpha->dha_res_seq = 0; 459 nmp_dccpha->dha_seq = 0; 460 461 nmp_dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + 462 sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t)); 463 464 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)]; 465 nmp_dccpha_ext = (dccpha_ext_t *)&nmp->b_rptr[ip_hdr_len + sizeof (dccpha_t)]; 466 nmp_dccpha_ext->dha_ext_seq = 0; 467 468 len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t); 469 nmp_dccpha_ack = (dccpha_ack_t *)&nmp->b_rptr[len]; 470 nmp_dccpha_ack->dha_ack_high = dccpha->dha_seq; 471 nmp_dccpha_ack->dha_ack_low = dccpha_ext->dha_ext_seq; 472 nmp_dccpha_ack->dha_ack_reserved = 0; 473 474 len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t); 475 nmp_dccpha_reset = (dccpha_reset_t *)&nmp->b_rptr[len]; 476 477 if (connp != NULL) { 478 nmp_dccpha_reset->dha_reset_code = 479 connp->conn_dccp->dccp_reset_code; 480 } else { 481 nmp_dccpha_reset->dha_reset_code = 482 DCCP_RESET_CONNECTION_REFUSED; 483 } 484 nmp_dccpha_reset->dha_reset_data[0] = 0; 485 nmp_dccpha_reset->dha_reset_data[1] = 0; 486 nmp_dccpha_reset->dha_reset_data[2] = 0; 487 488 (void) ip_output_simple(nmp, ixa); 489 490 ixa_cleanup(ixa); 491 } 492 493 /* 494 * 495 */ 496 static boolean_t 497 dccp_send_rst_chk(dccp_stack_t *dccps) 498 { 499 int64_t now; 500 501 if (dccps->dccps_rst_sent_rate_enabled != 0) { 502 now = ddi_get_lbolt64(); 503 if (TICK_TO_MSEC(now - dccps->dccps_last_rst_intrvl) > 504 1 * SECONDS) { 505 dccps->dccps_last_rst_intrvl = now; 506 dccps->dccps_rst_cnt = 1; 507 } else if (++dccps->dccps_rst_cnt > dccps->dccps_rst_sent_rate) { 508 return (B_FALSE); 509 } 510 } 511 512 return (B_TRUE); 513 } 514 515 /* ARGSUSED2 */ 516 void 517 dccp_send_synack(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy) 518 { 519 conn_t *econnp = (conn_t *)arg; 520 dccp_t *dccp = econnp->conn_dccp; 521 ip_xmit_attr_t *ixa = econnp->conn_ixa; 522 523 cmn_err(CE_NOTE, "dccp_output.c: dccp_send_synack"); 524 525 /* 526 * Guard against a RESET having blown it away while on the 527 * squeue. 528 */ 529 if (dccp->dccp_state == DCCPS_CLOSED) { 530 freemsg(mp); 531 return; 532 } 533 534 ixa->ixa_pktlen = msgdsize(mp); 535 (void) conn_ip_output(mp, ixa); 536 } 537 538 mblk_t * 539 dccp_xmit_mp(dccp_t *dccp, mblk_t *mp, int32_t max_to_send, int32_t *offset, 540 mblk_t **end_mp, uint32_t seq, boolean_t sendall, uint32_t *seg_len, 541 boolean_t rexmit) 542 { 543 conn_t *connp = dccp->dccp_connp; 544 dccp_stack_t *dccps = dccp->dccp_dccps; 545 dccpha_t *dccpha; 546 dccpha_ext_t *dccpha_ext; 547 dccpha_ack_t *dccpha_ack; 548 dccpha_srv_t *dccpha_srv; 549 ip_xmit_attr_t *ixa = connp->conn_ixa; 550 mblk_t *mp1; 551 uchar_t *rptr; 552 ushort_t len; 553 int data_length; 554 555 cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_mp"); 556 557 // dccpha_t already in iphc_len? 558 len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4; 559 560 mp1 = allocb(len, BPRI_MED); 561 if (mp1 == NULL) { 562 cmn_err(CE_NOTE, "allocb failed"); 563 return (NULL); 564 } 565 566 data_length = 0; 567 568 rptr = mp1->b_rptr; 569 mp1->b_wptr = &mp1->b_rptr[len]; 570 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 571 dccpha = (dccpha_t *)&rptr[ixa->ixa_ip_hdr_length]; 572 dccpha->dha_type = DCCP_PKT_RESPONSE; 573 dccpha->dha_offset = 8; 574 dccpha->dha_x = 1; 575 dccpha->dha_ccval = 0; 576 dccpha->dha_cscov = 0; 577 dccpha->dha_reserved = 0; 578 dccpha->dha_res_seq = 0; 579 dccpha->dha_seq = 0; 580 581 dccpha_ext = (dccpha_ext_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t)]; 582 dccpha_ext->dha_ext_seq = 0; 583 584 dccpha_ack = (dccpha_ack_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t) + sizeof (dccpha_ext_t)]; 585 dccpha_ack->dha_ack_reserved = 0; 586 dccpha_ack->dha_ack_high = 0; 587 dccpha_ack->dha_ack_low = 0; 588 589 dccpha_srv = (dccpha_srv_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t)]; 590 dccpha_srv->dha_srv_code = 0; 591 592 return (mp1); 593 } 594 595 /* 596 * Generate a DCCP-Response packet. 597 */ 598 mblk_t * 599 dccp_generate_response(conn_t *connp, mblk_t *mp) 600 { 601 dccpha_t *dccpha; 602 dccpha_ext_t *dccpha_ext; 603 dccpha_ack_t *dccpha_ack; 604 dccpha_srv_t *dccpha_srv; 605 mblk_t *mp1; 606 uint64_t seq; 607 uint64_t ack; 608 uint16_t ack_high; 609 uint32_t ack_low; 610 // uint_t ip_hdr_len = ira->ira_ip_hdr_length; 611 ip_xmit_attr_t *ixa = connp->conn_ixa; 612 uint_t ip_hdr_len; 613 uint_t len; 614 uint_t total_hdr_len; 615 uchar_t *rptr; 616 dccp_t *dccp = connp->conn_dccp; 617 void *options; 618 size_t opt_len; 619 int error; 620 621 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_packet"); 622 623 ip_hdr_len = ixa->ixa_ip_hdr_length; 624 625 if (mp == NULL) { 626 cmn_err(CE_NOTE, "NULL pointer mp"); 627 return (NULL); 628 } 629 630 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len]; 631 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)]; 632 633 ack_high = dccpha->dha_seq; 634 ack_low = dccpha_ext->dha_ext_seq; 635 636 seq = ntohs(ack_high) << 31; 637 seq |= ntohl(ack_low); 638 639 dccp->dccp_isr = seq; 640 dccp->dccp_gsr = seq; 641 dccp->dccp_swl = seq; 642 dccp->dccp_swh = seq; 643 dccp->dccp_gss++; 644 645 error = dccp_generate_options(dccp, &options, &opt_len); 646 if (error != 0) { 647 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_options failed"); 648 } 649 cmn_err(CE_NOTE, "generated options len: %d", (int) opt_len); 650 651 652 /* 653 * conn_ht_iphc_len = ip_hdr_length (20) + ulp_hdr_length 654 * (20) simple ip header (without vtag or options) 655 */ 656 total_hdr_len = len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4 + opt_len; 657 mp1 = allocb(len, BPRI_MED); 658 if (mp1 == NULL) { 659 cmn_err(CE_NOTE, "allocb failed"); 660 return (NULL); 661 } 662 663 rptr = mp1->b_rptr; 664 mp1->b_wptr = &mp1->b_rptr[len]; 665 666 bcopy(options, &mp1->b_rptr[len-opt_len], opt_len); 667 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 668 dccpha = (dccpha_t *)&rptr[ip_hdr_len]; 669 670 dccpha->dha_type = DCCP_PKT_RESPONSE; 671 dccpha->dha_offset = 7 + (opt_len / 4); 672 dccpha->dha_x = 1; 673 dccpha->dha_ccval = 0; 674 dccpha->dha_cscov = 0; 675 dccpha->dha_reserved = 0; 676 dccpha->dha_res_seq = 0; 677 dccpha->dha_seq = htons(dccp->dccp_gss >> 32);; 678 dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4 + opt_len); 679 680 681 dccpha_ext = (dccpha_ext_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t)]; 682 dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff); 683 684 dccpha_ack = (dccpha_ack_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t)]; 685 dccpha_ack->dha_ack_high = ack_high; 686 dccpha_ack->dha_ack_low = ack_low; 687 dccpha_ack->dha_ack_reserved = 0; 688 689 dccpha_srv = (dccpha_srv_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t)]; 690 dccpha_srv->dha_srv_code = 0; 691 692 ixa->ixa_pktlen = total_hdr_len; 693 694 if (ixa->ixa_flags & IXAF_IS_IPV4) { 695 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len); 696 } else { 697 ip6_t *ip6 = (ip6_t *)rptr; 698 699 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN); 700 } 701 702 cmn_err(CE_NOTE, "IPHC LEN: %d", connp->conn_ht_iphc_len); 703 cmn_err(CE_NOTE, "TOTAL LEN: %d", total_hdr_len); 704 705 kmem_free(options, opt_len); 706 707 return (mp1); 708 } 709 710 /* 711 * Generate a request packet. Must use 48-bit sequence 712 * numbers. 713 */ 714 mblk_t * 715 dccp_generate_request(conn_t *connp) 716 { 717 dccp_t *dccp = connp->conn_dccp; 718 dccpha_t *dccpha; 719 dccpha_ext_t *dccpha_ext; 720 dccpha_srv_t *dccpha_srv; 721 ip_xmit_attr_t *ixa = connp->conn_ixa; 722 mblk_t *mp; 723 uchar_t *rptr; 724 uint_t total_hdr_len; 725 uint_t len; 726 727 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_request"); 728 729 total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + 730 sizeof (dccpha_srv_t); 731 mp = allocb(total_hdr_len, BPRI_MED); 732 if (mp == NULL) { 733 cmn_err(CE_NOTE, "allocb failed"); 734 return (NULL); 735 } 736 737 rptr = mp->b_rptr; 738 mp->b_wptr = &mp->b_rptr[total_hdr_len]; 739 740 /* Copy in the template header */ 741 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 742 743 len = ixa->ixa_ip_hdr_length; 744 dccpha = (dccpha_t *)&rptr[len]; 745 dccpha->dha_type = DCCP_PKT_REQUEST; 746 dccpha->dha_offset = (sizeof (dccpha_t) + sizeof (dccpha_ext_t) + 747 sizeof (dccpha_srv_t)) / 4; 748 dccpha->dha_x = 1; 749 dccpha->dha_ccval = 0; 750 dccpha->dha_cscov = 0; 751 dccpha->dha_reserved = 0; 752 dccpha->dha_res_seq = 0; 753 dccpha->dha_seq = 0; 754 dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + 755 sizeof (dccpha_srv_t)); 756 757 /* Extended sequence number */ 758 len += sizeof (dccpha_t); 759 dccpha_ext = (dccpha_ext_t *)&rptr[len]; 760 761 /* Service number */ 762 len += sizeof (dccpha_ext_t); 763 dccpha_srv = (dccpha_srv_t *)&rptr[len]; 764 dccpha_srv->dha_srv_code = 0; 765 766 ixa->ixa_pktlen = total_hdr_len; 767 768 if (ixa->ixa_flags & IXAF_IS_IPV4) { 769 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len); 770 } else { 771 ip6_t *ip6 = (ip6_t *)rptr; 772 773 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN); 774 } 775 776 return (mp); 777 } 778 779 /* 780 * Close packet. 781 */ 782 mblk_t * 783 dccp_generate_reset(conn_t *connp) 784 { 785 dccp_t *dccp = connp->conn_dccp; 786 dccpha_t *dccpha; 787 dccpha_ext_t *dccpha_ext; 788 dccpha_ack_t *dccpha_ack; 789 dccpha_reset_t *dccpha_reset; 790 ip_xmit_attr_t *ixa = connp->conn_ixa; 791 mblk_t *mp; 792 uint64_t gss; 793 uchar_t *rptr; 794 uint_t total_hdr_len; 795 uint_t len = ixa->ixa_ip_hdr_length; 796 797 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_reset"); 798 799 /* XXX */ 800 dccp->dccp_gss++; 801 802 /* 803 * Allocate a new DCCP reset message 804 */ 805 total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + 806 sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t); 807 mp = allocb(total_hdr_len, BPRI_MED); 808 if (mp == NULL) { 809 cmn_err(CE_NOTE, "allocb failed"); 810 return(NULL); 811 } 812 813 rptr = mp->b_rptr; 814 mp->b_wptr = &mp->b_rptr[total_hdr_len]; 815 816 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 817 818 len = ixa->ixa_ip_hdr_length; 819 dccpha = (dccpha_t *)&mp->b_rptr[len]; 820 dccpha->dha_type = DCCP_PKT_RESET; 821 dccpha->dha_offset = 7; 822 dccpha->dha_x = 1; 823 dccpha->dha_ccval = 0; 824 dccpha->dha_cscov = 0; 825 dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + 826 sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t)); 827 dccpha->dha_seq = htons(dccp->dccp_gss >> 32); 828 dccpha->dha_res_seq = 0; 829 830 len += sizeof (dccpha_t); 831 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[len]; 832 dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff); 833 834 /* Set ack */ 835 len += sizeof (dccpha_ext_t); 836 dccpha_ack = (dccpha_ack_t *)&mp->b_rptr[len]; 837 dccpha_ack->dha_ack_high = htons(dccp->dccp_gsr >> 32); 838 dccpha_ack->dha_ack_low = htonl(dccp->dccp_gsr & 0xffffffff); 839 dccpha_ack->dha_ack_reserved = 0; 840 841 len += sizeof (dccpha_ack_t); 842 dccpha_reset = (dccpha_reset_t *)&mp->b_rptr[len]; 843 dccpha_reset->dha_reset_code = dccp->dccp_reset_code; 844 dccpha_reset->dha_reset_data[0] = dccp->dccp_reset_data[0]; 845 dccpha_reset->dha_reset_data[1] = dccp->dccp_reset_data[1]; 846 dccpha_reset->dha_reset_data[2] = dccp->dccp_reset_data[2]; 847 848 ixa->ixa_pktlen = total_hdr_len; 849 850 if (ixa->ixa_flags & IXAF_IS_IPV4) { 851 cmn_err(CE_NOTE, "setting ip len for ipv4: %d", total_hdr_len); 852 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len); 853 } else { 854 ip6_t *ip6 = (ip6_t *)rptr; 855 856 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN); 857 } 858 859 return (mp); 860 } 861 862 /* 863 * Acknowledgement packet. 864 */ 865 mblk_t * 866 dccp_generate_ack(conn_t *connp) 867 { 868 dccp_t *dccp = connp->conn_dccp; 869 dccpha_t *dccpha; 870 dccpha_ext_t *dccpha_ext; 871 dccpha_ack_t *dccpha_ack; 872 ip_xmit_attr_t *ixa = connp->conn_ixa; 873 mblk_t *mp; 874 uint64_t gss; 875 uchar_t *rptr; 876 uint_t total_hdr_len; 877 uint_t len = ixa->ixa_ip_hdr_length; 878 879 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_ack"); 880 881 /* XXX */ 882 dccp->dccp_gss++; 883 884 /* 885 * Allocate a new DCCP reset message 886 */ 887 total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + 888 sizeof (dccpha_ack_t); 889 mp = allocb(total_hdr_len, BPRI_MED); 890 if (mp == NULL) { 891 cmn_err(CE_NOTE, "allocb failed"); 892 return(NULL); 893 } 894 895 rptr = mp->b_rptr; 896 mp->b_wptr = &mp->b_rptr[total_hdr_len]; 897 898 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 899 900 len = ixa->ixa_ip_hdr_length; 901 dccpha = (dccpha_t *)&mp->b_rptr[len]; 902 dccpha->dha_type = DCCP_PKT_ACK; 903 dccpha->dha_offset = 6; 904 dccpha->dha_x = 1; 905 dccpha->dha_ccval = 0; 906 dccpha->dha_cscov = 0; 907 dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + 908 sizeof (dccpha_ack_t)); 909 dccpha->dha_seq = htons(dccp->dccp_gss >> 32); 910 dccpha->dha_res_seq = 0; 911 912 len += sizeof (dccpha_t); 913 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[len]; 914 dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff); 915 916 len += sizeof (dccpha_ext_t); 917 dccpha_ack = (dccpha_ack_t *)&mp->b_rptr[len]; 918 dccpha_ack->dha_ack_high = htons(dccp->dccp_gsr >> 32); 919 dccpha_ack->dha_ack_low = htonl(dccp->dccp_gsr & 0xffffffff); 920 dccpha_ack->dha_ack_reserved = 0; 921 922 ixa->ixa_pktlen = total_hdr_len; 923 924 if (ixa->ixa_flags & IXAF_IS_IPV4) { 925 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len); 926 } else { 927 ip6_t *ip6 = (ip6_t *)rptr; 928 929 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN); 930 } 931 932 return (mp); 933 } 934 935 /* 936 * Common to all packet generating functions. 937 */ 938 static mblk_t * 939 dccp_generate_common(conn_t *connp, uint8_t packet_type, 940 uint_t total_hdr_len) 941 { 942 dccp_t *dccp = connp->conn_dccp; 943 dccpha_t *dccpha; 944 dccpha_ext_t *dccpha_ext; 945 dccpha_ack_t *dccpha_ack; 946 ip_xmit_attr_t *ixa = connp->conn_ixa; 947 mblk_t *mp; 948 uchar_t *rptr; 949 uint_t len; 950 boolean_t extended; 951 952 /* 953 * Allocate a new DCCP reset message 954 */ 955 mp = allocb(total_hdr_len, BPRI_MED); 956 if (mp == NULL) { 957 return(NULL); 958 } 959 960 dccp->dccp_gss++; 961 962 rptr = mp->b_rptr; 963 mp->b_wptr = &mp->b_rptr[total_hdr_len]; 964 965 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 966 967 /* Basic header */ 968 len = ixa->ixa_ip_hdr_length; 969 dccpha = (dccpha_t *)&mp->b_rptr[len]; 970 dccpha->dha_type = packet_type; 971 dccpha->dha_offset = 6; 972 dccpha->dha_x = 1; 973 dccpha->dha_ccval = 0; 974 dccpha->dha_cscov = 0; 975 dccpha->dha_sum = htons(total_hdr_len - len); 976 dccpha->dha_seq = htons(dccp->dccp_gss >> 32); 977 dccpha->dha_res_seq = 0; 978 979 /* Extended sequence number */ 980 len += sizeof (dccpha_t); 981 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[len]; 982 dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff); 983 984 /* Acknowledgement number */ 985 len += sizeof (dccpha_ext_t); 986 dccpha_ack = (dccpha_ack_t *)&mp->b_rptr[len]; 987 dccpha_ack->dha_ack_high = htons(dccp->dccp_gsr >> 32); 988 dccpha_ack->dha_ack_low = htonl(dccp->dccp_gsr & 0xffffffff); 989 dccpha_ack->dha_ack_reserved = 0; 990 991 ixa->ixa_pktlen = total_hdr_len; 992 993 if (ixa->ixa_flags & IXAF_IS_IPV4) { 994 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len); 995 } else { 996 ip6_t *ip6 = (ip6_t *)rptr; 997 998 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN); 999 } 1000 1001 return (mp); 1002 } 1003 1004 /* 1005 * Acknowledgement packet. 1006 */ 1007 mblk_t * 1008 dccp_generate_sync(conn_t *connp) 1009 { 1010 dccp_t *dccp = connp->conn_dccp; 1011 dccpha_t *dccpha; 1012 dccpha_ext_t *dccpha_ext; 1013 dccpha_ack_t *dccpha_ack; 1014 ip_xmit_attr_t *ixa = connp->conn_ixa; 1015 mblk_t *mp; 1016 uchar_t *rptr; 1017 uint_t total_hdr_len; 1018 uint_t len = ixa->ixa_ip_hdr_length; 1019 1020 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_ack"); 1021 1022 total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + 1023 sizeof (dccpha_ack_t); 1024 mp = dccp_generate_common(connp, DCCP_PACKET_SYNC, total_hdr_len); 1025 if (mp == NULL) { 1026 cmn_err(CE_NOTE, "allocb failed"); 1027 return(NULL); 1028 } 1029 1030 rptr = mp->b_rptr; 1031 mp->b_wptr = &mp->b_rptr[total_hdr_len]; 1032 1033 return (mp); 1034 }