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 dccpha_ext_t *dccpha_ext; 309 squeue_t *new_sqp; 310 mblk_t *tpi_mp; 311 mblk_t *mp1; 312 uint64_t seq; 313 uint_t ifindex = ira->ira_ruifindex; 314 uint_t ip_hdr_len; 315 uint_t type; 316 int error; 317 318 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener"); 319 320 321 DTRACE_DCCP5(receive, mblk_t *, NULL, ip_xmit_attr_t *, lconnp->conn_ixa, 322 __dtrace_dccp_void_ip_t *, mp->b_rptr, dccp_t *, listener, 323 __dtrace_dccp_dccph_t *, dccpha); 324 325 /* Basic checks on packet */ 326 if (dccp_check_input(lconnp, mp, ira) == 0) { 327 cmn_err(CE_NOTE, "dccp_check_input failed."); 328 freemsg(mp); 329 return; 330 } 331 332 ip_hdr_len = ira->ira_ip_hdr_length; 333 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len]; 334 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)]; 335 type = (uint_t)dccpha->dha_type; 336 337 if (type != DCCP_PKT_REQUEST) { 338 if (type != DCCP_PKT_RESET) { 339 listener->dccp_reset_code = DCCP_RESET_NO_CONNECTION; 340 dccp_xmit_listeners_reset(mp, ira, ipst, lconnp); 341 } 342 343 freemsg(mp); 344 return; 345 } 346 347 /* XXX memory pressure */ 348 349 /* XXX request defense */ 350 351 /* XXX number of connections per listener */ 352 353 ASSERT(ira->ira_sqp != NULL); 354 new_sqp = ira->ira_sqp; 355 356 econnp = (conn_t *)dccp_get_conn(arg2, dccps); 357 if (econnp == NULL) { 358 cmn_err(CE_NOTE, "econnp not found (eager)"); 359 goto error2; 360 } 361 362 ASSERT(econnp->conn_netstack == lconnp->conn_netstack); 363 econnp->conn_sqp = new_sqp; 364 econnp->conn_initial_sqp = new_sqp; 365 econnp->conn_ixa->ixa_sqp = new_sqp; 366 367 econnp->conn_fport = dccpha->dha_lport; 368 econnp->conn_lport = dccpha->dha_fport; 369 370 error = conn_inherit_parent(lconnp, econnp); 371 if (error != 0) { 372 cmn_err(CE_NOTE, "conn_inherit_parent failed"); 373 goto error3; 374 } 375 376 /* We already know the laddr of the new connection is ours */ 377 econnp->conn_ixa->ixa_src_generation = ipst->ips_src_generation; 378 379 ASSERT(OK_32PTR(mp->b_rptr)); 380 ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION || 381 IPH_HDR_VERSION(mp->b_rptr) == IPV6_VERSION); 382 383 if (lconnp->conn_family == AF_INET) { 384 ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION); 385 tpi_mp = dccp_conn_create_v4(lconnp, econnp, mp, ira); 386 } else { 387 tpi_mp = dccp_conn_create_v6(lconnp, econnp, mp, ira); 388 } 389 390 if (tpi_mp == NULL) { 391 cmn_err(CE_NOTE, "tpi_mo == NULL"); 392 goto error3; 393 } 394 395 eager = econnp->conn_dccp; 396 SOCK_CONNID_INIT(eager->dccp_connid); 397 398 dccp_init_values(eager, listener); 399 400 ASSERT((econnp->conn_ixa->ixa_flags & 401 (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE | 402 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO)) == 403 (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE | 404 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO)); 405 406 if (!(ira->ira_flags & IRAF_IS_IPV4) && econnp->conn_bound_if == 0) { 407 if (IN6_IS_ADDR_LINKSCOPE(&econnp->conn_faddr_v6) || 408 IN6_IS_ADDR_LINKSCOPE(&econnp->conn_laddr_v6)) { 409 econnp->conn_incoming_ifindex = ifindex; 410 econnp->conn_ixa->ixa_flags |= IXAF_SCOPEID_SET; 411 econnp->conn_ixa->ixa_scopeid = ifindex; 412 } 413 } 414 415 if (ira->ira_cred != NULL) { 416 mblk_setcred(tpi_mp, ira->ira_cred, ira->ira_cpid); 417 } 418 419 if (IPCL_IS_NONSTR(lconnp)) { 420 econnp->conn_flags |= IPCL_NONSTR; 421 } 422 423 /* XXX dccps is right? */ 424 dccp_bind_hash_insert(&dccps->dccps_bind_fanout[ 425 DCCP_BIND_HASH(econnp->conn_lport, dccps->dccps_bind_fanout_size)], 426 eager, 0); 427 428 /* XXX CLUSTER */ 429 430 SOCK_CONNID_BUMP(eager->dccp_connid); 431 432 error = dccp_set_destination(eager); 433 if (error != 0) { 434 cmn_err(CE_NOTE, "dccp_set_destination failed."); 435 DCCPS_BUMP_MIB(dccps, dccpAttemptFails); 436 /* Undo the bind_hash_insert */ 437 dccp_bind_hash_remove(eager); 438 goto error3; 439 } 440 441 /* Eager lock */ 442 CONN_INC_REF(lconnp); 443 444 /* Set tcp_listener before adding it to tcp_conn_fanout */ 445 eager->dccp_listener = listener; 446 eager->dccp_saved_listener = listener; 447 448 eager->dccp_conn_req_seqnum = listener->dccp_conn_req_seqnum; 449 if (++listener->dccp_conn_req_seqnum == -1) { 450 /* 451 * -1 is "special" and defined in TPI as something 452 * that should never be used in T_CONN_IND 453 */ 454 ++listener->dccp_conn_req_seqnum; 455 } 456 457 /* XXX SYN DEFENSE */ 458 459 seq = ntohs(dccpha->dha_seq); 460 seq = seq << 32; 461 seq |= ntohl(dccpha_ext->dha_ext_seq); 462 463 /* ISS was set in set_destination */ 464 eager->dccp_gar = eager->dccp_iss; 465 eager->dccp_gsr = seq; 466 eager->dccp_osr = seq; 467 468 /* Process all DCCP options */ 469 error = dccp_process_options(eager, dccpha); 470 if (error != 0) { 471 cmn_err(CE_NOTE, "dccp_process_options failed."); 472 mp1 = dccp_generate_reset(econnp); 473 eager->dccp_state = DCCPS_CLOSED; 474 if (mp1 == NULL) { 475 cmn_err(CE_NOTE, "dccp_generate_reset failed."); 476 goto error; 477 } 478 479 ip_xmit_attr_t *ixa = econnp->conn_ixa; 480 481 ixa->ixa_pktlen = msgdsize(mp1); 482 (void) conn_ip_output(mp1, ixa); 483 484 return; 485 } 486 487 eager->dccp_state = DCCPS_RESPOND; 488 DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *, 489 econnp->conn_ixa, void, NULL, dccp_t *, eager, void, NULL, 490 int32_t, DCCPS_LISTEN); 491 492 mp1 = dccp_generate_response(econnp, mp); 493 if (mp1 == NULL) { 494 cmn_err(CE_NOTE, "dccp_generate_packet failed"); 495 /* 496 * Increment the ref count as we are going to 497 * enqueueing an mp in squeue 498 */ 499 CONN_INC_REF(econnp); 500 goto error; 501 } 502 503 CONN_INC_REF(econnp); 504 505 error = ipcl_conn_insert(econnp); 506 if (error != 0) { 507 cmn_err(CE_NOTE, "ipcl_conn_insert(econnp) failed"); 508 goto error; 509 } 510 511 ASSERT(econnp->conn_ixa->ixa_notify_cookie == econnp->conn_dccp); 512 freemsg(mp); 513 514 /* 515 * Send the RESPONSE. Use the right squeue so that conn_ixa is 516 * only used by one thread at a time. 517 */ 518 if (econnp->conn_sqp == lconnp->conn_sqp) { 519 DTRACE_DCCP5(send, mblk_t *, NULL, ip_xmit_attr_t *, 520 econnp->conn_ixa, __dtrace_dccp_void_ip_t *, mp1->b_rptr, 521 dccp_t *, eager, __dtrace_dccp_dccph_t *, 522 &mp1->b_rptr[econnp->conn_ixa->ixa_ip_hdr_length]); 523 (void) conn_ip_output(mp1, econnp->conn_ixa); 524 CONN_DEC_REF(econnp); 525 } else { 526 SQUEUE_ENTER_ONE(econnp->conn_sqp, mp1, dccp_send_synack, 527 econnp, NULL, SQ_PROCESS, SQTAG_DCCP_SEND_RESPONSE); 528 } 529 530 return; 531 error: 532 freemsg(mp1); 533 error2: 534 CONN_DEC_REF(econnp); 535 error3: 536 freemsg(mp); 537 } 538 539 void 540 dccp_input_listener_unbound(void *arg, mblk_t *mp, void *arg2, 541 ip_recv_attr_t *ira) 542 { 543 conn_t *connp = (conn_t *)arg; 544 squeue_t *sqp = (squeue_t *)arg2; 545 squeue_t *new_sqp; 546 uint32_t conn_flags; 547 548 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener_unbound"); 549 550 ASSERT(ira->ira_sqp != NULL); 551 new_sqp = ira->ira_sqp; 552 553 if (connp->conn_fanout == NULL) { 554 goto done; 555 } 556 557 /* 558 * Bind to correct squeue. 559 */ 560 if (!(connp->conn_flags & IPCL_FULLY_BOUND)) { 561 cmn_err(CE_NOTE, "not fully bound"); 562 563 mutex_enter(&connp->conn_fanout->connf_lock); 564 mutex_enter(&connp->conn_lock); 565 566 if (connp->conn_ref != 4 || 567 connp->conn_dccp->dccp_state != DCCPS_LISTEN) { 568 mutex_exit(&connp->conn_lock); 569 mutex_exit(&connp->conn_fanout->connf_lock); 570 goto done; 571 } 572 573 if (connp->conn_sqp != new_sqp) { 574 while (connp->conn_sqp != new_sqp) { 575 (void) casptr(&connp->conn_sqp, sqp, new_sqp); 576 } 577 connp->conn_ixa->ixa_sqp = new_sqp; 578 } 579 580 do { 581 conn_flags = connp->conn_flags; 582 conn_flags |= IPCL_FULLY_BOUND; 583 (void) cas32(&connp->conn_flags, connp->conn_flags, 584 conn_flags); 585 } while (!(connp->conn_flags & IPCL_FULLY_BOUND)); 586 587 mutex_exit(&connp->conn_lock); 588 mutex_exit(&connp->conn_fanout->connf_lock); 589 590 connp->conn_recv = dccp_input_listener; 591 } 592 593 done: 594 if (connp->conn_sqp != sqp) { 595 CONN_INC_REF(connp); 596 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, connp->conn_recv, connp, 597 ira, SQ_FILL, SQTAG_DCCP_CONN_REQ_UNBOUND); 598 } else { 599 dccp_input_listener(connp, mp, sqp, ira); 600 } 601 } 602 603 boolean_t 604 dccp_verifyicmp(conn_t *connp, void *arg2, icmph_t *icmph, icmp6_t *icmp6, 605 ip_recv_attr_t *ira) 606 { 607 cmn_err(CE_NOTE, "dccp_input.c: dccp_verifyicmp"); 608 609 return (B_TRUE); 610 } 611 612 /* 613 * Basic sanity checks on all input packets. 614 */ 615 static int 616 dccp_check_input(conn_t *connp, mblk_t *mp, ip_recv_attr_t *ira) 617 { 618 dccp_t *dccp = connp->conn_dccp; 619 dccpha_t *dccpha; 620 uint32_t size; 621 uint32_t offset_size; 622 uint_t ip_hdr_len = ira->ira_ip_hdr_length; 623 624 cmn_err(CE_NOTE, "dccp_input.c: dccp_check_input"); 625 626 size = msgdsize(mp) - (ip_hdr_len); 627 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len]; 628 offset_size = dccpha->dha_offset * 4; 629 630 cmn_err(CE_NOTE, "size: %d", size); 631 cmn_err(CE_NOTE, "offset_size: %d", offset_size); 632 633 /* Is packet shorter then 12 bytes? */ 634 if (size < DCCP_MIN_HEADER_LENGTH) { 635 cmn_err(CE_NOTE, "header < 12"); 636 return (0); 637 } 638 639 /* Data offset is greater then the packet itself */ 640 if (offset_size > size) { 641 cmn_err(CE_NOTE, "offset > size"); 642 return (0); 643 } 644 645 /* Check if known packet type */ 646 if (dccpha->dha_type > DCCP_PKT_SYNCACK) { 647 cmn_err(CE_NOTE, "type unknown"); 648 return (0); 649 } 650 651 /* 652 * Check data offset for this packet type and 653 * Data, Ack, or DataAck and P.X == 0 654 */ 655 if (dccpha->dha_x == 0) { 656 switch (dccpha->dha_type) { 657 case DCCP_PKT_DATA: 658 if (size < 12 || offset_size < 12) 659 return (0); 660 break; 661 case DCCP_PKT_ACK: 662 case DCCP_PKT_DATAACK: 663 if (size < 16 || offset_size < 16) 664 return (0); 665 break; 666 default: 667 return (0); 668 } 669 } else { 670 switch (dccpha->dha_type) { 671 case DCCP_PKT_REQUEST: 672 if (size < 20 || offset_size < 20) 673 return (0); 674 break; 675 case DCCP_PKT_RESPONSE: 676 case DCCP_PKT_RESET: 677 if (size < 28 || offset_size < 28) 678 return (0); 679 break; 680 case DCCP_PKT_DATA: 681 if (size < 16 || offset_size < 16) 682 return (0); 683 break; 684 case DCCP_PKT_ACK: 685 case DCCP_PKT_DATAACK: 686 case DCCP_PKT_CLOSEREQ: 687 case DCCP_PKT_CLOSE: 688 case DCCP_PKT_SYNC: 689 case DCCP_PKT_SYNCACK: 690 if (size < 24 || offset_size < 24) 691 return (0); 692 break; 693 default: 694 return (0); 695 } 696 } 697 698 /* Checksum coverage check */ 699 if (dccpha->dha_cscov != 0 && ((dccpha->dha_offset + 700 dccpha->dha_cscov - 1) * 4) > size) { 701 cmn_err(CE_NOTE, "cscov too large"); 702 return (0); 703 } 704 705 return (1); 706 } 707 708 /* 709 * After a request-response-ack all packets end up here. 710 */ 711 void 712 dccp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) 713 { 714 conn_t *connp = (conn_t *)arg; 715 squeue_t *sqp = (squeue_t *)arg2; 716 dccp_t *dccp = connp->conn_dccp; 717 dccp_stack_t *dccps = dccp->dccp_dccps; 718 dccpha_t *dccpha; 719 dccpha_ack_t *dccpha_ack; 720 dccpha_ext_t *dccpha_ext; 721 mblk_t *mp1; 722 uint64_t seq_seq; 723 uint64_t seq_ack; 724 uchar_t *iphdr; 725 uchar_t *rptr; 726 sock_upcalls_t *sockupcalls; 727 ip_pkt_t ipp; 728 uint_t ip_hdr_len; 729 uint_t len; 730 int seg_len; 731 int pkt_len; 732 int hdr_length; 733 int error; 734 735 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_data"); 736 737 ASSERT(DB_TYPE(mp) == M_DATA); 738 ASSERT(mp->b_next == NULL); 739 740 iphdr = mp->b_rptr; 741 rptr = mp->b_rptr; 742 ASSERT(OK_32PTR(rptr)); 743 744 /* Check basic characteristics */ 745 if (dccp_check_input(connp, mp, ira) == 0) { 746 cmn_err(CE_NOTE, "rejected packet"); 747 return; 748 } 749 750 ip_hdr_len = ira->ira_ip_hdr_length; 751 if (connp->conn_recv_ancillary.crb_all != 0) { 752 /* 753 * Record packet information in the ip_pkt_t 754 */ 755 ipp.ipp_fields = 0; 756 if (ira->ira_flags & IRAF_IS_IPV4) { 757 (void) ip_find_hdr_v4((ipha_t *)rptr, &ipp, 758 B_FALSE); 759 } else { 760 uint8_t nexthdrp; 761 762 /* 763 * IPv6 packets can only be received by applications 764 * that are prepared to receive IPv6 addresses. 765 * The IP fanout must ensure this. 766 */ 767 ASSERT(connp->conn_family == AF_INET6); 768 769 (void) ip_find_hdr_v6(mp, (ip6_t *)rptr, B_TRUE, &ipp, 770 &nexthdrp); 771 ASSERT(nexthdrp == IPPROTO_DCCP); 772 773 /* Could have caused a pullup? */ 774 iphdr = mp->b_rptr; 775 rptr = mp->b_rptr; 776 } 777 } 778 779 len = ip_hdr_len; 780 dccpha = (dccpha_t *)&rptr[len]; 781 782 ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX); 783 seg_len = (int)(mp->b_wptr - rptr) - 784 (ip_hdr_len + DCCP_HDR_LENGTH(dccpha)); 785 if ((mp1 = mp->b_cont) != NULL && mp1->b_datap->db_type == M_DATA) { 786 do { 787 ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <= 788 (uintptr_t)INT_MAX); 789 seg_len += (int)(mp1->b_wptr - mp1->b_rptr); 790 } while ((mp1 = mp1->b_cont) != NULL && 791 mp1->b_datap->db_type == M_DATA); 792 } 793 794 DTRACE_DCCP5(receive, mblk_t *, NULL, ip_xmit_attr_t *, connp->conn_ixa, 795 __dtrace_dccp_void_ip_t *, iphdr, dccp_t *, dccp, 796 __dtrace_dccp_dccph_t *, dccpha); 797 798 if (sqp != NULL) { 799 dccp->dccp_last_recv_time = LBOLT_FASTPATH; 800 } 801 802 BUMP_LOCAL(dccp->dccp_ibsegs); 803 DTRACE_PROBE2(dccp__trace__recv, mblk_t *, mp, dccp_t *, dccp); 804 805 sockupcalls = connp->conn_upcalls; 806 807 len += sizeof (dccpha_t); 808 dccpha_ext = (dccpha_ext_t *)&rptr[len]; 809 810 /* 811 * Sequence number. 812 */ 813 if (dccpha->dha_x == 1) { 814 seq_seq = ntohs(dccpha->dha_seq); 815 seq_seq = seq_seq << 32; 816 seq_seq |= ntohl(dccpha_ext->dha_ext_seq); 817 } else { 818 /* XXX */ 819 } 820 821 dccp->dccp_gsr = seq_seq; 822 823 /* 824 * Acknowledgement Number. 825 */ 826 if (dccpha->dha_type != DCCP_PKT_DATA) { 827 dccpha_ack = (dccpha_ack_t *)&rptr[ip_hdr_len + 828 sizeof (dccpha_t) + sizeof (dccpha_ext_t)]; 829 seq_ack = ntohs(dccpha_ack->dha_ack_high); 830 seq_ack = seq_ack << 32; 831 seq_ack |= ntohl(dccpha_ack->dha_ack_low); 832 833 dccp->dccp_gar = seq_ack; 834 } 835 836 837 switch (dccp->dccp_state) { 838 case DCCPS_REQUEST: 839 cmn_err(CE_NOTE, "DCCPS_REQUEST"); 840 break; 841 case DCCPS_RESPOND: 842 cmn_err(CE_NOTE, "DCCPS_RESPOND"); 843 break; 844 case DCCPS_PARTOPEN: 845 cmn_err(CE_NOTE, "DCCPS_PARTOPEN"); 846 break; 847 case DCCPS_LISTEN: 848 cmn_err(CE_NOTE, "DCCPS_LISTEN"); 849 break; 850 case DCCPS_BOUND: 851 cmn_err(CE_NOTE, "DCCPS_BOUND"); 852 break; 853 case DCCPS_OPEN: 854 cmn_err(CE_NOTE, "DCCPS_OPEN"); 855 break; 856 default: 857 cmn_err(CE_NOTE, "Unknow state"); 858 break; 859 } 860 861 /* 862 * Check for unexpected packet types. 863 */ 864 if ((dccp->dccp_active_open == B_FALSE && 865 (dccpha->dha_type == DCCP_PKT_RESPONSE || 866 dccpha->dha_type == DCCP_PKT_CLOSEREQ)) || 867 (dccp->dccp_state >= DCCPS_OPEN && 868 (dccpha->dha_type == DCCP_PACKET_REQUEST || 869 dccpha->dha_type == DCCP_PACKET_RESPONSE) && 870 seq_seq >= dccp->dccp_osr) || 871 (dccp->dccp_state == DCCPS_RESPOND && 872 dccpha->dha_type == DCCP_PACKET_DATA)) { 873 mblk_t *sync_mp; 874 875 sync_mp = dccp_generate_sync(connp); 876 if (sync_mp != NULL) 877 dccp_send_data(dccp, sync_mp); 878 return; 879 } 880 881 /* 882 * Process options. 883 */ 884 error = dccp_process_options(dccp, dccpha); 885 if (error != 0) { 886 mblk_t *reset_mp; 887 888 cmn_err(CE_NOTE, "dccp_process_options failed."); 889 890 reset_mp = dccp_generate_reset(connp); 891 dccp->dccp_state = DCCPS_CLOSED; 892 if (reset_mp != NULL) { 893 ip_xmit_attr_t *ixa = connp->conn_ixa; 894 895 ixa->ixa_pktlen = msgdsize(reset_mp); 896 (void) conn_ip_output(reset_mp, ixa); 897 } 898 899 return; 900 } 901 902 if (dccp->dccp_state == DCCPS_RESPOND) { 903 dccp->dccp_state = DCCPS_OPEN; 904 //dccp->dccp_osr = DCCP_SEQNO_GET(mp); 905 906 if (dccp->dccp_active_open) { 907 cmn_err(CE_NOTE, "dccp_active_open"); 908 if (!dccp_conn_con(dccp, iphdr, mp, NULL, ira)) { 909 cmn_err(CE_NOTE, "dccp_conn_con failed"); 910 freemsg(mp); 911 dccp->dccp_state = DCCPS_RESPOND; 912 return; 913 } 914 915 DTRACE_DCCP5(connect__established, mblk_t *, NULL, 916 ip_xmit_attr_t *, connp->conn_ixa, void_ip_t *, 917 iphdr, dccp_t *, dccp, dccph_t *, dccpha); 918 } else if (IPCL_IS_NONSTR(connp)) { 919 /* 920 * Passive open socket 921 */ 922 cmn_err(CE_NOTE, "nonstr"); 923 924 CONN_INC_REF(connp); 925 926 if (!dccp_newconn_notify(dccp, ira)) { 927 cmn_err(CE_NOTE, "dccp_newconn_notify failed"); 928 dccp->dccp_state = DCCPS_RESPOND; 929 freemsg(mp); 930 931 CONN_DEC_REF(connp); 932 return; 933 } 934 935 /* 936 * dccp_newconn_notify() changes conn_upcalls. 937 */ 938 if (connp->conn_upcalls != NULL) { 939 sockupcalls = connp->conn_upcalls; 940 } 941 942 DTRACE_DCCP5(accept__established, mlbk_t *, NULL, 943 ip_xmit_attr_t *, connp->conn_ixa, void_ip_t *, 944 iphdr, dccp_t *, dccp, dccph_t *, dccpha); 945 } else { 946 cmn_err(CE_NOTE, "str stream"); 947 dccp_t *listener = dccp->dccp_listener; 948 949 ASSERT(mp != NULL); 950 CONN_INC_REF(connp); 951 } 952 } 953 954 switch (dccpha->dha_type) { 955 case DCCP_PKT_REQUEST: 956 cmn_err(CE_NOTE, "DCCP_REQUEST"); 957 break; 958 case DCCP_PKT_RESPONSE: 959 cmn_err(CE_NOTE, "DCCP_RESPONSE"); 960 break; 961 case DCCP_PKT_DATA: 962 cmn_err(CE_NOTE, "DCCP_DATA"); 963 break; 964 case DCCP_PKT_ACK: 965 cmn_err(CE_NOTE, "DCCP_PKT_ACK"); 966 break; 967 case DCCP_PKT_DATAACK: 968 cmn_err(CE_NOTE, "DCCP_DATAACK"); 969 break; 970 case DCCP_PKT_CLOSEREQ: 971 cmn_err(CE_NOTE, "DCCP_CLOSEREQ"); 972 break; 973 case DCCP_PKT_CLOSE: 974 cmn_err(CE_NOTE, "DCCP_CLOSE"); 975 break; 976 case DCCP_PKT_RESET: 977 cmn_err(CE_NOTE, "DCCP_RESET"); 978 break; 979 case DCCP_PKT_SYNC: 980 cmn_err(CE_NOTE, "DCCP_SYNC"); 981 break; 982 case DCCP_PKT_SYNCACK: 983 cmn_err(CE_NOTE, "DCCP_SYNCACK"); 984 break; 985 default: 986 break; 987 } 988 989 switch (dccpha->dha_type) { 990 /* case DCCP_PKT_ACK: { */ 991 case DCCP_PKT_DATAACK: { 992 mblk_t *ack_mp; 993 994 ack_mp = dccp_generate_ack(connp); 995 if (ack_mp != NULL) 996 dccp_send_data(dccp, ack_mp); 997 998 dccp->dccp_state = DCCPS_OPEN; 999 return; 1000 } 1001 case DCCP_PKT_CLOSE: { 1002 mblk_t *reset_mp; 1003 1004 dccp->dccp_reset_code = DCCP_RESET_CLOSED; 1005 dccp->dccp_reset_data[0] = 0; 1006 dccp->dccp_reset_data[1] = 0; 1007 dccp->dccp_reset_data[2] = 0; 1008 reset_mp = dccp_generate_reset(connp); 1009 dccp_send_data(dccp, reset_mp); 1010 dccp->dccp_state = DCCPS_CLOSED; 1011 return; 1012 } 1013 default: 1014 break; 1015 } 1016 1017 hdr_length = ira->ira_ip_hdr_length; 1018 hdr_length += DCCP_HDR_LENGTH(dccpha); 1019 pkt_len = ira->ira_pktlen; 1020 1021 mp->b_wptr = rptr + pkt_len; 1022 mp->b_rptr = (uchar_t *)&mp->b_rptr[hdr_length]; 1023 pkt_len -= hdr_length; 1024 1025 if (IPCL_IS_NONSTR(connp)) { 1026 /* 1027 * Non-STREAMS socket. 1028 */ 1029 boolean_t push; 1030 int error; 1031 1032 if ((*sockupcalls->su_recv)(connp->conn_upper_handle, 1033 mp, pkt_len, 0, &error, NULL) <= 0) { 1034 cmn_err(CE_NOTE, "su_recv failed"); 1035 ASSERT(error != EOPNOTSUPP); 1036 } 1037 } else if (dccp->dccp_listener != NULL) { 1038 // dccp_recv_enqueue(dccp, mp, seq_len, ira->ira_cred); 1039 } else { 1040 /* 1041 * Active-STREAMS socket. 1042 */ 1043 } 1044 }