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 #include <sys/types.h> 32 #include <sys/stream.h> 33 #include <sys/strsun.h> 34 #include <sys/strsubr.h> 35 #include <sys/stropts.h> 36 #include <sys/strlog.h> 37 #define _SUN_TPI_VERSION 2 38 #include <sys/tihdr.h> 39 #include <sys/suntpi.h> 40 #include <sys/xti_inet.h> 41 #include <sys/squeue_impl.h> 42 #include <sys/squeue.h> 43 #include <sys/tsol/tnet.h> 44 45 #include <inet/common.h> 46 #include <inet/dccp_impl.h> 47 #include <inet/ip.h> 48 49 #include <sys/cmn_err.h> 50 51 static mblk_t *dccp_conn_create_v4(conn_t *, conn_t *, mblk_t *, 52 ip_recv_attr_t *); 53 static mblk_t *dccp_conn_create_v6(conn_t *, conn_t *, mblk_t *, 54 ip_recv_attr_t *); 55 static void dccp_input_listener(void *, mblk_t *, void *, ip_recv_attr_t *); 56 static void dccp_icmp_error_ipv6(dccp_t *, mblk_t *, ip_recv_attr_t *); 57 static int dccp_check_input(conn_t *, mblk_t *, ip_recv_attr_t *); 58 59 void 60 dccp_icmp_input(void *arg1, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) 61 { 62 conn_t *connp = (conn_t *)arg1; 63 dccp_t *dccp = connp->conn_dccp; 64 ipha_t *ipha; 65 icmph_t *icmph; 66 sin_t sin; 67 sin6_t sin6; 68 int iph_hdr_length; 69 int error; 70 71 cmn_err(CE_NOTE, "dccp_input.c: dccp_icmp_input"); 72 73 ipha = (ipha_t *)mp->b_rptr; 74 75 /* Assume IP provides aligned packets */ 76 ASSERT(OK_32PTR(mp->b_rptr)); 77 ASSERT((MBLKL(mp) >= sizeof (ipha_t))); 78 79 if (dccp->dccp_state == DCCPS_CLOSED) { 80 freemsg(mp); 81 return; 82 } 83 84 /* 85 * Verify IP version. Anything other than IPv4 or IPv6 packet is sent 86 * upstream. ICMPv6 is handled in dccp_icmp_error_ipv6. 87 */ 88 if (IPH_HDR_VERSION(ipha) != IPV4_VERSION) { 89 ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION); 90 dccp_icmp_error_ipv6(dccp, mp, ira); 91 return; 92 } 93 ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION); 94 95 ASSERT(IPH_HDR_LENGTH(ipha) == ira->ira_ip_hdr_length); 96 /* Skip past the outer IP and ICMP headers */ 97 iph_hdr_length = ira->ira_ip_hdr_length; 98 icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length]; 99 100 switch (icmph->icmph_type) { 101 case ICMP_DEST_UNREACHABLE: 102 switch (icmph->icmph_code) { 103 case ICMP_FRAGMENTATION_NEEDED: 104 case ICMP_PORT_UNREACHABLE: 105 case ICMP_PROTOCOL_UNREACHABLE: 106 case ICMP_HOST_UNREACHABLE: 107 case ICMP_NET_UNREACHABLE: 108 break; 109 default: 110 break; 111 } 112 break; 113 case ICMP_SOURCE_QUENCH: 114 break; 115 } 116 117 freemsg(mp); 118 } 119 120 /* 121 * Handler for ICMPv6 error messages. 122 */ 123 static void 124 dccp_icmp_error_ipv6(dccp_t *dccp, mblk_t *mp, ip_recv_attr_t *ira) 125 { 126 ip6_t *ip6h; 127 icmp6_t *icmp6; 128 uint16_t iph_hdr_length = ira->ira_ip_hdr_length; 129 130 cmn_err(CE_NOTE, "dccp_input.c: dccp_icmp_error_ipv6"); 131 132 ASSERT((MBLKL(mp) >= sizeof (ip6_t))); 133 134 icmp6 = (icmp6_t *)&mp->b_rptr[iph_hdr_length]; 135 ip6h = (ip6_t *)&icmp6[1]; 136 137 } 138 139 void 140 dccp_rsrv(queue_t *q) 141 { 142 cmn_err(CE_NOTE, "dccp_input.c: dccp_rsrv"); 143 } 144 145 /* 146 * Handle a REQUEST on an AF_INET6 socket; can be either IPv4 or IPv6. 147 */ 148 static mblk_t * 149 dccp_conn_create_v6(conn_t *lconnp, conn_t *connp, mblk_t *mp, 150 ip_recv_attr_t *ira) 151 { 152 dccp_t *ldccp = lconnp->conn_dccp; 153 dccp_t *dccp = connp->conn_dccp; 154 dccp_stack_t *dccps = dccp->dccp_dccps; 155 ipha_t *ipha; 156 ip6_t *ip6h; 157 mblk_t *tpi_mp; 158 sin6_t sin6; 159 uint_t ifindex = ira->ira_ruifindex; 160 161 if (ira->ira_flags & IRAF_IS_IPV4) { 162 ipha = (ipha_t *)mp->b_rptr; 163 164 connp->conn_ipversion = IPV4_VERSION; 165 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_laddr_v6); 166 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_faddr_v6); 167 connp->conn_saddr_v6 = connp->conn_laddr_v6; 168 169 sin6 = sin6_null; 170 sin6.sin6_addr = connp->conn_faddr_v6; 171 sin6.sin6_port = connp->conn_fport; 172 sin6.sin6_family = AF_INET6; 173 sin6.__sin6_src_id = ip_srcid_find_addr(&connp->conn_laddr_v6, 174 IPCL_ZONEID(lconnp), dccps->dccps_netstack); 175 176 if (connp->conn_recv_ancillary.crb_recvdstaddr) { 177 sin6_t sin6d; 178 179 sin6d = sin6_null; 180 sin6d.sin6_addr = connp->conn_laddr_v6; 181 sin6d.sin6_port = connp->conn_lport; 182 sin6d.sin6_family = AF_INET; 183 tpi_mp = mi_tpi_extconn_ind(NULL, 184 (char *)&sin6d, sizeof (sin6_t), 185 (char *)&dccp, 186 (t_scalar_t)sizeof (intptr_t), 187 (char *)&sin6d, sizeof (sin6_t), 188 (t_scalar_t)ldccp->dccp_conn_req_seqnum); 189 } else { 190 tpi_mp = mi_tpi_conn_ind(NULL, 191 (char *)&sin6, sizeof (sin6_t), 192 (char *)&dccp, (t_scalar_t)sizeof (intptr_t), 193 (t_scalar_t)ldccp->dccp_conn_req_seqnum); 194 } 195 } else { 196 ip6h = (ip6_t *)mp->b_rptr; 197 198 connp->conn_ipversion = IPV6_VERSION; 199 connp->conn_laddr_v6 = ip6h->ip6_dst; 200 connp->conn_faddr_v6 = ip6h->ip6_src; 201 connp->conn_saddr_v6 = connp->conn_laddr_v6; 202 203 sin6 = sin6_null; 204 sin6.sin6_addr = connp->conn_faddr_v6; 205 sin6.sin6_port = connp->conn_fport; 206 sin6.sin6_family = AF_INET6; 207 sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK; 208 sin6.__sin6_src_id = ip_srcid_find_addr(&connp->conn_laddr_v6, 209 IPCL_ZONEID(lconnp), dccps->dccps_netstack); 210 211 if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) { 212 /* Pass up the scope_id of remote addr */ 213 sin6.sin6_scope_id = ifindex; 214 } else { 215 sin6.sin6_scope_id = 0; 216 } 217 if (connp->conn_recv_ancillary.crb_recvdstaddr) { 218 sin6_t sin6d; 219 220 sin6d = sin6_null; 221 sin6.sin6_addr = connp->conn_laddr_v6; 222 sin6d.sin6_port = connp->conn_lport; 223 sin6d.sin6_family = AF_INET6; 224 if (IN6_IS_ADDR_LINKSCOPE(&connp->conn_laddr_v6)) 225 sin6d.sin6_scope_id = ifindex; 226 227 tpi_mp = mi_tpi_extconn_ind(NULL, 228 (char *)&sin6d, sizeof (sin6_t), 229 (char *)&dccp, (t_scalar_t)sizeof (intptr_t), 230 (char *)&sin6d, sizeof (sin6_t), 231 (t_scalar_t)ldccp->dccp_conn_req_seqnum); 232 } else { 233 tpi_mp = mi_tpi_conn_ind(NULL, 234 (char *)&sin6, sizeof (sin6_t), 235 (char *)&dccp, (t_scalar_t)sizeof (intptr_t), 236 (t_scalar_t)ldccp->dccp_conn_req_seqnum); 237 } 238 } 239 240 /* XXX mss */ 241 return (tpi_mp); 242 } 243 244 /* 245 * Handle a REQUEST on an AF_INET socket. 246 */ 247 static mblk_t * 248 dccp_conn_create_v4(conn_t *lconnp, conn_t *connp, mblk_t *mp, 249 ip_recv_attr_t *ira) 250 { 251 dccp_t *ldccp = lconnp->conn_dccp; 252 dccp_t *dccp = connp->conn_dccp; 253 dccp_stack_t *dccps = dccp->dccp_dccps; 254 ipha_t *ipha; 255 mblk_t *tpi_mp; 256 sin_t sin; 257 258 ASSERT(ira->ira_flags & IRAF_IS_IPV4); 259 ipha = (ipha_t *)mp->b_rptr; 260 261 connp->conn_ipversion = IPV4_VERSION; 262 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_laddr_v6); 263 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_faddr_v6); 264 connp->conn_saddr_v6 = connp->conn_laddr_v6; 265 266 sin = sin_null; 267 sin.sin_addr.s_addr = connp->conn_faddr_v4; 268 sin.sin_port = connp->conn_fport; 269 sin.sin_family = AF_INET; 270 271 if (lconnp->conn_recv_ancillary.crb_recvdstaddr) { 272 cmn_err(CE_NOTE, "ancillary"); 273 274 sin_t sind; 275 276 sind = sin_null; 277 sind.sin_addr.s_addr = connp->conn_laddr_v4; 278 sind.sin_port = connp->conn_lport; 279 sind.sin_family = AF_INET; 280 281 tpi_mp = mi_tpi_extconn_ind(NULL, 282 (char *)&sind, sizeof (sin_t), (char *)&dccp, 283 (t_scalar_t)sizeof (intptr_t), (char *)&sind, 284 sizeof (sin_t), (t_scalar_t)ldccp->dccp_conn_req_seqnum); 285 286 } else { 287 tpi_mp = mi_tpi_conn_ind(NULL, 288 (char *)&sin, sizeof (sin_t), 289 (char *)&dccp, (t_scalar_t)sizeof (intptr_t), 290 (t_scalar_t)ldccp->dccp_conn_req_seqnum); 291 } 292 293 /* XXX mss */ 294 295 return (tpi_mp); 296 } 297 298 static void 299 dccp_input_listener(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) 300 { 301 conn_t *lconnp = (conn_t *)arg; 302 conn_t *econnp; 303 dccp_t *listener = lconnp->conn_dccp; 304 dccp_t *eager; 305 dccp_stack_t *dccps = listener->dccp_dccps; 306 ip_stack_t *ipst = dccps->dccps_netstack->netstack_ip; 307 dccpha_t *dccpha; 308 squeue_t *new_sqp; 309 mblk_t *tpi_mp; 310 mblk_t *mp1; 311 uint_t ifindex = ira->ira_ruifindex; 312 uint_t ip_hdr_len; 313 uint_t type; 314 int error; 315 316 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener"); 317 318 ip_hdr_len = ira->ira_ip_hdr_length; 319 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len]; 320 type = (uint_t)dccpha->dha_type; 321 322 DTRACE_DCCP5(receive, mblk_t *, NULL, ip_xmit_attr_t *, lconnp->conn_ixa, 323 __dtrace_dccp_void_ip_t *, mp->b_rptr, dccp_t *, listener, 324 __dtrace_dccp_dccph_t *, dccpha); 325 326 dccp_check_input(lconnp, mp, ira); 327 328 if (type != DCCP_PKT_REQUEST) { 329 cmn_err(CE_NOTE, "--- not request pkt"); 330 if (type != DCCP_PKT_RESET) { 331 /* XXX send Reset(No Connection) */ 332 } 333 334 freemsg(mp); 335 return; 336 } 337 338 /* XXX memory pressure */ 339 340 /* XXX request defense */ 341 342 /* XXX number of connections per listener */ 343 344 ASSERT(ira->ira_sqp != NULL); 345 new_sqp = ira->ira_sqp; 346 347 econnp = (conn_t *)dccp_get_conn(arg2, dccps); 348 if (econnp == NULL) { 349 cmn_err(CE_NOTE, "econnp not found (eager)"); 350 goto error2; 351 } 352 353 ASSERT(econnp->conn_netstack == lconnp->conn_netstack); 354 econnp->conn_sqp = new_sqp; 355 econnp->conn_initial_sqp = new_sqp; 356 econnp->conn_ixa->ixa_sqp = new_sqp; 357 358 econnp->conn_fport = dccpha->dha_lport; 359 econnp->conn_lport = dccpha->dha_fport; 360 361 error = conn_inherit_parent(lconnp, econnp); 362 if (error != 0) { 363 cmn_err(CE_NOTE, "conn_inherit_parent failed"); 364 goto error3; 365 } 366 367 /* We already know the laddr of the new connection is ours */ 368 econnp->conn_ixa->ixa_src_generation = ipst->ips_src_generation; 369 370 ASSERT(OK_32PTR(mp->b_rptr)); 371 ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION || 372 IPH_HDR_VERSION(mp->b_rptr) == IPV6_VERSION); 373 374 if (lconnp->conn_family == AF_INET) { 375 ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION); 376 tpi_mp = dccp_conn_create_v4(lconnp, econnp, mp, ira); 377 } else { 378 tpi_mp = dccp_conn_create_v6(lconnp, econnp, mp, ira); 379 } 380 381 if (tpi_mp == NULL) { 382 cmn_err(CE_NOTE, "tpi_mo == NULL"); 383 goto error3; 384 } 385 386 eager = econnp->conn_dccp; 387 SOCK_CONNID_INIT(eager->dccp_connid); 388 389 dccp_init_values(eager, listener); 390 391 ASSERT((econnp->conn_ixa->ixa_flags & 392 (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE | 393 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO)) == 394 (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE | 395 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO)); 396 397 if (!(ira->ira_flags & IRAF_IS_IPV4) && econnp->conn_bound_if == 0) { 398 if (IN6_IS_ADDR_LINKSCOPE(&econnp->conn_faddr_v6) || 399 IN6_IS_ADDR_LINKSCOPE(&econnp->conn_laddr_v6)) { 400 econnp->conn_incoming_ifindex = ifindex; 401 econnp->conn_ixa->ixa_flags |= IXAF_SCOPEID_SET; 402 econnp->conn_ixa->ixa_scopeid = ifindex; 403 } 404 } 405 406 if (ira->ira_cred != NULL) { 407 mblk_setcred(tpi_mp, ira->ira_cred, ira->ira_cpid); 408 } 409 410 if (IPCL_IS_NONSTR(lconnp)) { 411 econnp->conn_flags |= IPCL_NONSTR; 412 } 413 414 /* XXX dccps is right? */ 415 dccp_bind_hash_insert(&dccps->dccps_bind_fanout[ 416 DCCP_BIND_HASH(econnp->conn_lport, dccps->dccps_bind_fanout_size)], 417 eager, 0); 418 419 /* XXX CLUSTER */ 420 421 SOCK_CONNID_BUMP(eager->dccp_connid); 422 423 error = dccp_set_destination(eager); 424 if (error != 0) { 425 cmn_err(CE_NOTE, "dccp_set_destination failed."); 426 dccp_bind_hash_remove(eager); 427 goto error3; 428 } 429 430 /* Process all DCCP options */ 431 dccp_process_options(eager, dccpha); 432 433 /* Eager lock */ 434 CONN_INC_REF(lconnp); 435 436 /* Set tcp_listener before adding it to tcp_conn_fanout */ 437 eager->dccp_listener = listener; 438 eager->dccp_saved_listener = listener; 439 440 eager->dccp_conn_req_seqnum = listener->dccp_conn_req_seqnum; 441 if (++listener->dccp_conn_req_seqnum == -1) { 442 /* 443 * -1 is "special" and defined in TPI as something 444 * that should never be used in T_CONN_IND 445 */ 446 ++listener->dccp_conn_req_seqnum; 447 } 448 449 /* XXX SYN DEFENSE */ 450 451 eager->dccp_state = DCCPS_RESPOND; 452 DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *, 453 econnp->conn_ixa, void, NULL, dccp_t *, eager, void, NULL, 454 int32_t, DCCPS_LISTEN); 455 456 /* ISS was set in set_destionation */ 457 eager->dccp_gar = eager->dccp_iss; 458 459 mp1 = dccp_generate_response(econnp, mp); 460 if (mp1 == NULL) { 461 cmn_err(CE_NOTE, "dccp_generate_packet failed"); 462 /* 463 * Increment the ref count as we are going to 464 * enqueueing an mp in squeue 465 */ 466 CONN_INC_REF(econnp); 467 goto error; 468 } 469 470 CONN_INC_REF(econnp); 471 472 error = ipcl_conn_insert(econnp); 473 if (error != 0) { 474 cmn_err(CE_NOTE, "ipcl_conn_insert(econnp) failed"); 475 goto error; 476 } 477 478 ASSERT(econnp->conn_ixa->ixa_notify_cookie == econnp->conn_dccp); 479 freemsg(mp); 480 481 /* 482 * Send the RESPONSE. Use the right squeue so that conn_ixa is 483 * only used by one thread at a time. 484 */ 485 if (econnp->conn_sqp == lconnp->conn_sqp) { 486 DTRACE_DCCP5(send, mblk_t *, NULL, ip_xmit_attr_t *, 487 econnp->conn_ixa, __dtrace_dccp_void_ip_t *, mp1->b_rptr, 488 dccp_t *, eager, __dtrace_dccp_dccph_t *, 489 &mp1->b_rptr[econnp->conn_ixa->ixa_ip_hdr_length]); 490 (void) conn_ip_output(mp1, econnp->conn_ixa); 491 CONN_DEC_REF(econnp); 492 } else { 493 SQUEUE_ENTER_ONE(econnp->conn_sqp, mp1, dccp_send_synack, 494 econnp, NULL, SQ_PROCESS, SQTAG_DCCP_SEND_RESPONSE); 495 } 496 497 return; 498 error: 499 freemsg(mp1); 500 error2: 501 CONN_DEC_REF(econnp); 502 error3: 503 freemsg(mp); 504 } 505 506 void 507 dccp_input_listener_unbound(void *arg, mblk_t *mp, void *arg2, 508 ip_recv_attr_t *ira) 509 { 510 conn_t *connp = (conn_t *)arg; 511 squeue_t *sqp = (squeue_t *)arg2; 512 squeue_t *new_sqp; 513 uint32_t conn_flags; 514 515 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener_unbound"); 516 517 ASSERT(ira->ira_sqp != NULL); 518 new_sqp = ira->ira_sqp; 519 520 if (connp->conn_fanout == NULL) { 521 goto done; 522 } 523 524 /* 525 * Bind to correct squeue. 526 */ 527 if (!(connp->conn_flags & IPCL_FULLY_BOUND)) { 528 cmn_err(CE_NOTE, "not fully bound"); 529 530 mutex_enter(&connp->conn_fanout->connf_lock); 531 mutex_enter(&connp->conn_lock); 532 533 if (connp->conn_ref != 4 || 534 connp->conn_dccp->dccp_state != DCCPS_LISTEN) { 535 mutex_exit(&connp->conn_lock); 536 mutex_exit(&connp->conn_fanout->connf_lock); 537 goto done; 538 } 539 540 if (connp->conn_sqp != new_sqp) { 541 while (connp->conn_sqp != new_sqp) { 542 (void) casptr(&connp->conn_sqp, sqp, new_sqp); 543 } 544 connp->conn_ixa->ixa_sqp = new_sqp; 545 } 546 547 do { 548 conn_flags = connp->conn_flags; 549 conn_flags |= IPCL_FULLY_BOUND; 550 (void) cas32(&connp->conn_flags, connp->conn_flags, 551 conn_flags); 552 } while (!(connp->conn_flags & IPCL_FULLY_BOUND)); 553 554 mutex_exit(&connp->conn_lock); 555 mutex_exit(&connp->conn_fanout->connf_lock); 556 557 connp->conn_recv = dccp_input_listener; 558 } 559 560 done: 561 if (connp->conn_sqp != sqp) { 562 CONN_INC_REF(connp); 563 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, connp->conn_recv, connp, 564 ira, SQ_FILL, SQTAG_DCCP_CONN_REQ_UNBOUND); 565 } else { 566 dccp_input_listener(connp, mp, sqp, ira); 567 } 568 } 569 570 boolean_t 571 dccp_verifyicmp(conn_t *connp, void *arg2, icmph_t *icmph, icmp6_t *icmp6, 572 ip_recv_attr_t *ira) 573 { 574 cmn_err(CE_NOTE, "dccp_input.c: dccp_verifyicmp"); 575 576 return (B_TRUE); 577 } 578 579 /* 580 * Basic sanity checks on all input packets. 581 */ 582 static int 583 dccp_check_input(conn_t *connp, mblk_t *mp, ip_recv_attr_t *ira) 584 { 585 dccp_t *dccp = connp->conn_dccp; 586 dccpha_t *dccpha; 587 uint32_t size; 588 uint32_t pkt_size; 589 uint_t ip_hdr_len = ira->ira_ip_hdr_length; 590 591 cmn_err(CE_NOTE, "dccp_input.c: dccp_check_input"); 592 593 size = msgdsize(mp) - (ip_hdr_len); 594 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len]; 595 pkt_size = dccpha->dha_offset * 4; 596 597 /* Is packet shorter then 12 bytes? */ 598 if (size < DCCP_MIN_HEADER_LENGTH) { 599 return (0); 600 } 601 602 /* Data offset is greater then the packet itself */ 603 if (pkt_size > size) { 604 return (0); 605 } 606 607 /* Check if known packet type */ 608 if (dccpha->dha_type > DCCP_PKT_SYNCACK) { 609 return (0); 610 } 611 612 /* 613 * Check data offset for this packet type and 614 * Data, Ack, or DataAck and P.X == 0 615 */ 616 if (dccpha->dha_x == 0) { 617 switch (dccpha->dha_type) { 618 case DCCP_PKT_DATA: 619 if (size < 12 || pkt_size < 12) 620 return (0); 621 break; 622 case DCCP_PKT_ACK: 623 case DCCP_PKT_DATAACK: 624 if (size < 16 || pkt_size < 16) 625 return (0); 626 break; 627 default: 628 return (0); 629 } 630 } else { 631 switch (dccpha->dha_type) { 632 case DCCP_PKT_REQUEST: 633 if (size < 20 || pkt_size < 20) 634 return (0); 635 break; 636 case DCCP_PKT_RESPONSE: 637 case DCCP_PKT_RESET: 638 if (size < 28 || pkt_size < 28) 639 return (0); 640 break; 641 case DCCP_PKT_DATA: 642 if (size < 16 || pkt_size < 16) 643 return (0); 644 break; 645 case DCCP_PKT_ACK: 646 case DCCP_PKT_DATAACK: 647 case DCCP_PKT_CLOSEREQ: 648 case DCCP_PKT_CLOSE: 649 case DCCP_PKT_SYNC: 650 case DCCP_PKT_SYNCACK: 651 if (size < 24 || pkt_size < 24) 652 return (0); 653 break; 654 default: 655 return (0); 656 } 657 } 658 659 return (1); 660 } 661 662 /* 663 * After a request-response-ack all packets end up here. 664 */ 665 void 666 dccp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) 667 { 668 conn_t *connp = (conn_t *)arg; 669 squeue_t *sqp = (squeue_t *)arg2; 670 dccp_t *dccp = connp->conn_dccp; 671 dccp_stack_t *dccps = dccp->dccp_dccps; 672 dccpha_t *dccpha; 673 dccpha_ack_t *dccpha_ack; 674 dccpha_ext_t *dccpha_ext; 675 mblk_t *mp1; 676 uint64_t seq_seq; 677 uint64_t seq_ack; 678 uchar_t *iphdr; 679 uchar_t *rptr; 680 sock_upcalls_t *sockupcalls; 681 ip_pkt_t ipp; 682 uint_t ip_hdr_len; 683 uint_t len; 684 int seg_len; 685 int pkt_len; 686 int hdr_length; 687 688 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_data"); 689 690 ASSERT(DB_TYPE(mp) == M_DATA); 691 ASSERT(mp->b_next == NULL); 692 693 iphdr = mp->b_rptr; 694 rptr = mp->b_rptr; 695 ASSERT(OK_32PTR(rptr)); 696 697 /* Check basic packet characteristics */ 698 if (dccp_check_input(connp, mp, ira) == 0) { 699 cmn_err(CE_NOTE, "reject packet"); 700 return; 701 } 702 703 ip_hdr_len = ira->ira_ip_hdr_length; 704 if (connp->conn_recv_ancillary.crb_all != 0) { 705 /* 706 * Record packet information in the ip_pkt_t 707 */ 708 ipp.ipp_fields = 0; 709 if (ira->ira_flags & IRAF_IS_IPV4) { 710 (void) ip_find_hdr_v4((ipha_t *)rptr, &ipp, 711 B_FALSE); 712 } else { 713 uint8_t nexthdrp; 714 715 /* 716 * IPv6 packets can only be received by applications 717 * that are prepared to receive IPv6 addresses. 718 * The IP fanout must ensure this. 719 */ 720 ASSERT(connp->conn_family == AF_INET6); 721 722 (void) ip_find_hdr_v6(mp, (ip6_t *)rptr, B_TRUE, &ipp, 723 &nexthdrp); 724 ASSERT(nexthdrp == IPPROTO_DCCP); 725 726 /* Could have caused a pullup? */ 727 iphdr = mp->b_rptr; 728 rptr = mp->b_rptr; 729 } 730 } 731 732 len = ip_hdr_len; 733 dccpha = (dccpha_t *)&rptr[len]; 734 735 ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX); 736 seg_len = (int)(mp->b_wptr - rptr) - 737 (ip_hdr_len + DCCP_HDR_LENGTH(dccpha)); 738 if ((mp1 = mp->b_cont) != NULL && mp1->b_datap->db_type == M_DATA) { 739 do { 740 ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <= 741 (uintptr_t)INT_MAX); 742 seg_len += (int)(mp1->b_wptr - mp1->b_rptr); 743 } while ((mp1 = mp1->b_cont) != NULL && 744 mp1->b_datap->db_type == M_DATA); 745 } 746 747 DTRACE_DCCP5(receive, mblk_t *, NULL, ip_xmit_attr_t *, connp->conn_ixa, 748 __dtrace_dccp_void_ip_t *, iphdr, dccp_t *, dccp, 749 __dtrace_dccp_dccph_t *, dccpha); 750 751 BUMP_LOCAL(dccp->dccp_ibsegs); 752 DTRACE_PROBE2(dccp__trace__recv, mblk_t *, mp, dccp_t *, dccp); 753 754 sockupcalls = connp->conn_upcalls; 755 756 len += sizeof (dccpha_t); 757 dccpha_ext = (dccpha_ext_t *)&rptr[len]; 758 759 /* XXX length checks */ 760 if (dccpha->dha_x == 1) { 761 seq_seq = ntohs(dccpha->dha_seq); 762 seq_seq = seq_seq << 32; 763 seq_seq |= ntohl(dccpha_ext->dha_ext_seq); 764 } else { 765 /* XXX */ 766 } 767 768 dccp->dccp_gsr = seq_seq; 769 770 switch (dccp->dccp_state) { 771 case DCCPS_REQUEST: 772 cmn_err(CE_NOTE, "DCCPS_REQUEST"); 773 break; 774 case DCCPS_RESPOND: 775 cmn_err(CE_NOTE, "DCCPS_RESPOND"); 776 break; 777 case DCCPS_PARTOPEN: 778 cmn_err(CE_NOTE, "DCCPS_PARTOPEN"); 779 break; 780 case DCCPS_LISTEN: 781 cmn_err(CE_NOTE, "DCCPS_LISTEN"); 782 break; 783 case DCCPS_BOUND: 784 cmn_err(CE_NOTE, "DCCPS_BOUND"); 785 break; 786 case DCCPS_OPEN: 787 cmn_err(CE_NOTE, "DCCPS_OPEN"); 788 break; 789 default: 790 cmn_err(CE_NOTE, "Unknow state"); 791 break; 792 } 793 794 if (dccp->dccp_state == DCCPS_RESPOND) { 795 dccp->dccp_state = DCCPS_OPEN; 796 //dccp->dccp_osr = DCCP_SEQNO_GET(mp); 797 798 if (dccp->dccp_active_open) { 799 cmn_err(CE_NOTE, "dccp_active_open"); 800 if (!dccp_conn_con(dccp, iphdr, mp, NULL, ira)) { 801 cmn_err(CE_NOTE, "dccp_conn_con failed"); 802 freemsg(mp); 803 dccp->dccp_state = DCCPS_RESPOND; 804 return; 805 } 806 807 DTRACE_DCCP5(connect__established, mblk_t *, NULL, 808 ip_xmit_attr_t *, connp->conn_ixa, void_ip_t *, 809 iphdr, dccp_t *, dccp, dccph_t *, dccpha); 810 } else if (IPCL_IS_NONSTR(connp)) { 811 /* 812 * Passive open socket 813 */ 814 cmn_err(CE_NOTE, "nonstr"); 815 816 CONN_INC_REF(connp); 817 818 if (!dccp_newconn_notify(dccp, ira)) { 819 cmn_err(CE_NOTE, "dccp_newconn_notify failed"); 820 dccp->dccp_state = DCCPS_RESPOND; 821 freemsg(mp); 822 823 CONN_DEC_REF(connp); 824 return; 825 } 826 827 /* 828 * dccp_newconn_notify() changes conn_upcalls. 829 */ 830 if (connp->conn_upcalls != NULL) { 831 sockupcalls = connp->conn_upcalls; 832 } 833 834 DTRACE_DCCP5(accept__established, mlbk_t *, NULL, 835 ip_xmit_attr_t *, connp->conn_ixa, void_ip_t *, 836 iphdr, dccp_t *, dccp, dccph_t *, dccpha); 837 } else { 838 cmn_err(CE_NOTE, "str stream"); 839 dccp_t *listener = dccp->dccp_listener; 840 841 ASSERT(mp != NULL); 842 CONN_INC_REF(connp); 843 } 844 } 845 846 switch (dccpha->dha_type) { 847 case DCCP_PKT_REQUEST: 848 cmn_err(CE_NOTE, "DCCP_REQUEST"); 849 break; 850 case DCCP_PKT_RESPONSE: 851 cmn_err(CE_NOTE, "DCCP_RESPONSE"); 852 break; 853 case DCCP_PKT_DATA: 854 cmn_err(CE_NOTE, "DCCP_DATA"); 855 break; 856 case DCCP_PKT_ACK: 857 cmn_err(CE_NOTE, "DCCP_PKT_ACK"); 858 break; 859 case DCCP_PKT_DATAACK: 860 cmn_err(CE_NOTE, "DCCP_DATAACK"); 861 break; 862 case DCCP_PKT_CLOSEREQ: 863 cmn_err(CE_NOTE, "DCCP_CLOSEREQ"); 864 break; 865 case DCCP_PKT_CLOSE: 866 cmn_err(CE_NOTE, "DCCP_CLOSE"); 867 break; 868 case DCCP_PKT_RESET: 869 cmn_err(CE_NOTE, "DCCP_RESET"); 870 break; 871 case DCCP_PKT_SYNC: 872 cmn_err(CE_NOTE, "DCCP_SYNC"); 873 break; 874 case DCCP_PKT_SYNCACK: 875 cmn_err(CE_NOTE, "DCCP_SYNCACK"); 876 break; 877 default: 878 break; 879 } 880 881 switch (dccpha->dha_type) { 882 case DCCP_PKT_ACK: 883 dccp->dccp_state = DCCPS_OPEN; 884 return; 885 case DCCP_PKT_DATAACK: 886 dccp->dccp_state = DCCPS_OPEN; 887 break; 888 case DCCP_PKT_CLOSE: { 889 mblk_t *reset_mp; 890 891 reset_mp = dccp_generate_reset(connp); 892 dccp_send_data(dccp, reset_mp); 893 dccp->dccp_state = DCCPS_CLOSED; 894 return; 895 } 896 default: 897 break; 898 } 899 900 hdr_length = ira->ira_ip_hdr_length; 901 hdr_length += DCCP_HDR_LENGTH(dccpha); 902 pkt_len = ira->ira_pktlen; 903 904 mp->b_wptr = rptr + pkt_len; 905 mp->b_rptr = (uchar_t *)&mp->b_rptr[hdr_length]; 906 pkt_len -= hdr_length; 907 908 if (IPCL_IS_NONSTR(connp)) { 909 /* 910 * Non-STREAMS socket. 911 */ 912 boolean_t push; 913 int error; 914 915 if ((*sockupcalls->su_recv)(connp->conn_upper_handle, 916 mp, pkt_len, 0, &error, NULL) <= 0) { 917 cmn_err(CE_NOTE, "su_recv failed"); 918 ASSERT(error != EOPNOTSUPP); 919 } 920 } else if (dccp->dccp_listener != NULL) { 921 // dccp_recv_enqueue(dccp, mp, seq_len, ira->ira_cred); 922 } else { 923 /* 924 * Active-STREAMS socket. 925 */ 926 } 927 }