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 }