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