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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/t_lock.h>
  28 #include <sys/param.h>
  29 #include <sys/systm.h>
  30 #include <sys/buf.h>
  31 #include <sys/vfs.h>
  32 #include <sys/vnode.h>
  33 #include <sys/debug.h>
  34 #include <sys/errno.h>
  35 #include <sys/stropts.h>
  36 #include <sys/cmn_err.h>
  37 #include <sys/sysmacros.h>
  38 #include <sys/policy.h>
  39 
  40 #include <sys/filio.h>
  41 #include <sys/sockio.h>
  42 
  43 #include <sys/project.h>
  44 #include <sys/tihdr.h>
  45 #include <sys/strsubr.h>
  46 
  47 #include <sys/socket.h>
  48 #include <sys/socketvar.h>
  49 #include <sys/strsun.h>
  50 
  51 #include <sys/tsol/label.h>
  52 
  53 #include <inet/sdp_itf.h>
  54 #include "socksdp.h"
  55 #include <fs/sockfs/sockcommon.h>
  56 
  57 /*
  58  * SDP sockfs sonode operations
  59  */
  60 static int sosdp_init(struct sonode *, struct sonode *, struct cred *, int);
  61 static int sosdp_accept(struct sonode *, int, struct cred *, struct sonode **);
  62 static int sosdp_bind(struct sonode *, struct sockaddr *, socklen_t, int,
  63     struct cred *);
  64 static int sosdp_listen(struct sonode *, int, struct cred *);
  65 static int sosdp_connect(struct sonode *, struct sockaddr *, socklen_t,
  66     int, int, struct cred *);
  67 static int sosdp_recvmsg(struct sonode *, struct nmsghdr *, struct uio *,
  68     struct cred *);
  69 static int sosdp_sendmsg(struct sonode *, struct nmsghdr *, struct uio *,
  70     struct cred *);
  71 static int sosdp_getpeername(struct sonode *, struct sockaddr *, socklen_t *,
  72     boolean_t, struct cred *);
  73 static int sosdp_getsockname(struct sonode *, struct sockaddr *, socklen_t *,
  74     struct cred *);
  75 static int sosdp_shutdown(struct sonode *, int, struct cred *);
  76 static int sosdp_getsockopt(struct sonode *, int, int, void *, socklen_t *,
  77     int, struct cred *);
  78 static int sosdp_setsockopt(struct sonode *, int, int, const void *,
  79     socklen_t, struct cred *);
  80 static int sosdp_ioctl(struct sonode *, int, intptr_t, int, struct cred *,
  81     int32_t *);
  82 static int sosdp_poll(struct sonode *, short, int, short *,
  83     struct pollhead **);
  84 static int sosdp_close(struct sonode *, int, struct cred *);
  85 void sosdp_fini(struct sonode *, struct cred *);
  86 
  87 
  88 /*
  89  * Socket upcalls
  90  */
  91 static void *sdp_sock_newconn(void *parenthandle, void *connind);
  92 static void sdp_sock_connected(void *handle);
  93 static void sdp_sock_disconnected(void *handle, int error);
  94 static void sdp_sock_connfail(void *handle, int error);
  95 static int sdp_sock_recv(void *handle, mblk_t *mp, int flags);
  96 static void sdp_sock_xmitted(void *handle, int txqueued);
  97 static void sdp_sock_urgdata(void *handle);
  98 static void sdp_sock_ordrel(void *handle);
  99 
 100 sonodeops_t sosdp_sonodeops = {
 101         sosdp_init,                     /* sop_init     */
 102         sosdp_accept,                   /* sop_accept   */
 103         sosdp_bind,                     /* sop_bind     */
 104         sosdp_listen,                   /* sop_listen   */
 105         sosdp_connect,                  /* sop_connect  */
 106         sosdp_recvmsg,                  /* sop_recvmsg  */
 107         sosdp_sendmsg,                  /* sop_sendmsg  */
 108         so_sendmblk_notsupp,            /* sop_sendmblk */
 109         sosdp_getpeername,              /* sop_getpeername */
 110         sosdp_getsockname,              /* sop_getsockname */
 111         sosdp_shutdown,                 /* sop_shutdown */
 112         sosdp_getsockopt,               /* sop_getsockopt */
 113         sosdp_setsockopt,               /* sop_setsockopt */
 114         sosdp_ioctl,                    /* sop_ioctl    */
 115         sosdp_poll,                     /* sop_poll     */
 116         sosdp_close,                    /* sop_close    */
 117 };
 118 
 119 sdp_upcalls_t sosdp_sock_upcalls = {
 120         sdp_sock_newconn,
 121         sdp_sock_connected,
 122         sdp_sock_disconnected,
 123         sdp_sock_connfail,
 124         sdp_sock_recv,
 125         sdp_sock_xmitted,
 126         sdp_sock_urgdata,
 127         sdp_sock_ordrel,
 128 };
 129 
 130 /* ARGSUSED */
 131 static int
 132 sosdp_init(struct sonode *so, struct sonode *pso, struct cred *cr, int flags)
 133 {
 134         int error = 0;
 135         sdp_sockbuf_limits_t sbl;
 136         sdp_upcalls_t *upcalls;
 137 
 138         if (pso != NULL) {
 139                 /* passive open, just inherit settings from parent */
 140 
 141                 mutex_enter(&so->so_lock);
 142 
 143                 so->so_state |= (SS_ISBOUND | SS_ISCONNECTED |
 144                     (pso->so_state & SS_ASYNC));
 145                 sosdp_so_inherit(pso, so);
 146                 so->so_proto_props = pso->so_proto_props;
 147 
 148                 mutex_exit(&so->so_lock);
 149 
 150                 return (0);
 151         }
 152 
 153         if ((error = secpolicy_basic_net_access(cr)) != 0)
 154                 return (error);
 155 
 156         upcalls = &sosdp_sock_upcalls;
 157 
 158         so->so_proto_handle = (sock_lower_handle_t)sdp_create(so, NULL,
 159             so->so_family, SDP_CAN_BLOCK, upcalls, &sbl, cr, &error);
 160         if (so->so_proto_handle == NULL)
 161                 return (ENOMEM);
 162 
 163         so->so_rcvbuf = sbl.sbl_rxbuf;
 164         so->so_rcvlowat = sbl.sbl_rxlowat;
 165         so->so_sndbuf = sbl.sbl_txbuf;
 166         so->so_sndlowat = sbl.sbl_txlowat;
 167 
 168         return (error);
 169 }
 170 
 171 /*
 172  * Accept incoming connection.
 173  */
 174 /* ARGSUSED */
 175 static int
 176 sosdp_accept(struct sonode *lso, int fflag, struct cred *cr,
 177     struct sonode **nsop)
 178 {
 179         int error = 0;
 180         struct sonode *nso;
 181 
 182         dprint(3, ("sosdp_accept: so:%p so_proto_handle:%p", (void *)lso,
 183             (void *)lso->so_proto_handle));
 184 
 185         if (!(lso->so_state & SS_ACCEPTCONN)) {
 186                 /*
 187                  * Not a listen socket.
 188                  */
 189                 eprintsoline(lso, EINVAL);
 190                 return (EINVAL);
 191         }
 192         /*
 193          * Returns right away if socket is nonblocking.
 194          */
 195         error = so_acceptq_dequeue(lso, (fflag & (FNONBLOCK|FNDELAY)), &nso);
 196         if (error != 0) {
 197                 eprintsoline(lso, error);
 198                 dprint(4, ("sosdp_accept: failed %d:lso:%p so_proto_handle:%p",
 199                     error, (void *)lso, (void *)lso->so_proto_handle));
 200                 return (error);
 201         }
 202 
 203         dprint(2, ("sosdp_accept: new %p\n", (void *)nso));
 204         *nsop = nso;
 205 
 206         return (0);
 207 }
 208 
 209 /*
 210  * Bind local endpoint.
 211  */
 212 /* ARGSUSED */
 213 int
 214 sosdp_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
 215     int flags, struct cred *cr)
 216 {
 217         int     error = 0;
 218 
 219         if (!(flags & _SOBIND_LOCK_HELD)) {
 220                 mutex_enter(&so->so_lock);
 221                 so_lock_single(so);     /* Set SOLOCKED */
 222         } else {
 223                 ASSERT(MUTEX_HELD(&so->so_lock));
 224                 ASSERT(so->so_flag & SOLOCKED);
 225         }
 226 
 227         if ((so->so_state & SS_ISBOUND) || name == NULL || namelen == 0) {
 228                 /*
 229                  * Multiple binds not allowed for any SDP socket.
 230                  * Also binding with null address is not supported.
 231                  */
 232                 error = EINVAL;
 233                 eprintsoline(so, error);
 234                 goto done;
 235         }
 236 
 237         /*
 238          * X/Open requires this check
 239          */
 240         if (so->so_state & SS_CANTSENDMORE) {
 241                 error = EINVAL;
 242                 goto done;
 243         }
 244 
 245         /*
 246          * Protocol module does address family checks
 247          */
 248         mutex_exit(&so->so_lock);
 249 
 250         error = sdp_bind((struct sdp_conn_struct_t *)so->so_proto_handle,
 251             name, namelen);
 252 
 253         mutex_enter(&so->so_lock);
 254 
 255         if (error == 0) {
 256                 so->so_state |= SS_ISBOUND;
 257         } else {
 258                 eprintsoline(so, error);
 259         }
 260 done:
 261         if (!(flags & _SOBIND_LOCK_HELD)) {
 262                 so_unlock_single(so, SOLOCKED);
 263                 mutex_exit(&so->so_lock);
 264         } else {
 265                 /* If the caller held the lock don't release it here */
 266                 ASSERT(MUTEX_HELD(&so->so_lock));
 267                 ASSERT(so->so_flag & SOLOCKED);
 268         }
 269         return (error);
 270 }
 271 
 272 /*
 273  * Turn socket into a listen socket.
 274  */
 275 /* ARGSUSED */
 276 static int
 277 sosdp_listen(struct sonode *so, int backlog, struct cred *cr)
 278 {
 279         int error = 0;
 280 
 281         mutex_enter(&so->so_lock);
 282         so_lock_single(so);
 283 
 284         /*
 285          * If this socket is trying to do connect, or if it has
 286          * been connected, disallow.
 287          */
 288         if (so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED |
 289             SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE)) {
 290                 error = EINVAL;
 291                 eprintsoline(so, EINVAL);
 292                 goto done;
 293         }
 294         /*
 295          * If listen() is only called to change backlog, we don't
 296          * need to notify protocol module.
 297          */
 298         if (so->so_state & SS_ACCEPTCONN) {
 299                 so->so_backlog = backlog;
 300                 goto done;
 301         }
 302 
 303         mutex_exit(&so->so_lock);
 304 
 305         error = sdp_listen((struct sdp_conn_struct_t *)so->so_proto_handle,
 306             backlog);
 307 
 308         mutex_enter(&so->so_lock);
 309         if (error == 0) {
 310                 so->so_state |= (SS_ACCEPTCONN | SS_ISBOUND);
 311                 so->so_backlog = backlog;
 312         } else {
 313                 eprintsoline(so, error);
 314         }
 315 done:
 316         so_unlock_single(so, SOLOCKED);
 317         mutex_exit(&so->so_lock);
 318 
 319         return (error);
 320 }
 321 
 322 /*
 323  * Active open.
 324  */
 325 /*ARGSUSED*/
 326 static int
 327 sosdp_connect(struct sonode *so, struct sockaddr *name,
 328     socklen_t namelen, int fflag, int flags, struct cred *cr)
 329 {
 330         int error = 0;
 331 
 332         mutex_enter(&so->so_lock);
 333         so_lock_single(so);
 334 
 335         /*
 336          * Can't connect() after listen(), or if the socket is already
 337          * connected.
 338          */
 339         if (so->so_state & (SS_ACCEPTCONN|SS_ISCONNECTED|SS_ISCONNECTING)) {
 340                 if (so->so_state & SS_ISCONNECTED) {
 341                         error = EISCONN;
 342                 } else if (so->so_state & SS_ISCONNECTING) {
 343                         error = EALREADY;
 344                 } else {
 345                         error = EOPNOTSUPP;
 346                 }
 347                 eprintsoline(so, error);
 348                 goto done;
 349         }
 350 
 351         /*
 352          * check for failure of an earlier call
 353          */
 354         if (so->so_error != 0) {
 355                 error = sogeterr(so, B_TRUE);
 356                 eprintsoline(so, error);
 357                 goto done;
 358         }
 359 
 360         /*
 361          * Connection is closing, or closed, don't allow reconnect.
 362          * TCP allows this to proceed, but the socket remains unwriteable.
 363          * BSD returns EINVAL.
 364          */
 365         if (so->so_state & (SS_ISDISCONNECTING|SS_CANTRCVMORE|
 366             SS_CANTSENDMORE)) {
 367                 error = EINVAL;
 368                 eprintsoline(so, error);
 369                 goto done;
 370         }
 371         if (name == NULL || namelen == 0) {
 372                 eprintsoline(so, EINVAL);
 373                 goto done;
 374         }
 375         soisconnecting(so);
 376         mutex_exit(&so->so_lock);
 377 
 378         error = sdp_connect((struct sdp_conn_struct_t *)so->so_proto_handle,
 379             name, namelen);
 380 
 381         mutex_enter(&so->so_lock);
 382         if (error == 0) {
 383                 /*
 384                  * Allow other threads to access the socket
 385                  */
 386                 error = sowaitconnected(so, fflag, 0);
 387                 dprint(4,
 388                     ("sosdp_connect: wait on so:%p "
 389                     "so_proto_handle:%p failed:%d",
 390                     (void *)so, (void *)so->so_proto_handle, error));
 391         }
 392 
 393         switch (error) {
 394         case 0:
 395         case EINPROGRESS:
 396         case EALREADY:
 397         case EINTR:
 398                 /* Non-fatal errors */
 399                 so->so_state |= SS_ISBOUND;
 400                 break;
 401         default:
 402                 /* clear SS_ISCONNECTING in case it was set */
 403                 so->so_state &= ~SS_ISCONNECTING;
 404                 break;
 405         }
 406 done:
 407         so_unlock_single(so, SOLOCKED);
 408         mutex_exit(&so->so_lock);
 409         return (error);
 410 }
 411 
 412 /*
 413  * Receive data.
 414  */
 415 /* ARGSUSED */
 416 int
 417 sosdp_recvmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
 418     struct cred *cr)
 419 {
 420         int flags, error = 0;
 421         int size;
 422 
 423         flags = msg->msg_flags;
 424         msg->msg_flags = 0;
 425 
 426 
 427         if (!(so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|
 428             SS_CANTRCVMORE))) {
 429                 return (ENOTCONN);
 430         }
 431 
 432         /*
 433          * flag possibilities:
 434          *
 435          * MSG_PEEK     Don't consume data
 436          * MSG_WAITALL  Wait for full quantity of data (ignored if MSG_PEEK)
 437          * MSG_DONTWAIT Non-blocking (same as FNDELAY | FNONBLOCK)
 438          *
 439          * MSG_WAITALL can return less than the full buffer if either
 440          *
 441          * 1. we would block and we are non-blocking
 442          * 2. a full message cannot be delivered
 443          *
 444          */
 445 
 446         mutex_enter(&so->so_lock);
 447 
 448         /*
 449          * Allow just one reader at a time.
 450          */
 451         error = so_lock_read_intr(so,
 452             uiop->uio_fmode | ((flags & MSG_DONTWAIT) ? FNONBLOCK : 0));
 453         if (error != 0) {
 454                 mutex_exit(&so->so_lock);
 455                 return (error);
 456         }
 457         size = uiop->uio_resid;
 458         mutex_exit(&so->so_lock);
 459 
 460         if (!(so->so_state & SS_CANTRCVMORE)) {
 461                 if (uiop->uio_fmode & (FNDELAY|FNONBLOCK)) {
 462                         flags |= MSG_DONTWAIT;
 463                 }
 464                 error = sdp_recv(
 465                     (struct sdp_conn_struct_t *)so->so_proto_handle, msg,
 466                     size, flags, uiop);
 467         } else {
 468                 msg->msg_controllen = 0;
 469                 msg->msg_namelen = 0;
 470         }
 471 done:
 472         mutex_enter(&so->so_lock);
 473         so_unlock_read(so);
 474         mutex_exit(&so->so_lock);
 475         return (error);
 476 }
 477 
 478 /*
 479  * Send message.
 480  */
 481 /* ARGSUSED */
 482 static int
 483 sosdp_sendmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
 484     struct cred *cr)
 485 {
 486         int flags;
 487         ssize_t count;
 488         int error;
 489 
 490         ASSERT(so->so_type == SOCK_STREAM);
 491 
 492         dprint(4, ("sosdp_sendmsg: so:%p so_proto_handle:%p",
 493             (void *)so, (void *)so->so_proto_handle));
 494 
 495         flags = msg->msg_flags;
 496 
 497         if (msg->msg_controllen != 0) {
 498                 return (EOPNOTSUPP);
 499         }
 500 
 501         mutex_enter(&so->so_lock);
 502         if (so->so_state & SS_CANTSENDMORE) {
 503                 mutex_exit(&so->so_lock);
 504                 return (EPIPE);
 505         }
 506 
 507         if (so->so_error != 0) {
 508                 error = sogeterr(so, B_TRUE);
 509                 mutex_exit(&so->so_lock);
 510                 return (error);
 511         }
 512 
 513         if (uiop->uio_fmode & (FNDELAY|FNONBLOCK))
 514                 flags |= MSG_DONTWAIT;
 515 
 516         count = uiop->uio_resid;
 517 
 518         if (!(so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED))) {
 519                 dprint(4, ("sosdp_sendmsg: invalid state: <%x>",
 520                     so->so_state));
 521                 mutex_exit(&so->so_lock);
 522                 return (ENOTCONN);
 523         }
 524 
 525         mutex_exit(&so->so_lock);
 526         error = sdp_send((struct sdp_conn_struct_t *)so->so_proto_handle,
 527             msg, count, flags, uiop);
 528 
 529         return (error);
 530 }
 531 
 532 /*
 533  * Get address of remote node.
 534  */
 535 /* ARGSUSED */
 536 static int
 537 sosdp_getpeername(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
 538     boolean_t accept, struct cred *cr)
 539 {
 540 
 541         if (!accept && !(so->so_state & SS_ISCONNECTED)) {
 542                 return (ENOTCONN);
 543         } else {
 544                 return (sdp_getpeername(
 545                     (struct sdp_conn_struct_t *)so->so_proto_handle,
 546                     addr, addrlen));
 547         }
 548 }
 549 
 550 /*
 551  * Get local address.
 552  */
 553 /* ARGSUSED */
 554 static int
 555 sosdp_getsockname(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
 556     struct cred *cr)
 557 {
 558         mutex_enter(&so->so_lock);
 559 
 560         if (!(so->so_state & SS_ISBOUND)) {
 561                 /*
 562                  * Zero address, except for address family
 563                  */
 564                 if (so->so_family == AF_INET || so->so_family == AF_INET6) {
 565                         bzero(addr, *addrlen);
 566                         *addrlen = (so->so_family == AF_INET6) ?
 567                             sizeof (struct sockaddr_in6) :
 568                             sizeof (struct sockaddr_in);
 569                         addr->sa_family = so->so_family;
 570                 }
 571                 mutex_exit(&so->so_lock);
 572                 return (0);
 573         } else {
 574                 mutex_exit(&so->so_lock);
 575                 return (sdp_getsockname(
 576                     (struct sdp_conn_struct_t *)so->so_proto_handle,
 577                     addr, addrlen));
 578         }
 579 }
 580 
 581 /*
 582  * Called from shutdown().
 583  */
 584 /* ARGSUSED */
 585 static int
 586 sosdp_shutdown(struct sonode *so, int how, struct cred *cr)
 587 {
 588         uint_t state_change;
 589         int error = 0;
 590 
 591         mutex_enter(&so->so_lock);
 592         so_lock_single(so);
 593         /*
 594          * Record the current state and then perform any state changes.
 595          * Then use the difference between the old and new states to
 596          * determine which needs to be done.
 597          */
 598         state_change = so->so_state;
 599         if (!(state_change & SS_ISCONNECTED)) {
 600                 error = ENOTCONN;
 601                 goto done;
 602         }
 603 
 604         switch (how) {
 605         case SHUT_RD:
 606                 socantrcvmore(so);
 607                 break;
 608         case SHUT_WR:
 609                 socantsendmore(so);
 610                 break;
 611         case SHUT_RDWR:
 612                 socantsendmore(so);
 613                 socantrcvmore(so);
 614                 break;
 615         default:
 616                 error = EINVAL;
 617                 goto done;
 618         }
 619 
 620         state_change = so->so_state & ~state_change;
 621 
 622         if (state_change & SS_CANTSENDMORE) {
 623                 so->so_state |= SS_ISDISCONNECTING;
 624         }
 625         so_notify_shutdown(so);
 626 
 627         if (state_change & SS_CANTSENDMORE) {
 628                 error = sdp_shutdown(
 629                     (struct sdp_conn_struct_t *)so->so_proto_handle, how);
 630         }
 631 
 632         mutex_enter(&so->so_lock);
 633 done:
 634         so_unlock_single(so, SOLOCKED);
 635         mutex_exit(&so->so_lock);
 636 
 637         /*
 638          * HACK: sdp_disconnect() may return EWOULDBLOCK.  But this error is
 639          * not documented in standard socket API.  Catch it here.
 640          */
 641         if (error == EWOULDBLOCK)
 642                 error = 0;
 643         return (error);
 644 }
 645 
 646 /*
 647  * Get socket options.
 648  */
 649 /*ARGSUSED*/
 650 static int
 651 sosdp_getsockopt(struct sonode *so, int level, int option_name,
 652     void *optval, socklen_t *optlenp, int flags, struct cred *cr)
 653 {
 654         int error = 0;
 655         void *option = NULL;
 656         socklen_t maxlen = *optlenp, len, optlen;
 657         uint32_t value;
 658         uint8_t buffer[4];
 659         void *optbuf = &buffer;
 660 
 661 
 662         mutex_enter(&so->so_lock);
 663 
 664         if (level == SOL_SOCKET) {
 665                 switch (option_name) {
 666                 case SO_TYPE:
 667                 case SO_ERROR:
 668                 case SO_DEBUG:
 669                 case SO_ACCEPTCONN:
 670                 case SO_REUSEADDR:
 671                 case SO_KEEPALIVE:
 672                 case SO_DONTROUTE:
 673                 case SO_BROADCAST:
 674                 case SO_USELOOPBACK:
 675                 case SO_OOBINLINE:
 676                 case SO_SNDBUF:
 677                 case SO_RCVBUF:
 678                 case SO_SNDLOWAT:
 679                 case SO_RCVLOWAT:
 680                 case SO_DGRAM_ERRIND:
 681                         if (maxlen < (t_uscalar_t)sizeof (int32_t)) {
 682                                 error = EINVAL;
 683                                 eprintsoline(so, error);
 684                                 goto done;
 685                         }
 686                         break;
 687                 case SO_LINGER:
 688                         if (maxlen < (t_uscalar_t)sizeof (struct linger)) {
 689                                 error = EINVAL;
 690                                 eprintsoline(so, error);
 691                                 goto done;
 692                         }
 693                         break;
 694                 }
 695                 len = (t_uscalar_t)sizeof (uint32_t);   /* Default */
 696                 option = &value;
 697 
 698                 switch (option_name) {
 699                 case SO_TYPE:
 700                         value = so->so_type;
 701                         goto copyout;
 702 
 703                 case SO_ERROR:
 704                         value = sogeterr(so, B_TRUE);
 705                         goto copyout;
 706 
 707                 case SO_ACCEPTCONN:
 708                         value = (so->so_state & SS_ACCEPTCONN) ?
 709                             SO_ACCEPTCONN : 0;
 710                         goto copyout;
 711 
 712                 case SO_DEBUG:
 713                 case SO_REUSEADDR:
 714                 case SO_KEEPALIVE:
 715                 case SO_DONTROUTE:
 716                 case SO_BROADCAST:
 717                 case SO_USELOOPBACK:
 718                 case SO_OOBINLINE:
 719                 case SO_DGRAM_ERRIND:
 720                         value = (so->so_options & option_name);
 721                         goto copyout;
 722 
 723                         /*
 724                          * The following options are only returned by sockfs
 725                          * when sdp_get_opt() fails.
 726                          */
 727 
 728                 case SO_LINGER:
 729                         option = &so->so_linger;
 730                         len = (t_uscalar_t)sizeof (struct linger);
 731                         break;
 732                 case SO_SNDBUF:
 733                         value = so->so_sndbuf;
 734                         len = (t_uscalar_t)sizeof (int);
 735                         goto copyout;
 736 
 737                 case SO_RCVBUF:
 738                         value = so->so_rcvbuf;
 739                         len = (t_uscalar_t)sizeof (int);
 740                         goto copyout;
 741 
 742                 case SO_SNDLOWAT:
 743                         value = so->so_sndlowat;
 744                         len = (t_uscalar_t)sizeof (int);
 745                         goto copyout;
 746 
 747                 case SO_RCVLOWAT:
 748                         value = so->so_rcvlowat;
 749                         len = (t_uscalar_t)sizeof (int);
 750                         goto copyout;
 751 
 752                 default:
 753                         option = NULL;
 754                         break;
 755                 }
 756         }
 757         if (maxlen > sizeof (buffer)) {
 758                 optbuf = kmem_alloc(maxlen, KM_SLEEP);
 759         }
 760         optlen = maxlen;
 761         mutex_exit(&so->so_lock);
 762         error = sdp_get_opt((struct sdp_conn_struct_t *)so->so_proto_handle,
 763             level, option_name, optbuf, &optlen);
 764         mutex_enter(&so->so_lock);
 765         ASSERT(optlen <= maxlen);
 766         if (error != 0) {
 767                 if (option == NULL) {
 768                         /* We have no fallback value */
 769                         eprintsoline(so, error);
 770                         goto free;
 771                 }
 772                 error = 0;
 773                 goto copyout;
 774         }
 775 
 776         option = optbuf;
 777         len = optlen;
 778 
 779 copyout:
 780         len = MIN(len, maxlen);
 781         bcopy(option, optval, len);
 782         *optlenp = len;
 783 
 784 free:
 785         if (optbuf != &buffer) {
 786                 kmem_free(optbuf, maxlen);
 787         }
 788 done:
 789         mutex_exit(&so->so_lock);
 790         return (error);
 791 }
 792 
 793 /*
 794  * Set socket options
 795  */
 796 /* ARGSUSED */
 797 static int
 798 sosdp_setsockopt(struct sonode *so, int level, int option_name,
 799     const void *optval, t_uscalar_t optlen, struct cred *cr)
 800 {
 801         void *conn = NULL;
 802         int error = 0;
 803 
 804         if (so->so_state & SS_CANTSENDMORE) {
 805                 return (EINVAL);
 806         }
 807 
 808         mutex_enter(&so->so_lock);
 809         so_lock_single(so);
 810 
 811         if (so->so_type == SOCK_STREAM) {
 812                 conn = (void *)so->so_proto_handle;
 813         }
 814 
 815         dprint(2, ("sosdp_setsockopt (%d) - conn %p %d %d \n",
 816             so->so_type, conn, level, option_name));
 817 
 818         if (conn != NULL) {
 819                 mutex_exit(&so->so_lock);
 820                 error = sdp_set_opt((struct sdp_conn_struct_t *)conn, level,
 821                     option_name, optval, optlen);
 822                 mutex_enter(&so->so_lock);
 823         }
 824 
 825         /*
 826          * Check for SOL_SOCKET options and record their values.
 827          * If we know about a SOL_SOCKET parameter and the transport
 828          * failed it with TBADOPT or TOUTSTATE (i.e. ENOPROTOOPT or
 829          * EPROTO) we let the setsockopt succeed.
 830          */
 831         if (level == SOL_SOCKET) {
 832                 boolean_t handled = B_FALSE;
 833 
 834                 /* Check parameters */
 835                 switch (option_name) {
 836                 case SO_DEBUG:
 837                 case SO_REUSEADDR:
 838                 case SO_KEEPALIVE:
 839                 case SO_DONTROUTE:
 840                 case SO_BROADCAST:
 841                 case SO_USELOOPBACK:
 842                 case SO_OOBINLINE:
 843                 case SO_SNDBUF:
 844                 case SO_RCVBUF:
 845                 case SO_SNDLOWAT:
 846                 case SO_RCVLOWAT:
 847                 case SO_DGRAM_ERRIND:
 848                         if (optlen != (t_uscalar_t)sizeof (int32_t)) {
 849                                 error = EINVAL;
 850                                 eprintsoline(so, error);
 851                                 goto done;
 852                         }
 853                         ASSERT(optval);
 854                         handled = B_TRUE;
 855                         break;
 856                 case SO_LINGER:
 857                         if (optlen != (t_uscalar_t)sizeof (struct linger)) {
 858                                 error = EINVAL;
 859                                 eprintsoline(so, error);
 860                                 goto done;
 861                         }
 862                         ASSERT(optval);
 863                         handled = B_TRUE;
 864                         break;
 865                 }
 866 
 867 #define intvalue (*(int32_t *)optval)
 868 
 869                 switch (option_name) {
 870                 case SO_TYPE:
 871                 case SO_ERROR:
 872                 case SO_ACCEPTCONN:
 873                         /* Can't be set */
 874                         error = ENOPROTOOPT;
 875                         goto done;
 876                 case SO_LINGER: {
 877                         struct linger *l = (struct linger *)optval;
 878 
 879                         so->so_linger.l_linger = l->l_linger;
 880                         if (l->l_onoff) {
 881                                 so->so_linger.l_onoff = SO_LINGER;
 882                                 so->so_options |= SO_LINGER;
 883                         } else {
 884                                 so->so_linger.l_onoff = 0;
 885                                 so->so_options &= ~SO_LINGER;
 886                         }
 887                         break;
 888                 }
 889 
 890                 case SO_DEBUG:
 891                 case SO_REUSEADDR:
 892                 case SO_KEEPALIVE:
 893                 case SO_DONTROUTE:
 894                 case SO_BROADCAST:
 895                 case SO_USELOOPBACK:
 896                 case SO_OOBINLINE:
 897                 case SO_DGRAM_ERRIND:
 898                         if (intvalue != 0) {
 899                                 dprintso(so, 1,
 900                                     ("sosdp_setsockopt: setting 0x%x\n",
 901                                     option_name));
 902                                 so->so_options |= option_name;
 903                         } else {
 904                                 dprintso(so, 1,
 905                                     ("sosdp_setsockopt: clearing 0x%x\n",
 906                                     option_name));
 907                                 so->so_options &= ~option_name;
 908                         }
 909                         break;
 910 
 911                 case SO_SNDBUF:
 912                         so->so_sndbuf = intvalue;
 913                         if (so->so_sndlowat > so->so_sndbuf) {
 914                                 so->so_sndlowat = so->so_sndbuf;
 915                         }
 916                         break;
 917                 case SO_RCVBUF:
 918                         so->so_rcvbuf = intvalue;
 919                         if (so->so_rcvlowat > so->so_rcvbuf) {
 920                                 so->so_rcvlowat = so->so_rcvbuf;
 921                         }
 922                         break;
 923                 case SO_SNDLOWAT:
 924                         if (so->so_sndlowat > so->so_sndbuf) {
 925                                 so->so_sndlowat = so->so_sndbuf;
 926                         }
 927                         break;
 928                 case SO_RCVLOWAT:
 929                         if (so->so_rcvlowat > so->so_rcvbuf) {
 930                                 so->so_rcvlowat = so->so_rcvbuf;
 931                         }
 932                         break;
 933                 }
 934 #undef  intvalue
 935 
 936                 if (error != 0) {
 937                         if ((error == ENOPROTOOPT || error == EPROTO ||
 938                             error == EINVAL) && handled) {
 939                                 dprintso(so, 1,
 940                                     ("sosdp_setsockopt: ignoring error %d "
 941                                     "for 0x%x\n", error, option_name));
 942                                 error = 0;
 943                         }
 944                 }
 945         }
 946 
 947 done:
 948         so_unlock_single(so, SOLOCKED);
 949         mutex_exit(&so->so_lock);
 950 
 951         return (error);
 952 }
 953 
 954 /* ARGSUSED */
 955 static int
 956 sosdp_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode,
 957     struct cred *cr, int32_t *rvalp)
 958 {
 959         int32_t value;
 960         int error, intval;
 961         pid_t pid;
 962 
 963         /* handle socket specific ioctls */
 964         switch (cmd) {
 965         case FIONBIO:
 966                 if (so_copyin((void *)arg, &value, sizeof (int32_t),
 967                     (mode & (int)FKIOCTL))) {
 968                         return (EFAULT);
 969                 }
 970                 mutex_enter(&so->so_lock);
 971                 if (value != 0) {
 972                         so->so_state |= SS_NDELAY;
 973                 } else {
 974                         so->so_state &= ~SS_NDELAY;
 975                 }
 976                 mutex_exit(&so->so_lock);
 977                 return (0);
 978 
 979         case FIOASYNC:
 980                 if (so_copyin((void *)arg, &value, sizeof (int32_t),
 981                     (mode & (int)FKIOCTL))) {
 982                         return (EFAULT);
 983                 }
 984                 mutex_enter(&so->so_lock);
 985 
 986                 if (value) {
 987                         /* Turn on SIGIO */
 988                         so->so_state |= SS_ASYNC;
 989                 } else {
 990                         /* Turn off SIGIO */
 991                         so->so_state &= ~SS_ASYNC;
 992                 }
 993                 mutex_exit(&so->so_lock);
 994                 return (0);
 995 
 996         case SIOCSPGRP:
 997         case FIOSETOWN:
 998                 if (so_copyin((void *)arg, &pid, sizeof (pid_t),
 999                     (mode & (int)FKIOCTL))) {
1000                         return (EFAULT);
1001                 }
1002                 mutex_enter(&so->so_lock);
1003 
1004                 error = (pid != so->so_pgrp) ? socket_chgpgrp(so, pid) : 0;
1005                 mutex_exit(&so->so_lock);
1006                 return (error);
1007 
1008         case SIOCGPGRP:
1009         case FIOGETOWN:
1010                 if (so_copyout(&so->so_pgrp, (void *)arg,
1011                     sizeof (pid_t), (mode & (int)FKIOCTL)))
1012                         return (EFAULT);
1013                 return (0);
1014 
1015         case SIOCATMARK:
1016                 intval = 0;
1017                 error = sdp_ioctl(
1018                     (struct sdp_conn_struct_t *)so->so_proto_handle, cmd,
1019                     &intval, cr);
1020                 if (so_copyout(&intval, (void *)arg, sizeof (int),
1021                     (mode & (int)FKIOCTL)))
1022                         return (EFAULT);
1023                 return (0);
1024 
1025 
1026         case SIOCSENABLESDP: {
1027                 int32_t enable;
1028 
1029                 /*
1030                  * System wide enable SDP
1031                  */
1032 
1033                 if (so_copyin((void *)arg, &enable, sizeof (int32_t),
1034                     mode & (int)FKIOCTL))
1035                         return (EFAULT);
1036 
1037                 error = sdp_ioctl(
1038                     (struct sdp_conn_struct_t *)so->so_proto_handle, cmd,
1039                     &enable, cr);
1040                 if (so_copyout(&enable, (void *)arg,
1041                     sizeof (int32_t), (mode & (int)FKIOCTL)))
1042                         return (EFAULT);
1043                 return (0);
1044         }
1045                 /* from strioctl */
1046         case FIONREAD:
1047                 /*
1048                  * Return number of bytes of data in all data messages
1049                  * in queue in "arg".
1050                  * For stream socket, amount of available data.
1051                  */
1052                 if (so->so_state & SS_ACCEPTCONN) {
1053                         intval = 0;
1054                 } else {
1055                         mutex_enter(&so->so_lock);
1056                         intval = sdp_polldata(
1057                             (struct sdp_conn_struct_t *)so->so_proto_handle,
1058                             SDP_READ);
1059                         mutex_exit(&so->so_lock);
1060                 }
1061                 if (so_copyout(&intval, (void *)arg, sizeof (intval),
1062                     (mode & (int)FKIOCTL)))
1063                         return (EFAULT);
1064                 return (0);
1065         default:
1066                 return (EINVAL);
1067         }
1068 }
1069 
1070 /*
1071  * Check socktpi_poll() on why so_lock is not held in this function.
1072  */
1073 static int
1074 sosdp_poll(struct sonode *so, short events, int anyyet, short *reventsp,
1075     struct pollhead **phpp)
1076 {
1077         short origevents = events;
1078         int so_state;
1079 
1080         so_state = so->so_state;
1081 
1082         ASSERT(so->so_version != SOV_STREAM);
1083 
1084         if (!(so_state & SS_ISCONNECTED) && (so->so_type == SOCK_STREAM)) {
1085                 /*
1086                  * Not connected yet - turn off write side events
1087                  */
1088                 events &= ~(POLLOUT|POLLWRBAND);
1089         }
1090 
1091         /*
1092          * Check for errors
1093          */
1094         if (so->so_error != 0 &&
1095             ((POLLIN|POLLRDNORM|POLLOUT) & origevents)  != 0) {
1096                 *reventsp = (POLLIN|POLLRDNORM|POLLOUT) & origevents;
1097                 return (0);
1098         }
1099 
1100         *reventsp = 0;
1101 
1102         /*
1103          * Don't mark socket as writable until TX queued data is
1104          * below watermark.
1105          */
1106         if (so->so_type == SOCK_STREAM) {
1107                 if (sdp_polldata(
1108                     (struct sdp_conn_struct_t *)so->so_proto_handle,
1109                     SDP_XMIT)) {
1110                         *reventsp |= POLLOUT & events;
1111                 }
1112         } else {
1113                 *reventsp = 0;
1114                 goto done;
1115         }
1116 
1117         if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
1118             SDP_READ)) {
1119                 *reventsp |= (POLLIN|POLLRDNORM) & events;
1120         }
1121 
1122         if ((so_state & SS_CANTRCVMORE) || (so->so_acceptq_len > 0)) {
1123                 *reventsp |= (POLLIN|POLLRDNORM) & events;
1124         }
1125 
1126 done:
1127         if (!*reventsp && !anyyet) {
1128                 *phpp = &so->so_poll_list;
1129         }
1130 
1131         return (0);
1132 }
1133 
1134 /* ARGSUSED */
1135 static int
1136 sosdp_close(struct sonode *so, int flag, struct cred *cr)
1137 {
1138         int error = 0;
1139 
1140         mutex_enter(&so->so_lock);
1141         so_lock_single(so);
1142         /*
1143          * Need to set flags as there might be ops in progress on
1144          * this socket.
1145          *
1146          * If socket already disconnected/disconnecting,
1147          * don't send signal (again).
1148          */
1149         soisdisconnected(so, 0);
1150         mutex_exit(&so->so_lock);
1151 
1152         /*
1153          * Initiate connection shutdown.
1154          */
1155         error = sdp_disconnect((struct sdp_conn_struct_t *)so->so_proto_handle,
1156             flag);
1157 
1158         mutex_enter(&so->so_lock);
1159         so_unlock_single(so, SOLOCKED);
1160         so_notify_disconnected(so, B_FALSE, error);
1161 
1162         return (error);
1163 }
1164 
1165 /* ARGSUSED */
1166 void
1167 sosdp_fini(struct sonode *so, struct cred *cr)
1168 {
1169         dprint(3, ("sosdp_fini: so:%p so_proto_handle:%p", (void *)so,
1170             (void *)so->so_proto_handle));
1171 
1172         ASSERT(so->so_ops == &sosdp_sonodeops);
1173 
1174         if (so->so_proto_handle != NULL)
1175                 sdp_close((struct sdp_conn_struct_t *)so->so_proto_handle);
1176         so->so_proto_handle = NULL;
1177 
1178         mutex_enter(&so->so_lock);
1179 
1180         so_acceptq_flush(so, B_TRUE);
1181 
1182         mutex_exit(&so->so_lock);
1183 
1184         sonode_fini(so);
1185 }
1186 
1187 /*
1188  * Upcalls from SDP
1189  */
1190 
1191 /*
1192  * Incoming connection on listen socket.
1193  */
1194 static void *
1195 sdp_sock_newconn(void *parenthandle, void *connind)
1196 {
1197         struct sonode *lso = parenthandle;
1198         struct sonode *nso;
1199         int error;
1200 
1201         ASSERT(lso->so_state & SS_ACCEPTCONN);
1202         ASSERT(lso->so_proto_handle != NULL); /* closed conn */
1203         ASSERT(lso->so_type == SOCK_STREAM);
1204 
1205         dprint(3, ("sosdp_newconn A: so:%p so_proto_handle:%p", (void *)lso,
1206             (void *)lso->so_proto_handle));
1207 
1208         /*
1209          * Check current # of queued conns against backlog
1210          */
1211         if (lso->so_rcv_queued >= lso->so_backlog) {
1212                 return (NULL);
1213         }
1214 
1215         nso = socket_newconn(lso, connind, NULL, SOCKET_NOSLEEP, &error);
1216         if (nso == NULL) {
1217                 eprintsoline(lso, error);
1218                 return (NULL);
1219         }
1220 
1221         dprint(2, ("sdp_stream_newconn: new %p\n", (void *)nso));
1222 
1223         (void) so_acceptq_enqueue(lso, nso);
1224 
1225         mutex_enter(&lso->so_lock);
1226         so_notify_newconn(lso);
1227         return (nso);
1228 }
1229 
1230 /*
1231  * For outgoing connections, the connection has been established.
1232  */
1233 static void
1234 sdp_sock_connected(void *handle)
1235 {
1236         struct sonode *so = handle;
1237 
1238         ASSERT(so->so_type == SOCK_STREAM);
1239         dprint(3, ("sosdp_connected C: so:%p so_proto_handle:%p", (void *)so,
1240             (void *)so->so_proto_handle));
1241 
1242         mutex_enter(&so->so_lock);
1243         ASSERT(so->so_proto_handle); /* closed conn */
1244 
1245         ASSERT(!(so->so_state & SS_ACCEPTCONN));
1246         soisconnected(so);
1247 
1248         so_notify_connected(so);
1249 }
1250 
1251 /*
1252  * Connection got disconnected. Either with an error, or through
1253  * normal handshake.
1254  */
1255 static void
1256 sdp_sock_disconnected(void *handle, int error)
1257 {
1258         struct sonode *so = handle;
1259 
1260         ASSERT(so->so_type == SOCK_STREAM);
1261         dprint(2, ("sosdp_disconnected C: so:%p so_proto_handle:%p error:%d",
1262             (void *)so, (void *)so->so_proto_handle, error));
1263 
1264         mutex_enter(&so->so_lock);
1265         ASSERT(so->so_proto_handle != NULL); /* closed conn */
1266 
1267         soisdisconnected(so, error);
1268         so_notify_disconnected(so, B_FALSE, error);
1269 }
1270 
1271 /*
1272  * Incoming data.
1273  */
1274 /*ARGSUSED*/
1275 static int
1276 sdp_sock_recv(void *handle, mblk_t *mp, int flags)
1277 {
1278         struct sonode *so = handle;
1279 
1280         ASSERT(so->so_type == SOCK_STREAM);
1281 
1282         mutex_enter(&so->so_lock);
1283         so_notify_data(so, 0);
1284 
1285         return (so->so_rcvbuf);
1286 }
1287 
1288 /*
1289  * TX queued data got acknowledged.
1290  */
1291 static void
1292 sdp_sock_xmitted(void *handle, int writeable)
1293 {
1294         struct sonode *so = handle;
1295 
1296         dprint(4, ("sosdp_sock_xmitted: so:%p so_proto_handle:%p txq:%d",
1297             (void *)so, (void *)so->so_proto_handle, writeable));
1298         mutex_enter(&so->so_lock);
1299         ASSERT(so->so_proto_handle != NULL); /* closed conn */
1300 
1301 
1302         /*
1303          * Only do pollwakeup if the amount of queued data is less than
1304          * watermark.
1305          */
1306         if (!writeable) {
1307                 so_notify_writable(so);
1308         } else {
1309                 mutex_exit(&so->so_lock);
1310         }
1311 }
1312 
1313 
1314 /*
1315  * SDP notifies socket for presence of urgent data.
1316  */
1317 static void
1318 sdp_sock_urgdata(void *handle)
1319 {
1320         struct sonode *so = handle;
1321 
1322         ASSERT(so->so_type == SOCK_STREAM);
1323 
1324         mutex_enter(&so->so_lock);
1325 
1326         ASSERT(so->so_proto_handle != NULL); /* closed conn */
1327         so_notify_oobsig(so);
1328 }
1329 
1330 /*
1331  * SDP notifies socket about receiving of conn close request from peer side.
1332  */
1333 static void
1334 sdp_sock_ordrel(void *handle)
1335 {
1336         struct sonode *so = handle;
1337 
1338         ASSERT(so->so_type == SOCK_STREAM);
1339 
1340         dprint(4, ("sdp_sock_ordrel : so:%p, so_proto_handle:%p",
1341             (void *)so, (void *)so->so_proto_handle));
1342         mutex_enter(&so->so_lock);
1343         socantrcvmore(so);
1344         so_notify_eof(so);
1345 }
1346 
1347 static void
1348 sdp_sock_connfail(void *handle, int error)
1349 {
1350         struct sonode *so = handle;
1351 
1352         dprint(3, ("sosdp_conn Failed: so:%p so_proto_handle:%p", (void *)so,
1353             (void *)so->so_proto_handle));
1354         mutex_enter(&so->so_lock);
1355         ASSERT(so->so_proto_handle != NULL); /* closed conn */
1356         so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
1357         so->so_error = (ushort_t)error;
1358         mutex_exit(&so->so_lock);
1359         cv_broadcast(&so->so_state_cv);
1360 }