1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright 2012 David Hoeppner.  All rights reserved.
  29  */
  30 
  31 /*
  32  * This file contains function related to the socket interface.
  33  */
  34 
  35 #include <sys/types.h>
  36 #include <sys/strlog.h>
  37 #include <sys/policy.h>
  38 #include <sys/sockio.h>
  39 #include <sys/strsubr.h>
  40 #include <sys/strsun.h>
  41 #define _SUN_TPI_VERSION 2
  42 #include <sys/tihdr.h>
  43 #include <sys/squeue_impl.h>
  44 #include <sys/squeue.h>
  45 #include <sys/socketvar.h>
  46 
  47 #include <inet/common.h>
  48 #include <inet/dccp_impl.h>
  49 #include <inet/dccp_stack.h>
  50 #include <inet/proto_set.h>
  51 #include <inet/ip.h>
  52 
  53 #include <sys/cmn_err.h>
  54 
  55 static void     dccp_activate(sock_lower_handle_t, sock_upper_handle_t,
  56                     sock_upcalls_t *, int, cred_t *);
  57 static int      dccp_accept(sock_lower_handle_t, sock_lower_handle_t,
  58                     sock_upper_handle_t, cred_t *);
  59 static int      dccp_bind(sock_lower_handle_t, struct sockaddr *,
  60                     socklen_t, cred_t *);
  61 static int      dccp_listen(sock_lower_handle_t, int, cred_t *);
  62 static int      dccp_connect(sock_lower_handle_t, const struct sockaddr *,
  63                     socklen_t, sock_connid_t *, cred_t *);
  64 static int      dccp_getpeername(sock_lower_handle_t, struct sockaddr *,
  65                     socklen_t *, cred_t *);
  66 static int      dccp_getsockname(sock_lower_handle_t, struct sockaddr *,
  67                     socklen_t *, cred_t *);
  68 static int      dccp_getsockopt(sock_lower_handle_t, int, int, void *,
  69                     socklen_t *, cred_t *);
  70 static int      dccp_setsockopt(sock_lower_handle_t, int, int, const void *,
  71                     socklen_t, cred_t *);
  72 static int      dccp_send(sock_lower_handle_t, mblk_t *, struct nmsghdr *,
  73                     cred_t *);
  74 static int      dccp_shutdown(sock_lower_handle_t, int, cred_t *);
  75 static void     dccp_clr_flowctrl(sock_lower_handle_t);
  76 static int      dccp_ioctl(sock_lower_handle_t, int, intptr_t, int, int32_t *,
  77                     cred_t *);
  78 static int      dccp_close(sock_lower_handle_t, int, cred_t *);
  79 
  80 sock_downcalls_t sock_dccp_downcalls = {
  81         dccp_activate,          /* sd_activate */
  82         dccp_accept,            /* sd_accept */
  83         dccp_bind,              /* sd_bind */
  84         dccp_listen,            /* sd_listen */
  85         dccp_connect,           /* sd_connect */
  86         dccp_getpeername,       /* sd_getpeername */
  87         dccp_getsockname,       /* sd_getsockname */
  88         dccp_getsockopt,        /* sd_getsockopt */
  89         dccp_setsockopt,        /* sd_setsockopt */
  90         dccp_send,              /* sd_send */
  91         NULL,                   /* sd_send_uio */
  92         NULL,                   /* sd_recv_uio */
  93         NULL,                   /* sd_poll */
  94         dccp_shutdown,          /* sd_shutdown */
  95         dccp_clr_flowctrl,      /* sd_setflowctrl */
  96         dccp_ioctl,             /* sd_ioctl */
  97         dccp_close,             /* sd_close */
  98 };
  99 
 100 /* ARGSUSED */
 101 static void
 102 dccp_activate(sock_lower_handle_t proto_handle, sock_upper_handle_t sock_handle,
 103     sock_upcalls_t *sock_upcalls, int flags, cred_t *cr)
 104 {
 105         conn_t *connp = (conn_t *)proto_handle;
 106         struct sock_proto_props         sopp;
 107         extern struct module_info       dccp_rinfo;
 108 
 109         cmn_err(CE_NOTE, "dccp_socket.c: dccp_activate");
 110 
 111         ASSERT(connp->conn_upper_handle == NULL);
 112 
 113         /* All Solaris components should pass a cred for this operation */
 114         ASSERT(cr != NULL);
 115 
 116         sopp.sopp_flags = SOCKOPT_RCVHIWAT | SOCKOPT_RCVLOWAT |
 117             SOCKOPT_MAXPSZ | SOCKOPT_MAXBLK | SOCKOPT_RCVTIMER |
 118             SOCKOPT_RCVTHRESH | SOCKOPT_MAXADDRLEN | SOCKOPT_MINPSZ;
 119 
 120         sopp.sopp_rxhiwat = SOCKET_RECVHIWATER;
 121         sopp.sopp_rxlowat = SOCKET_RECVLOWATER;
 122         sopp.sopp_maxpsz = INFPSZ;
 123         sopp.sopp_maxblk = INFPSZ;
 124         sopp.sopp_rcvtimer = SOCKET_TIMER_INTERVAL;
 125         sopp.sopp_rcvthresh = SOCKET_RECVHIWATER >> 3;
 126         sopp.sopp_maxaddrlen = sizeof (sin6_t);
 127         sopp.sopp_minpsz = (dccp_rinfo.mi_minpsz == 1) ? 0 :
 128             dccp_rinfo.mi_minpsz;
 129 
 130         connp->conn_upcalls = sock_upcalls;
 131         connp->conn_upper_handle = sock_handle;
 132 
 133         /* XXX  conn_rcvbuf */
 134         (*connp->conn_upcalls->su_set_proto_props)(connp->conn_upper_handle,
 135             &sopp);
 136 }
 137 
 138 /*ARGSUSED*/
 139 static int
 140 dccp_accept(sock_lower_handle_t lproto_handle,
 141     sock_lower_handle_t eproto_handle, sock_upper_handle_t sock_handle,
 142     cred_t *cr)
 143 {
 144         conn_t  *lconnp, *econnp;
 145         dccp_t  *listener, *eager;
 146 
 147         cmn_err(CE_NOTE, "dccp_socket.c: dccp_accept");
 148 
 149         econnp = (conn_t *)eproto_handle;
 150         eager = econnp->conn_dccp;
 151         ASSERT(IPCL_IS_NONSTR(econnp));
 152         ASSERT(eager->dccp_listener != NULL);
 153         listener = eager->dccp_listener;
 154         lconnp = (conn_t *)listener->dccp_connp;
 155         ASSERT(listener->dccp_state == DCCPS_LISTEN);
 156         ASSERT(lconnp->conn_upper_handle != NULL);
 157 
 158         ASSERT(econnp->conn_upper_handle == NULL ||
 159             econnp->conn_upper_handle == sock_handle);
 160         ASSERT(econnp->conn_upcalls == NULL ||
 161             econnp->conn_upcalls == lconnp->conn_upcalls);
 162         econnp->conn_upper_handle = sock_handle;
 163         econnp->conn_upcalls = lconnp->conn_upcalls;
 164 
 165         ASSERT(econnp->conn_netstack ==
 166             listener->dccp_connp->conn_netstack);
 167         ASSERT(eager->dccp_dccps == listener->dccp_dccps);
 168 
 169         ASSERT(econnp->conn_ref >= 2);
 170         eager->dccp_listener = NULL; /* XXX */
 171         CONN_DEC_REF(listener->dccp_connp);
 172 
 173         return (0);
 174 }
 175 
 176 static int
 177 dccp_bind(sock_lower_handle_t proto_handle, struct sockaddr *sa,
 178     socklen_t len, cred_t *cr)
 179 {
 180         conn_t  *connp = (conn_t *)proto_handle;
 181         int     error;
 182 
 183         cmn_err(CE_NOTE, "dccp_socket.c: dccp_bind");
 184 
 185         ASSERT(connp->conn_upper_handle != NULL);
 186 
 187         /* All Solaris components should pass a cred for this operation */
 188         ASSERT(cr != NULL);
 189 
 190         error = squeue_synch_enter(connp, NULL);
 191         if (error != 0) {
 192                 /* Failed to enter */
 193                 return (ENOSR);
 194         }
 195 
 196         /* Binding to NULL address means unbind */
 197         if (sa == NULL) {
 198                 if (connp->conn_dccp->dccp_state < DCCPS_LISTEN) {
 199                         error = dccp_do_unbind(connp);
 200                 } else {
 201                         error = EINVAL;
 202                 }
 203         } else {
 204                 error = dccp_do_bind(connp, sa, len, cr, B_TRUE);
 205         }
 206 
 207         squeue_synch_exit(connp);
 208 
 209         if (error < 0) {
 210                 if (error == -TOUTSTATE) {
 211                         error = EINVAL;
 212                 } else {
 213                         error = proto_tlitosyserr(-error);
 214                 }
 215         }
 216 
 217         return (error);
 218 }
 219 
 220 /* ARGSUSED */
 221 static int
 222 dccp_listen(sock_lower_handle_t proto_handle, int backlog, cred_t *cr)
 223 {
 224         conn_t  *connp = (conn_t *)proto_handle;
 225         dccp_t  *dccp = connp->conn_dccp;
 226         int     error;
 227 
 228         cmn_err(CE_NOTE, "dccp_socket.c: dccp_listen");
 229 
 230         ASSERT(connp->conn_upper_handle != NULL);
 231 
 232         /* All Solaris components should pass a cred for this operation */
 233         ASSERT(cr != NULL);
 234 
 235         error = squeue_synch_enter(connp, NULL);
 236         if (error != 0) {
 237                 /* Failed to enter */
 238                 return (ENOBUFS);
 239         }
 240 
 241         error = dccp_do_listen(connp, NULL, 0, backlog, cr, B_FALSE);
 242         if (error == 0) {
 243                 /* XXX:DCCP */
 244                 (*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
 245                     SOCK_OPCTL_ENAB_ACCEPT,
 246                     (uintptr_t)(10));
 247         } else if (error < 0) {
 248                 if (error == -TOUTSTATE) {
 249                         error = EINVAL;
 250                 } else {
 251                         error = proto_tlitosyserr(-error);
 252                 }
 253         }
 254 
 255         squeue_synch_exit(connp);
 256 
 257         return (error);
 258 }
 259 
 260 static int
 261 dccp_connect(sock_lower_handle_t proto_handle, const struct sockaddr *sa,
 262     socklen_t len, sock_connid_t *id, cred_t *cr)
 263 {
 264         conn_t  *connp = (conn_t *)proto_handle;
 265         int     error;
 266 
 267         cmn_err(CE_NOTE, "dccp_socket.c: dccp_connect");
 268 
 269         ASSERT(connp->conn_upper_handle != NULL);
 270 
 271         /* All Solaris components should pass a cred for this operation */
 272         ASSERT(cr != NULL);
 273 
 274         error = proto_verify_ip_addr(connp->conn_family, sa, len);
 275         if (error != 0) {
 276                 return (error);
 277         }
 278 
 279         error = squeue_synch_enter(connp, NULL);
 280         if (error != 0) {
 281                 /* Failed to enter */
 282                 return (ENOSR);
 283         }
 284 
 285         error = dccp_do_connect(connp, sa, len, cr, curproc->p_pid);
 286         if (error == 0) {
 287                 *id = connp->conn_dccp->dccp_connid;
 288         } else if (error < 0) {
 289                 if (error == -TOUTSTATE) {
 290                         switch (connp->conn_dccp->dccp_state) {
 291                         case DCCPS_REQUEST:
 292                                 error = EALREADY;
 293                                 break;
 294                         case DCCPS_PARTOPEN:
 295                                 error = EISCONN;
 296                                 break;
 297                         case DCCPS_LISTEN:
 298                                 error = EOPNOTSUPP;
 299                                 break;
 300                         default:
 301                                 error = EINVAL;
 302                                 break;
 303                         }
 304                 } else {
 305                         error = proto_tlitosyserr(-error);
 306                 }
 307         }
 308 
 309         squeue_synch_exit(connp);
 310 
 311         cmn_err(CE_NOTE, "dccp_connect.c: exit %d", error);
 312         return ((error == 0) ? EINPROGRESS : error);
 313 }
 314 
 315 /* ARGSUSED3 */
 316 static int
 317 dccp_getpeername(sock_lower_handle_t proto_handle, struct sockaddr *addr,
 318     socklen_t *addrlenp, cred_t *cr)
 319 {
 320         conn_t  *connp = (conn_t *)proto_handle;
 321         dccp_t  *dccp = connp->conn_dccp;
 322 
 323         cmn_err(CE_NOTE, "dccp_socket.c: dccp_getpeername");
 324 
 325         /* All Solaris components should pass a cred for this operation */
 326         ASSERT(cr != NULL);
 327 
 328         ASSERT(dccp != NULL);
 329         if (dccp->dccp_state < DCCPS_OPEN) {
 330                 return (ENOTCONN);
 331         }
 332 
 333         return (conn_getpeername(connp, addr, addrlenp));
 334 }
 335 
 336 /* ARGSUSED3 */
 337 static int
 338 dccp_getsockname(sock_lower_handle_t proto_handle, struct sockaddr *addr,
 339     socklen_t *addrlenp, cred_t *cr)
 340 {
 341         conn_t  *connp = (conn_t *)proto_handle;
 342         int     error;
 343 
 344         cmn_err(CE_NOTE, "dccp_socket.c: dccp_getsockname");
 345 
 346         /* All Solaris components should pass a cred for this operation */
 347         ASSERT(cr != NULL);
 348 
 349         /* XXX UDP has locks here, TCP not */
 350         mutex_enter(&connp->conn_lock);
 351         error = conn_getsockname(connp, addr, addrlenp);
 352         mutex_exit(&connp->conn_lock);
 353 
 354         return (error);
 355 }
 356 
 357 static int
 358 dccp_getsockopt(sock_lower_handle_t proto_handle, int level, int option_name,
 359     void *optvalp, socklen_t *optlen, cred_t *cr)
 360 {
 361         conn_t          *connp = (conn_t *)proto_handle;
 362         void            *optvalp_buf;
 363         t_uscalar_t     max_optbuf_len;
 364         int             len;
 365         int             error;
 366 
 367         cmn_err(CE_NOTE, "dccp_socket.c: dccp_getsockopt");
 368 
 369         ASSERT(connp->conn_upper_handle != NULL);
 370 
 371         /* All Solaris components should pass a cred for this operation */
 372         ASSERT(cr != NULL);
 373 
 374         error = proto_opt_check(level, option_name, *optlen, &max_optbuf_len,
 375             dccp_opt_obj.odb_opt_des_arr,
 376             dccp_opt_obj.odb_opt_arr_cnt,
 377             B_FALSE, B_TRUE, cr);
 378         if (error != 0) {
 379                 if (error < 0) {
 380                         error = proto_tlitosyserr(-error);
 381                 }
 382                 return (error);
 383         }
 384 
 385         optvalp_buf = kmem_alloc(max_optbuf_len, KM_SLEEP);
 386         if (optvalp_buf == NULL) {
 387                 return (ENOMEM);
 388         }
 389 
 390         error = squeue_synch_enter(connp, NULL);
 391         if (error == ENOMEM) {
 392                 kmem_free(optvalp_buf, max_optbuf_len);
 393                 return (ENOMEM);
 394         }
 395 
 396         len = dccp_opt_get(connp, level, option_name, optvalp_buf);
 397         squeue_synch_exit(connp);
 398 
 399         if (len == -1) {
 400                 kmem_free(optvalp_buf, max_optbuf_len);
 401                 return (EINVAL);
 402         }
 403 
 404         t_uscalar_t size = MIN(len, *optlen);
 405 
 406         bcopy(optvalp_buf, optvalp, size);
 407         bcopy(&size, optlen, sizeof (size));
 408 
 409         kmem_free(optvalp_buf, max_optbuf_len);
 410 
 411         return (0);
 412 }
 413 
 414 static int
 415 dccp_setsockopt(sock_lower_handle_t proto_handle, int level, int option_name,
 416     const void *optvalp, socklen_t optlen, cred_t *cr)
 417 {
 418         conn_t  *connp = (conn_t *)proto_handle;
 419         int     error;
 420 
 421         cmn_err(CE_NOTE, "dccp_socket.c: dccp_setsockopt");
 422 
 423         ASSERT(connp->conn_upper_handle != NULL);
 424 
 425         /* All Solaris components should pass a cred for this operation */
 426         ASSERT(cr != NULL);
 427 
 428         error = squeue_synch_enter(connp, NULL);
 429         if (error == ENOMEM) {
 430                 return (ENOMEM);
 431         }
 432 
 433         error = proto_opt_check(level, option_name, optlen, NULL,
 434             dccp_opt_obj.odb_opt_des_arr,
 435             dccp_opt_obj.odb_opt_arr_cnt,
 436             B_TRUE, B_FALSE, cr);
 437         if (error != 0) {
 438                 if (error < 0) {
 439                         error = proto_tlitosyserr(-error);
 440                 }
 441                 squeue_synch_exit(connp);
 442                 return (error);
 443         }
 444 
 445         error = dccp_opt_set(connp, SETFN_OPTCOM_NEGOTIATE, level, option_name,
 446             optlen, (uchar_t *)optvalp, (uint_t *)&optlen, (uchar_t *)optvalp,
 447             NULL, cr);
 448         squeue_synch_exit(connp);
 449 
 450         ASSERT(error >= 0);
 451 
 452         return (error);
 453 }
 454 
 455 /* ARGSUSED */
 456 static int
 457 dccp_send(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg,
 458     cred_t *cr)
 459 {
 460         conn_t  *connp = (conn_t *)proto_handle;
 461         dccp_t  *dccp;
 462         uint32_t msize;
 463         int32_t dccpstate;
 464 
 465         cmn_err(CE_NOTE, "dccp_socket.c: dccp_send");
 466 
 467         /* All Solaris components should pass a cred for this operation */
 468         ASSERT(cr != NULL);
 469 
 470         ASSERT(connp->conn_ref >= 2);
 471         ASSERT(connp->conn_upper_handle != NULL);
 472 
 473         if (msg->msg_controllen != 0) {
 474                 freemsg(mp);
 475                 return (EOPNOTSUPP);
 476         }
 477 
 478         switch (DB_TYPE(mp)) {
 479         case M_DATA:
 480                 dccp = connp->conn_dccp;
 481                 ASSERT(dccp != NULL);
 482 
 483                 dccpstate = dccp->dccp_state;
 484                 if (dccpstate < DCCPS_OPEN) {
 485                         freemsg(mp);
 486 
 487                         return ((dccpstate == DCCPS_REQUEST) ? ENOTCONN :
 488                             ((dccp->dccp_connid > 0) ? EPIPE : ENOTCONN));
 489                 } else if (dccpstate > DCCPS_CLOSING) {
 490                         freemsg(mp);
 491                         return (EPIPE);
 492                 }
 493 
 494                 /* XXX */
 495 
 496                 msize = msgdsize(mp);
 497 
 498                 CONN_INC_REF(connp);
 499 
 500                 if (msg->msg_flags & MSG_OOB) {
 501                         SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_output_urgent,
 502                             connp, NULL, dccp_squeue_flag, SQTAG_DCCP_OUTPUT); 
 503                 } else {
 504                         SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_output,
 505                             connp, NULL, dccp_squeue_flag, SQTAG_DCCP_OUTPUT);
 506                 }
 507 
 508                 return (0);
 509 
 510         default:
 511                 ASSERT(0);
 512         }
 513 
 514         freemsg(mp);
 515 
 516         return (0);
 517 }
 518 
 519 /* ARGSUSED */
 520 static int
 521 dccp_shutdown(sock_lower_handle_t proto_handle, int how, cred_t *cr)
 522 {
 523         conn_t  *connp = (conn_t *)proto_handle;
 524         dccp_t  *dccp = connp->conn_dccp;
 525 
 526         cmn_err(CE_NOTE, "dccp_socket.c: dccp_shutdown");
 527 
 528         /* All Solaris components should pass a cred for this operation. */
 529         ASSERT(cr != NULL);
 530 
 531         ASSERT(connp->conn_upper_handle != NULL);
 532 
 533 
 534         return (ENOTSUP);
 535 }
 536 
 537 static void
 538 dccp_clr_flowctrl(sock_lower_handle_t proto_handle)
 539 {
 540         conn_t  *connp = (conn_t *)proto_handle;
 541         dccp_t  *dccp = connp->conn_dccp;
 542         mblk_t  *mp;
 543         int     error;
 544 
 545         ASSERT(connp->conn_upper_handle != NULL);
 546 
 547         cmn_err(CE_NOTE, "dccp_socket.c: dccp_clr_flowctrl");
 548 
 549         error = squeue_synch_enter(connp, mp);
 550 
 551         squeue_synch_exit(connp);
 552 }
 553 
 554 /* ARGSUSED */
 555 static int
 556 dccp_ioctl(sock_lower_handle_t proto_handle, int cmd, intptr_t arg,
 557     int mode, int32_t *rvalp, cred_t *cr)
 558 {
 559         conn_t  *connp = (conn_t *)proto_handle;
 560         int     error;
 561 
 562         cmn_err(CE_NOTE, "dccp_socket.c: dccp_ioctl");
 563 
 564         ASSERT(connp->conn_upper_handle != NULL);
 565 
 566         /* All Solaris components should pass a cred for this operation. */
 567         ASSERT(cr != NULL);
 568 
 569         return (ENOTSUP);
 570 }
 571 
 572 /* ARGSUSED */
 573 static int
 574 dccp_close(sock_lower_handle_t proto_handle, int flags, cred_t *cr)
 575 {
 576         conn_t  *connp = (conn_t *)proto_handle;
 577 
 578         cmn_err(CE_NOTE, "dccp_socket.c: dccp_close\n");
 579 
 580         ASSERT(connp->conn_upper_handle != NULL);
 581 
 582         /* All Solaris components should pass a cred for this operation */
 583         ASSERT(cr != NULL);
 584 
 585         dccp_close_common(connp, flags);
 586 
 587         ip_free_helper_stream(connp);
 588 
 589         CONN_DEC_REF(connp);
 590 
 591         /*
 592          * EINPROGRESS tells sockfs to wait for a 'closed' upcall before
 593          * freeing the socket.
 594          */
 595         return (EINPROGRESS);
 596 }
 597 
 598 
 599 /*
 600  * Socket create function.
 601  */
 602 sock_lower_handle_t
 603 dccp_create(int family, int type, int proto, sock_downcalls_t **sockdowncalls,
 604     uint_t *smodep, int *errorp, int flags, cred_t *credp)
 605 {
 606         conn_t          *connp;
 607         boolean_t       isv6;
 608 
 609         /* XXX (type != SOCK_STREAM */
 610         if ((family != AF_INET && family != AF_INET6) ||
 611             (proto != 0 && proto != IPPROTO_DCCP)) {
 612                 *errorp = EPROTONOSUPPORT;
 613                 return (NULL);
 614         }
 615 
 616         cmn_err(CE_NOTE, "dccp_socket: dccp_create\n");
 617 
 618         isv6 = family == AF_INET6 ? B_TRUE: B_FALSE;
 619         connp = dccp_create_common(credp, isv6, B_TRUE, errorp);
 620         if (connp == NULL) {
 621                 return (NULL);
 622         }
 623 
 624         /*
 625          * Increment ref for DCCP connection.
 626          */
 627         mutex_enter(&connp->conn_lock);
 628         CONN_INC_REF_LOCKED(connp);
 629         ASSERT(connp->conn_ref == 2);
 630         connp->conn_state_flags &= ~CONN_INCIPIENT;
 631         connp->conn_flags |= IPCL_NONSTR;
 632         mutex_exit(&connp->conn_lock);
 633 
 634         ASSERT(errorp != NULL);
 635         *errorp = 0;
 636         *sockdowncalls = &sock_dccp_downcalls;
 637         *smodep = SM_CONNREQUIRED | SM_EXDATA | SM_ACCEPTSUPP |
 638             SM_SENDFILESUPP;
 639 
 640         return ((sock_lower_handle_t)connp);
 641 }
 642 
 643 int
 644 dccp_fallback(sock_lower_handle_t proto_handle, queue_t *q,
 645     boolean_t issocket, so_proto_quiesced_cb_t quiesced_cb,
 646     sock_quiesce_arg_t *arg)
 647 {
 648         cmn_err(CE_NOTE, "dccp_socket: dccp_fallback\n");
 649 
 650         return (0);
 651 }
 652 
 653 /*
 654  * Notifies a non-STREAMS based listener about a new connection. This
 655  * function is executed on the *eager*'s squeue once the 3 way handshake
 656  * has completed. Note that the behavior differs from STREAMS, where the
 657  * T_CONN_IND is sent up by tcp_send_conn_ind() while on the *listener*'s
 658  * squeue.
 659  *
 660  * Returns B_TRUE if the notification succeeded and an upper handle was
 661  * obtained. `tcp' should be closed on failure.
 662  */
 663 boolean_t
 664 dccp_newconn_notify(dccp_t *dccp, ip_recv_attr_t *ira)
 665 {
 666         dccp_t                  *listener = dccp->dccp_listener;
 667         dccp_t                  *tail;
 668         conn_t                  *lconnp = listener->dccp_connp;
 669         conn_t                  *econnp = dccp->dccp_connp;
 670         ipaddr_t                *addr_cache;
 671         sock_upper_handle_t     upper;
 672         struct sock_proto_props sopp;
 673 
 674         cmn_err(CE_NOTE, "dccp_socket.c: dccp_newconn_notify");
 675 
 676         if (lconnp->conn_upcalls) {
 677                 cmn_err(CE_NOTE, "NOT NULL");
 678         } else {
 679                 cmn_err(CE_NOTE, "ISSSSSS NULL");
 680         }
 681 
 682         if ((upper = (*lconnp->conn_upcalls->su_newconn)
 683                 (lconnp->conn_upper_handle, (sock_lower_handle_t)econnp,
 684                 &sock_dccp_downcalls, ira->ira_cred, ira->ira_cpid,
 685                 &econnp->conn_upcalls)) == NULL) {
 686                         return (B_FALSE);
 687         }
 688         econnp->conn_upper_handle = upper;
 689 
 690         (*econnp->conn_upcalls->su_set_proto_props)
 691             (econnp->conn_upper_handle, &sopp);
 692 
 693         return (B_TRUE);
 694 }