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 61 /* 62 * STREAMS 63 */ 64 void 65 dccp_wput(queue_t *q, mblk_t *mp) 66 { 67 cmn_err(CE_NOTE, "dccp_output.c: dccp_wput"); 68 } 69 70 /* 71 * Fast path write put. 72 */ 73 void 74 dccp_wput_data(dccp_t *dccp, mblk_t *mp, boolean_t urgent) 75 { 76 cmn_err(CE_NOTE, "dccp_output.c: dccp_wput_data"); 77 } 78 79 /* 80 * 81 */ 82 void 83 dccp_wput_sock(queue_t *wq, mblk_t *mp) 84 { 85 conn_t *connp = Q_TO_CONN(wq); 86 dccp_t *dccp = connp->conn_dccp; 87 struct T_capability_req *car = (struct T_capability_req *)mp->b_rptr; 88 89 ASSERT(wq->q_qinfo == &dccp_sock_winit); 90 wq->q_qinfo = &dccp_winit; 91 92 ASSERT(IPCL_IS_TCP(connp)); 93 ASSERT(DCCP_IS_SOCKET(dccp)); 94 95 if (DB_TYPE(mp) == M_PCPROTO && 96 MBLKL(mp) == sizeof (struct T_capability_req) && 97 car->PRIM_type == T_CAPABILITY_REQ) { 98 dccp_capability_req(dccp, mp); 99 return; 100 } 101 102 dccp_wput(wq, mp); 103 } 104 105 /* ARGSUSED */ 106 void 107 dccp_wput_fallback(queue_t *eq, mblk_t *mp) 108 { 109 cmn_err(CE_NOTE, "dccp_output.c: dccp_wput_fallback"); 110 111 #ifdef DEBUG 112 cmn_err(CE_CONT, "tcp_wput_fallback: Message during fallback \n"); 113 #endif /* DEBUG */ 114 115 freemsg(mp); 116 } 117 118 /* 119 * Output fast path. 120 */ 121 void 122 dccp_output(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy) 123 { 124 conn_t *connp = (conn_t *)arg; 125 dccp_t *dccp = connp->conn_dccp; 126 dccp_stack_t *dccps = dccp->dccp_dccps; 127 dccpha_t *dccpha; 128 mblk_t *mp1; 129 ip_xmit_attr_t *ixa; 130 struct datab *db; 131 uchar_t *rptr; 132 uint32_t msize; 133 uint32_t sum; 134 int len; 135 int plen; 136 137 cmn_err(CE_NOTE, "dccp_output.c: dccp_output"); 138 139 ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) || 140 (connp->conn_fanout == NULL && connp->conn_ref >= 3)); 141 142 ASSERT(DB_TYPE(mp) == M_DATA); 143 msize = (mp->b_cont == NULL) ? MBLKL(mp) : msgdsize(mp); 144 145 ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX); 146 len = (int)(mp->b_wptr - mp->b_rptr); 147 148 if ((mp->b_cont != NULL) || 149 (dccp->dccp_state != DCCPS_OPEN) || 150 (len == 0)) { 151 dccp_wput_data(dccp, mp, B_FALSE); 152 return; 153 } 154 155 mp1 = dupb(mp); 156 if (mp1 == NULL) { 157 goto no_memory; 158 } 159 160 /* Adjust header information */ 161 dccpha = dccp->dccp_dccpha; 162 163 sum = len + connp->conn_ht_ulp_len + connp->conn_sum; 164 sum = (sum >> 16) + (sum & 0xffff); 165 dccpha->dha_sum = htons(sum); 166 167 DCCPS_BUMP_MIB(dccps, dccpOutDataSegs); 168 DCCPS_UPDATE_MIB(dccps, dccpOutDataBytes, len); 169 BUMP_LOCAL(dccp->dccp_obsegs); 170 171 plen = len + connp->conn_ht_iphc_len; 172 173 ixa = connp->conn_ixa; 174 ixa->ixa_pktlen = plen; 175 176 if (ixa->ixa_flags & IXAF_IS_IPV4) { 177 dccp->dccp_ipha->ipha_length = htons(plen); 178 } else { 179 dccp->dccp_ip6h->ip6_plen = htons(plen - IPV6_HDR_LEN); 180 } 181 182 rptr = mp1->b_rptr; 183 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 184 185 dccp_send_data(dccp, mp1); 186 187 return; 188 189 no_memory: 190 return; 191 } 192 193 void 194 dccp_output_urgent(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy) 195 { 196 cmn_err(CE_NOTE, "dccp_output.c: dccp_output_urgent"); 197 } 198 199 void 200 dccp_close_output(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy) 201 { 202 conn_t *connp = (conn_t *)arg; 203 dccp_t *dccp = connp->conn_dccp; 204 dccp_stack_t *dccps = dccp->dccp_dccps; 205 char *msg; 206 207 cmn_err(CE_NOTE, "dccp_output.c: dccp_close_output"); 208 209 /* 210 * When a non-STREAMS socket is being closed, it does not always 211 * stick around waiting for tcp_close_output to run and can therefore 212 * have dropped a reference already. So adjust the asserts accordingly. 213 */ 214 ASSERT((connp->conn_fanout != NULL && 215 connp->conn_ref >= (IPCL_IS_NONSTR(connp) ? 3 : 4)) || 216 (connp->conn_fanout == NULL && 217 connp->conn_ref >= (IPCL_IS_NONSTR(connp) ? 2 : 3))); 218 219 msg = NULL; 220 switch (dccp->dccp_state) { 221 case DCCPS_CLOSED: 222 break; 223 case DCCPS_BOUND: 224 break; 225 case DCCPS_REQUEST: 226 msg = "dccp_close, during connect"; 227 break; 228 case DCCPS_RESPOND: 229 /* FALLTHRU */ 230 default: 231 /* 232 * If SO_LINGER has set a zero linger time, abort the 233 * connection with a reset. 234 */ 235 if (connp->conn_linger && connp->conn_lingertime == 0) { 236 msg = "dccp_close, zero lingertime"; 237 break; 238 } 239 } 240 } 241 242 #pragma inline(dccp_send_data) 243 244 void 245 dccp_send_data(dccp_t *dccp, mblk_t *mp) 246 { 247 conn_t *connp = dccp->dccp_connp; 248 int error; 249 250 cmn_err(CE_NOTE, "dccp_output.c: dccp_sent_data"); 251 252 /* XXX zcopy aware */ 253 254 DTRACE_DCCP5(send, mblk_t *, NULL, ip_xmit_attr_t *, connp->conn_ixa, 255 __dtrace_dccp_void_ip_t *, mp->b_rptr, dccp_t *, dccp, 256 __dtrace_dccp_dccph_t *, 257 &mp->b_rptr[connp->conn_ixa->ixa_ip_hdr_length]); 258 259 ASSERT(connp->conn_ixa->ixa_notify_cookie == connp->conn_tcp); 260 error = conn_ip_output(mp, connp->conn_ixa); 261 if (error != 0) { 262 cmn_err(CE_NOTE, "conn_ip_output failed with code %d\n", error); 263 } 264 } 265 266 /* 267 * Send a reset as response to an incoming packet or 268 * reset a connection. 269 */ 270 void 271 dccp_xmit_listeners_reset(mblk_t *mp, ip_recv_attr_t *ira, ip_stack_t *ipst, 272 conn_t *connp) 273 { 274 netstack_t *ns = ipst->ips_netstack; 275 dccp_stack_t *dccps = ns->netstack_dccp; 276 ipsec_stack_t *ipss = dccps->dccps_netstack->netstack_ipsec; 277 dccpha_t *dccpha; 278 ipha_t *ipha; 279 ip6_t *ip6h; 280 uchar_t *rptr; 281 uint32_t seq_len; 282 uint_t ip_hdr_len = ira->ira_ip_hdr_length; 283 boolean_t policy_present; 284 285 cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_listeners_reset"); 286 287 DCCP_STAT(dccps, dccp_no_listener); 288 289 if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) { 290 policy_present = ipss->ipsec_inbound_v4_policy_present; 291 ipha = (ipha_t *)mp->b_rptr; 292 ip6h = NULL; 293 } else { 294 policy_present = ipss->ipsec_inbound_v6_policy_present; 295 ipha = NULL; 296 ip6h = (ip6_t *)mp->b_rptr; 297 } 298 299 if (policy_present) { 300 mp = ipsec_check_global_policy(mp, (conn_t *)NULL, ipha, ip6h, 301 ira, ns); 302 if (mp == NULL) { 303 return; 304 } 305 } 306 307 rptr = mp->b_rptr; 308 309 dccpha = (dccpha_t *)&rptr[ip_hdr_len]; 310 311 seq_len = msgdsize(mp) - (ip_hdr_len); 312 313 dccp_xmit_early_reset("no dccp, reset", mp, 0, 314 0, 0, ira, ipst, connp); 315 } 316 317 /* 318 * RFC 4340, Section 8.1.3 319 */ 320 static void 321 dccp_xmit_early_reset(char *str, mblk_t *mp, uint32_t seq, uint32_t ack, int ctl, 322 ip_recv_attr_t *ira, ip_stack_t *ipst, conn_t *connp) 323 { 324 dccpha_t *dccpha; 325 dccpha_t *nmp_dccpha; 326 dccpha_ack_t *nmp_dccpha_ack; 327 dccpha_reset_t *dccpha_reset; 328 dccpha_reset_t *nmp_dccpha_reset; 329 dccpha_ext_t *dccpha_ext; 330 dccpha_ext_t *nmp_dccpha_ext; 331 netstack_t *ns = ipst->ips_netstack; 332 dccp_stack_t *dccps = ns->netstack_dccp; 333 ip6_t *ip6h; 334 ipha_t *ipha; 335 ipha_t *nmp_ipha; 336 ip_xmit_attr_t ixas; 337 ip_xmit_attr_t *ixa; 338 in6_addr_t v6addr; 339 ipaddr_t v4addr; 340 mblk_t *nmp; 341 uint64_t pkt_ack; 342 uint_t ip_hdr_len = ira->ira_ip_hdr_length; 343 ushort_t port; 344 ushort_t len; 345 346 cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_early_reset"); 347 348 if (!dccp_send_rst_chk(dccps)) { 349 cmn_err(CE_NOTE, "dccp_output.c: not sending reset packet"); 350 DCCP_STAT(dccps, dccp_rst_unsent); 351 freemsg(mp); 352 return; 353 } 354 355 bzero(&ixas, sizeof (ixas)); 356 ixa = &ixas; 357 358 ixa->ixa_flags |= IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE; 359 ixa->ixa_protocol = IPPROTO_DCCP; 360 ixa->ixa_zoneid = ira->ira_zoneid; 361 ixa->ixa_ifindex = 0; 362 ixa->ixa_ipst = ipst; 363 ixa->ixa_cred = kcred; 364 ixa->ixa_cpid = NOPID; 365 366 if (str && dccps->dccps_dbg) { 367 (void) strlog(DCCP_MOD_ID, 0, 1, SL_TRACE, 368 "dccp_xmit_early_reset: '%s', seq 0x%x, ack 0x%x, " 369 "flags 0x%x", 370 str, seq, ack, ctl); 371 } 372 373 if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) { 374 ipha = (ipha_t *)mp->b_rptr; 375 376 } else { 377 /* XXX */ 378 } 379 380 /* 381 * Allocate a new DCCP reset message 382 */ 383 len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t); 384 nmp = allocb(len, BPRI_MED); 385 if (nmp == NULL) { 386 cmn_err(CE_NOTE, "alloc failed"); 387 return; 388 } 389 bcopy(mp->b_rptr, nmp->b_wptr, ip_hdr_len + sizeof (dccpha_t)); 390 391 nmp_dccpha = (dccpha_t *)&nmp->b_rptr[ip_hdr_len]; 392 nmp_dccpha->dha_offset = 7; 393 394 if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) { 395 nmp_ipha = (ipha_t *)nmp->b_rptr; 396 397 nmp_ipha->ipha_length = htons(len); 398 nmp_ipha->ipha_src = ipha->ipha_dst; 399 nmp_ipha->ipha_dst = ipha->ipha_src; 400 401 ixa->ixa_flags |= IXAF_IS_IPV4; 402 ixa->ixa_ip_hdr_length = ip_hdr_len; 403 } else { 404 cmn_err(CE_NOTE, "not v4"); 405 } 406 407 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len]; 408 409 nmp->b_wptr = &nmp->b_rptr[len]; 410 411 ixa->ixa_pktlen = len; // ? 412 413 nmp_dccpha->dha_fport = dccpha->dha_lport; 414 nmp_dccpha->dha_lport = dccpha->dha_fport; 415 nmp_dccpha->dha_type = DCCP_PKT_RESET; 416 nmp_dccpha->dha_x = 1; 417 nmp_dccpha->dha_res_seq = 0; 418 nmp_dccpha->dha_seq = 0; 419 420 nmp_dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t)); 421 422 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)]; 423 nmp_dccpha_ext = (dccpha_ext_t *)&nmp->b_rptr[ip_hdr_len + sizeof (dccpha_t)]; 424 nmp_dccpha_ext->dha_ext_seq = 0; 425 426 len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t); 427 nmp_dccpha_ack = (dccpha_ack_t *)&nmp->b_rptr[len]; 428 nmp_dccpha_ack->dha_ack_high = dccpha->dha_seq; 429 nmp_dccpha_ack->dha_ack_low = dccpha_ext->dha_ext_seq; 430 431 len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t); 432 nmp_dccpha_reset = (dccpha_reset_t *)&nmp->b_rptr[len]; 433 nmp_dccpha_reset->dha_reset_code = DCCP_RESET_CONNECTION_REFUSED; 434 nmp_dccpha_reset->dha_reset_data[0] = 0; 435 nmp_dccpha_reset->dha_reset_data[1] = 0; 436 nmp_dccpha_reset->dha_reset_data[2] = 0; 437 438 (void) ip_output_simple(nmp, ixa); 439 440 ixa_cleanup(ixa); 441 } 442 443 /* 444 * 445 */ 446 static boolean_t 447 dccp_send_rst_chk(dccp_stack_t *dccps) 448 { 449 int64_t now; 450 451 if (dccps->dccps_rst_sent_rate_enabled != 0) { 452 now = ddi_get_lbolt64(); 453 if (TICK_TO_MSEC(now - dccps->dccps_last_rst_intrvl) > 454 1 * SECONDS) { 455 dccps->dccps_last_rst_intrvl = now; 456 dccps->dccps_rst_cnt = 1; 457 } else if (++dccps->dccps_rst_cnt > dccps->dccps_rst_sent_rate) { 458 return (B_FALSE); 459 } 460 } 461 462 return (B_TRUE); 463 } 464 465 /* ARGSUSED2 */ 466 void 467 dccp_send_synack(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy) 468 { 469 conn_t *econnp = (conn_t *)arg; 470 dccp_t *dccp = econnp->conn_dccp; 471 ip_xmit_attr_t *ixa = econnp->conn_ixa; 472 473 cmn_err(CE_NOTE, "dccp_output.c: dccp_send_synack"); 474 475 /* 476 * Guard against a RESET having blown it away while on the 477 * squeue. 478 */ 479 if (dccp->dccp_state == DCCPS_CLOSED) { 480 freemsg(mp); 481 return; 482 } 483 484 ixa->ixa_pktlen = msgdsize(mp); 485 (void) conn_ip_output(mp, ixa); 486 } 487 488 mblk_t * 489 dccp_xmit_mp(dccp_t *dccp, mblk_t *mp, int32_t max_to_send, int32_t *offset, 490 mblk_t **end_mp, uint32_t seq, boolean_t sendall, uint32_t *seg_len, 491 boolean_t rexmit) 492 { 493 conn_t *connp = dccp->dccp_connp; 494 dccp_stack_t *dccps = dccp->dccp_dccps; 495 dccpha_t *dccpha; 496 dccpha_ext_t *dccpha_ext; 497 dccpha_ack_t *dccpha_ack; 498 dccpha_srv_t *dccpha_srv; 499 ip_xmit_attr_t *ixa = connp->conn_ixa; 500 mblk_t *mp1; 501 uchar_t *rptr; 502 ushort_t len; 503 int data_length; 504 505 cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_mp"); 506 507 // dccpha_t already in iphc_len? 508 len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4; 509 510 mp1 = allocb(len, BPRI_MED); 511 if (mp1 == NULL) { 512 cmn_err(CE_NOTE, "allocb failed"); 513 return (NULL); 514 } 515 516 data_length = 0; 517 518 rptr = mp1->b_rptr; 519 mp1->b_wptr = &mp1->b_rptr[len]; 520 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 521 dccpha = (dccpha_t *)&rptr[ixa->ixa_ip_hdr_length]; 522 dccpha->dha_type = DCCP_PKT_RESPONSE; 523 dccpha->dha_offset = 8; 524 dccpha->dha_x = 1; 525 dccpha->dha_ccval = 0; 526 dccpha->dha_cscov = 0; 527 dccpha->dha_reserved = 0; 528 dccpha->dha_res_seq = 0; 529 dccpha->dha_seq = 0; 530 531 dccpha_ext = (dccpha_ext_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t)]; 532 dccpha_ext->dha_ext_seq = 0; 533 534 dccpha_ack = (dccpha_ack_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t) + sizeof (dccpha_ext_t)]; 535 dccpha_ack->dha_ack_reserved = 0; 536 dccpha_ack->dha_ack_high = 0; 537 dccpha_ack->dha_ack_low = 0; 538 539 dccpha_srv = (dccpha_srv_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t)]; 540 dccpha_srv->dha_srv_code = 0; 541 542 return (mp1); 543 } 544 545 /* 546 * Generate a DCCP-Response packet. 547 */ 548 mblk_t * 549 dccp_generate_response(conn_t *connp, mblk_t *mp) 550 { 551 dccpha_t *dccpha; 552 dccpha_ext_t *dccpha_ext; 553 dccpha_ack_t *dccpha_ack; 554 dccpha_srv_t *dccpha_srv; 555 mblk_t *mp1; 556 uint64_t seq; 557 uint64_t ack; 558 uint16_t ack_high; 559 uint32_t ack_low; 560 // uint_t ip_hdr_len = ira->ira_ip_hdr_length; 561 ip_xmit_attr_t *ixa = connp->conn_ixa; 562 uint_t ip_hdr_len; 563 uint_t len; 564 uint_t total_hdr_len; 565 uchar_t *rptr; 566 dccp_t *dccp = connp->conn_dccp; 567 void *options; 568 size_t opt_len; 569 int error; 570 571 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_packet"); 572 573 ip_hdr_len = ixa->ixa_ip_hdr_length; 574 575 if (mp == NULL) { 576 cmn_err(CE_NOTE, "NULL pointer mp"); 577 return (NULL); 578 } 579 580 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len]; 581 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)]; 582 583 ack_high = dccpha->dha_seq; 584 ack_low = dccpha_ext->dha_ext_seq; 585 586 seq = ntohs(ack_high) << 31; 587 seq |= ntohl(ack_low); 588 589 dccp->dccp_isr = seq; 590 dccp->dccp_gsr = seq; 591 dccp->dccp_swl = seq; 592 dccp->dccp_swh = seq; 593 dccp->dccp_gss++; 594 595 error = dccp_generate_options(dccp, &options, &opt_len); 596 if (error != 0) { 597 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_options failed"); 598 } 599 cmn_err(CE_NOTE, "generated options len: %d", (int) opt_len); 600 601 602 /* 603 * conn_ht_iphc_len = ip_hdr_length (20) + ulp_hdr_length 604 * (20) simple ip header (without vtag or options) 605 */ 606 total_hdr_len = len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4 + opt_len; 607 mp1 = allocb(len, BPRI_MED); 608 if (mp1 == NULL) { 609 cmn_err(CE_NOTE, "allocb failed"); 610 return (NULL); 611 } 612 613 rptr = mp1->b_rptr; 614 mp1->b_wptr = &mp1->b_rptr[len]; 615 616 bcopy(options, &mp1->b_rptr[len-opt_len], opt_len); 617 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 618 dccpha = (dccpha_t *)&rptr[ip_hdr_len]; 619 620 dccpha->dha_type = DCCP_PKT_RESPONSE; 621 dccpha->dha_offset = 7 + (opt_len / 4); 622 dccpha->dha_x = 1; 623 dccpha->dha_ccval = 0; 624 dccpha->dha_cscov = 0; 625 dccpha->dha_reserved = 0; 626 dccpha->dha_res_seq = 0; 627 dccpha->dha_seq = htons(dccp->dccp_gss >> 32);; 628 dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4 + opt_len); 629 630 631 dccpha_ext = (dccpha_ext_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t)]; 632 dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff); 633 634 dccpha_ack = (dccpha_ack_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t)]; 635 dccpha_ack->dha_ack_high = ack_high; 636 dccpha_ack->dha_ack_low = ack_low; 637 638 dccpha_srv = (dccpha_srv_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t)]; 639 dccpha_srv->dha_srv_code = 0; 640 641 ixa->ixa_pktlen = total_hdr_len; 642 643 if (ixa->ixa_flags & IXAF_IS_IPV4) { 644 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len); 645 } else { 646 ip6_t *ip6 = (ip6_t *)rptr; 647 648 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN); 649 } 650 651 cmn_err(CE_NOTE, "IPHC LEN: %d", connp->conn_ht_iphc_len); 652 cmn_err(CE_NOTE, "TOTAL LEN: %d", total_hdr_len); 653 654 kmem_free(options, opt_len); 655 656 return (mp1); 657 } 658 659 /* 660 * Generate a request packet. Must use 48-bit sequence 661 * numbers. 662 */ 663 mblk_t * 664 dccp_generate_request(conn_t *connp) 665 { 666 dccp_t *dccp = connp->conn_dccp; 667 dccpha_t *dccpha; 668 dccpha_ext_t *dccpha_ext; 669 dccpha_srv_t *dccpha_srv; 670 ip_xmit_attr_t *ixa = connp->conn_ixa; 671 mblk_t *mp; 672 uchar_t *rptr; 673 uint_t total_hdr_len; 674 uint_t len; 675 676 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_request"); 677 678 total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + 679 sizeof (dccpha_srv_t); 680 mp = allocb(total_hdr_len, BPRI_MED); 681 if (mp == NULL) { 682 cmn_err(CE_NOTE, "allocb failed"); 683 return (NULL); 684 } 685 686 rptr = mp->b_rptr; 687 mp->b_wptr = &mp->b_rptr[total_hdr_len]; 688 689 /* Copy in the template header */ 690 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 691 692 len = ixa->ixa_ip_hdr_length; 693 dccpha = (dccpha_t *)&rptr[len]; 694 dccpha->dha_type = DCCP_PKT_REQUEST; 695 dccpha->dha_offset = (sizeof (dccpha_t) + sizeof (dccpha_ext_t) + 696 sizeof (dccpha_srv_t)) / 4; 697 dccpha->dha_x = 1; 698 dccpha->dha_ccval = 0; 699 dccpha->dha_cscov = 0; 700 dccpha->dha_reserved = 0; 701 dccpha->dha_res_seq = 0; 702 dccpha->dha_seq = 0; 703 dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + 704 sizeof (dccpha_srv_t)); 705 706 /* Extended sequence number */ 707 len += sizeof (dccpha_t); 708 dccpha_ext = (dccpha_ext_t *)&rptr[len]; 709 710 /* Service number */ 711 len += sizeof (dccpha_ext_t); 712 dccpha_srv = (dccpha_srv_t *)&rptr[len]; 713 dccpha_srv->dha_srv_code = 0; 714 715 ixa->ixa_pktlen = total_hdr_len; 716 717 if (ixa->ixa_flags & IXAF_IS_IPV4) { 718 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len); 719 } else { 720 ip6_t *ip6 = (ip6_t *)rptr; 721 722 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN); 723 } 724 725 return (mp); 726 } 727 728 /* 729 * Close packet. 730 */ 731 mblk_t * 732 dccp_generate_reset(conn_t *connp) 733 { 734 dccp_t *dccp = connp->conn_dccp; 735 dccpha_t *dccpha; 736 dccpha_ext_t *dccpha_ext; 737 dccpha_ack_t *dccpha_ack; 738 dccpha_reset_t *dccpha_reset; 739 ip_xmit_attr_t *ixa = connp->conn_ixa; 740 mblk_t *mp; 741 uint64_t gss; 742 uchar_t *rptr; 743 uint_t total_hdr_len; 744 uint_t len = ixa->ixa_ip_hdr_length; 745 746 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_reset"); 747 748 /* XXX */ 749 dccp->dccp_gss++; 750 751 /* 752 * Allocate a new DCCP reset message 753 */ 754 total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + 755 sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t); 756 mp = allocb(total_hdr_len, BPRI_MED); 757 if (mp == NULL) { 758 cmn_err(CE_NOTE, "allocb failed"); 759 return(NULL); 760 } 761 762 rptr = mp->b_rptr; 763 mp->b_wptr = &mp->b_rptr[total_hdr_len]; 764 765 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len); 766 767 len = ixa->ixa_ip_hdr_length; 768 dccpha = (dccpha_t *)&mp->b_rptr[len]; 769 dccpha->dha_type = DCCP_PKT_RESET; 770 dccpha->dha_offset = 7; 771 dccpha->dha_x = 1; 772 dccpha->dha_ccval = 0; 773 dccpha->dha_cscov = 0; 774 dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + 775 sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t)); 776 dccpha->dha_seq = htons(dccp->dccp_gss >> 32); 777 778 len += sizeof (dccpha_t); 779 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[len]; 780 dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff); 781 782 len += sizeof (dccpha_ext_t); 783 dccpha_ack = (dccpha_ack_t *)&mp->b_rptr[len]; 784 dccpha_ack->dha_ack_high = htons(dccp->dccp_gsr >> 32); 785 dccpha_ack->dha_ack_low = htonl(dccp->dccp_gsr & 0xffffffff); 786 787 len += sizeof (dccpha_ack_t); 788 dccpha_reset = (dccpha_reset_t *)&mp->b_rptr[len]; 789 dccpha_reset->dha_reset_code = DCCP_RESET_CLOSED; 790 dccpha_reset->dha_reset_data[0] = 0; 791 dccpha_reset->dha_reset_data[1] = 0; 792 dccpha_reset->dha_reset_data[2] = 0; 793 794 ixa->ixa_pktlen = total_hdr_len; 795 796 if (ixa->ixa_flags & IXAF_IS_IPV4) { 797 cmn_err(CE_NOTE, "setting ip len for ipv4: %d", total_hdr_len); 798 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len); 799 } else { 800 ip6_t *ip6 = (ip6_t *)rptr; 801 802 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN); 803 } 804 805 return (mp); 806 }