Print this page
14685 sotpi ops need to be wary of null v_stream


   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) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2015, Joyent, Inc.
  25  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.

  26  */
  27 
  28 #include <sys/types.h>
  29 #include <sys/t_lock.h>
  30 #include <sys/param.h>
  31 #include <sys/systm.h>
  32 #include <sys/buf.h>
  33 #include <sys/conf.h>
  34 #include <sys/cred.h>
  35 #include <sys/kmem.h>
  36 #include <sys/kmem_impl.h>
  37 #include <sys/sysmacros.h>
  38 #include <sys/vfs.h>
  39 #include <sys/vnode.h>
  40 #include <sys/debug.h>
  41 #include <sys/errno.h>
  42 #include <sys/time.h>
  43 #include <sys/file.h>
  44 #include <sys/open.h>
  45 #include <sys/user.h>


 244 sonodeops_t sotpi_sonodeops = {
 245         sotpi_init,             /* sop_init             */
 246         sotpi_accept,           /* sop_accept           */
 247         sotpi_bind,             /* sop_bind             */
 248         sotpi_listen,           /* sop_listen           */
 249         sotpi_connect,          /* sop_connect          */
 250         sotpi_recvmsg,          /* sop_recvmsg          */
 251         sotpi_sendmsg,          /* sop_sendmsg          */
 252         sotpi_sendmblk,         /* sop_sendmblk         */
 253         sotpi_getpeername,      /* sop_getpeername      */
 254         sotpi_getsockname,      /* sop_getsockname      */
 255         sotpi_shutdown,         /* sop_shutdown         */
 256         sotpi_getsockopt,       /* sop_getsockopt       */
 257         sotpi_setsockopt,       /* sop_setsockopt       */
 258         sotpi_ioctl,            /* sop_ioctl            */
 259         sotpi_poll,             /* sop_poll             */
 260         sotpi_close,            /* sop_close            */
 261 };
 262 
 263 /*



















 264  * Return a TPI socket vnode.
 265  *
 266  * Note that sockets assume that the driver will clone (either itself
 267  * or by using the clone driver) i.e. a socket() call will always
 268  * result in a new vnode being created.
 269  */
 270 
 271 /*
 272  * Common create code for socket and accept. If tso is set the values
 273  * from that node is used instead of issuing a T_INFO_REQ.
 274  */
 275 
 276 /* ARGSUSED */
 277 static struct sonode *
 278 sotpi_create(struct sockparams *sp, int family, int type, int protocol,
 279     int version, int sflags, int *errorp, cred_t *cr)
 280 {
 281         struct sonode   *so;
 282         kmem_cache_t    *cp;
 283         int             sfamily = family;


 986                         if (error) {
 987                                 if (error == EEXIST)
 988                                         error = EADDRINUSE;
 989                                 eprintsoline(so, error);
 990                                 goto done;
 991                         }
 992                         /*
 993                          * Establish pointer from the underlying filesystem
 994                          * vnode to the socket node.
 995                          * sti_ux_bound_vp and v_stream->sd_vnode form the
 996                          * cross-linkage between the underlying filesystem
 997                          * node and the socket node.
 998                          */
 999 
1000                         if ((VOP_REALVP(vp, &rvp, NULL) == 0) && (vp != rvp)) {
1001                                 VN_HOLD(rvp);
1002                                 VN_RELE(vp);
1003                                 vp = rvp;
1004                         }
1005 
1006                         ASSERT(SOTOV(so)->v_stream);
1007                         mutex_enter(&vp->v_lock);
1008                         vp->v_stream = SOTOV(so)->v_stream;
1009                         sti->sti_ux_bound_vp = vp;
1010                         mutex_exit(&vp->v_lock);
1011 
1012                         /*
1013                          * Use the vnode pointer value as a unique address
1014                          * (together with the magic number to avoid conflicts
1015                          * with implicit binds) in the transport provider.
1016                          */
1017                         sti->sti_ux_laddr.soua_vp =
1018                             (void *)sti->sti_ux_bound_vp;
1019                         sti->sti_ux_laddr.soua_magic = SOU_MAGIC_EXPLICIT;
1020                         addr = &sti->sti_ux_laddr;
1021                         addrlen = (t_uscalar_t)sizeof (sti->sti_ux_laddr);
1022                         dprintso(so, 1, ("sobind UNIX: addrlen %d, addr %p\n",
1023                             addrlen,
1024                             (void *)((struct so_ux_addr *)addr)->soua_vp));
1025                         break;
1026                 }


4951                         return (strwrite_common(SOTOV(so), uiop, cr, wflag));
4952                 }
4953         }
4954         return (0);
4955 }
4956 
4957 /*
4958  * Update sti_faddr by asking the transport (unless AF_UNIX).
4959  */
4960 /* ARGSUSED */
4961 int
4962 sotpi_getpeername(struct sonode *so, struct sockaddr *name, socklen_t *namelen,
4963     boolean_t accept, struct cred *cr)
4964 {
4965         struct strbuf   strbuf;
4966         int             error = 0, res;
4967         void            *addr;
4968         t_uscalar_t     addrlen;
4969         k_sigset_t      smask;
4970         sotpi_info_t    *sti = SOTOTPI(so);

4971 
4972         dprintso(so, 1, ("sotpi_getpeername(%p) %s\n",
4973             (void *)so, pr_state(so->so_state, so->so_mode)));
4974 
4975         ASSERT(*namelen > 0);
4976         mutex_enter(&so->so_lock);
4977         so_lock_single(so);     /* Set SOLOCKED */





4978 
4979         if (accept) {
4980                 bcopy(sti->sti_faddr_sa, name,
4981                     MIN(*namelen, sti->sti_faddr_len));
4982                 *namelen = sti->sti_faddr_noxlate ? 0: sti->sti_faddr_len;
4983                 goto done;
4984         }
4985 
4986         if (!(so->so_state & SS_ISCONNECTED)) {
4987                 error = ENOTCONN;
4988                 goto done;
4989         }
4990         /* Added this check for X/Open */
4991         if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
4992                 error = EINVAL;
4993                 if (xnet_check_print) {
4994                         printf("sockfs: X/Open getpeername check => EINVAL\n");
4995                 }
4996                 goto done;
4997         }


5022         ASSERT(sti->sti_faddr_sa);
5023         /* Allocate local buffer to use with ioctl */
5024         addrlen = (t_uscalar_t)sti->sti_faddr_maxlen;
5025         mutex_exit(&so->so_lock);
5026         addr = kmem_alloc(addrlen, KM_SLEEP);
5027 
5028         /*
5029          * Issue TI_GETPEERNAME with signals masked.
5030          * Put the result in sti_faddr_sa so that getpeername works after
5031          * a shutdown(output).
5032          * If the ioctl fails (e.g. due to a ECONNRESET) the error is reposted
5033          * back to the socket.
5034          */
5035         strbuf.buf = addr;
5036         strbuf.maxlen = addrlen;
5037         strbuf.len = 0;
5038 
5039         sigintr(&smask, 0);
5040         res = 0;
5041         ASSERT(cr);
5042         error = strioctl(SOTOV(so), TI_GETPEERNAME, (intptr_t)&strbuf,
5043             0, K_TO_K, cr, &res);
5044         sigunintr(&smask);
5045 
5046         mutex_enter(&so->so_lock);
5047         /*
5048          * If there is an error record the error in so_error put don't fail
5049          * the getpeername. Instead fallback on the recorded
5050          * sti->sti_faddr_sa.
5051          */
5052         if (error) {
5053                 /*
5054                  * Various stream head errors can be returned to the ioctl.
5055                  * However, it is impossible to determine which ones of
5056                  * these are really socket level errors that were incorrectly
5057                  * consumed by the ioctl. Thus this code silently ignores the
5058                  * error - to code explicitly does not reinstate the error
5059                  * using soseterror().
5060                  * Experiments have shows that at least this set of
5061                  * errors are reported and should not be reinstated on the
5062                  * socket:


5087 #endif /* DEBUG */
5088 done:
5089         so_unlock_single(so, SOLOCKED);
5090         mutex_exit(&so->so_lock);
5091         return (error);
5092 }
5093 
5094 /*
5095  * Update sti_laddr by asking the transport (unless AF_UNIX).
5096  */
5097 int
5098 sotpi_getsockname(struct sonode *so, struct sockaddr *name, socklen_t *namelen,
5099     struct cred *cr)
5100 {
5101         struct strbuf   strbuf;
5102         int             error = 0, res;
5103         void            *addr;
5104         t_uscalar_t     addrlen;
5105         k_sigset_t      smask;
5106         sotpi_info_t    *sti = SOTOTPI(so);

5107 
5108         dprintso(so, 1, ("sotpi_getsockname(%p) %s\n",
5109             (void *)so, pr_state(so->so_state, so->so_mode)));
5110 
5111         ASSERT(*namelen > 0);
5112         mutex_enter(&so->so_lock);
5113         so_lock_single(so);     /* Set SOLOCKED */





5114 
5115 #ifdef DEBUG
5116 
5117         dprintso(so, 1, ("sotpi_getsockname (local): %s\n",
5118             pr_addr(so->so_family, sti->sti_laddr_sa,
5119             (t_uscalar_t)sti->sti_laddr_len)));
5120 #endif /* DEBUG */
5121         if (sti->sti_laddr_valid) {
5122                 bcopy(sti->sti_laddr_sa, name,
5123                     MIN(*namelen, sti->sti_laddr_len));
5124                 *namelen = sti->sti_laddr_len;
5125                 goto done;
5126         }
5127 
5128         if (so->so_family == AF_UNIX) {
5129                 /*
5130                  * Transport has different name space - return local info. If we
5131                  * have enough space, let consumers know the family.
5132                  */
5133                 if (*namelen >= sizeof (sa_family_t)) {


5147 
5148         /* Allocate local buffer to use with ioctl */
5149         addrlen = (t_uscalar_t)sti->sti_laddr_maxlen;
5150         mutex_exit(&so->so_lock);
5151         addr = kmem_alloc(addrlen, KM_SLEEP);
5152 
5153         /*
5154          * Issue TI_GETMYNAME with signals masked.
5155          * Put the result in sti_laddr_sa so that getsockname works after
5156          * a shutdown(output).
5157          * If the ioctl fails (e.g. due to a ECONNRESET) the error is reposted
5158          * back to the socket.
5159          */
5160         strbuf.buf = addr;
5161         strbuf.maxlen = addrlen;
5162         strbuf.len = 0;
5163 
5164         sigintr(&smask, 0);
5165         res = 0;
5166         ASSERT(cr);
5167         error = strioctl(SOTOV(so), TI_GETMYNAME, (intptr_t)&strbuf,
5168             0, K_TO_K, cr, &res);
5169         sigunintr(&smask);
5170 
5171         mutex_enter(&so->so_lock);
5172         /*
5173          * If there is an error record the error in so_error put don't fail
5174          * the getsockname. Instead fallback on the recorded
5175          * sti->sti_laddr_sa.
5176          */
5177         if (error) {
5178                 /*
5179                  * Various stream head errors can be returned to the ioctl.
5180                  * However, it is impossible to determine which ones of
5181                  * these are really socket level errors that were incorrectly
5182                  * consumed by the ioctl. Thus this code silently ignores the
5183                  * error - to code explicitly does not reinstate the error
5184                  * using soseterror().
5185                  * Experiments have shows that at least this set of
5186                  * errors are reported and should not be reinstated on the
5187                  * socket:


5221  * On the return most *optlenp bytes are copied to optval.
5222  */
5223 /* ARGSUSED */
5224 int
5225 sotpi_getsockopt(struct sonode *so, int level, int option_name,
5226     void *optval, socklen_t *optlenp, int flags, struct cred *cr)
5227 {
5228         struct T_optmgmt_req    optmgmt_req;
5229         struct T_optmgmt_ack    *optmgmt_ack;
5230         struct opthdr           oh;
5231         struct opthdr           *opt_res;
5232         mblk_t                  *mp = NULL;
5233         int                     error = 0;
5234         void                    *option = NULL; /* Set if fallback value */
5235         t_uscalar_t             maxlen = *optlenp;
5236         t_uscalar_t             len;
5237         uint32_t                value;
5238         struct timeval          tmo_val; /* used for SO_RCVTIMEO, SO_SNDTIMEO */
5239         struct timeval32        tmo_val32;
5240         struct so_snd_bufinfo   snd_bufinfo;    /* used for zero copy */

5241 
5242         dprintso(so, 1, ("sotpi_getsockopt(%p, 0x%x, 0x%x, %p, %p) %s\n",
5243             (void *)so, level, option_name, optval, (void *)optlenp,
5244             pr_state(so->so_state, so->so_mode)));
5245 
5246         mutex_enter(&so->so_lock);
5247         so_lock_single(so);     /* Set SOLOCKED */






5248 
5249         /*
5250          * Check for SOL_SOCKET options.
5251          * Certain SOL_SOCKET options are returned directly whereas
5252          * others only provide a default (fallback) value should
5253          * the T_SVR4_OPTMGMT_REQ fail.
5254          */
5255         if (level == SOL_SOCKET) {
5256                 /* Check parameters */
5257                 switch (option_name) {
5258                 case SO_TYPE:
5259                 case SO_ERROR:
5260                 case SO_DEBUG:
5261                 case SO_ACCEPTCONN:
5262                 case SO_REUSEADDR:
5263                 case SO_KEEPALIVE:
5264                 case SO_DONTROUTE:
5265                 case SO_BROADCAST:
5266                 case SO_USELOOPBACK:
5267                 case SO_OOBINLINE:


5372                 /*
5373                  * The following options are only returned by sockfs when the
5374                  * T_SVR4_OPTMGMT_REQ fails.
5375                  */
5376                 case SO_LINGER:
5377                         option = &so->so_linger;
5378                         len = (t_uscalar_t)sizeof (struct linger);
5379                         break;
5380                 case SO_SNDBUF: {
5381                         ssize_t lvalue;
5382 
5383                         /*
5384                          * If the option has not been set then get a default
5385                          * value from the read queue. This value is
5386                          * returned if the transport fails
5387                          * the T_SVR4_OPTMGMT_REQ.
5388                          */
5389                         lvalue = so->so_sndbuf;
5390                         if (lvalue == 0) {
5391                                 mutex_exit(&so->so_lock);
5392                                 (void) strqget(strvp2wq(SOTOV(so))->q_next,
5393                                     QHIWAT, 0, &lvalue);
5394                                 mutex_enter(&so->so_lock);
5395                                 dprintso(so, 1,
5396                                     ("got SO_SNDBUF %ld from q\n", lvalue));
5397                         }
5398                         value = (int)lvalue;
5399                         option = &value;
5400                         len = (t_uscalar_t)sizeof (so->so_sndbuf);
5401                         break;
5402                 }
5403                 case SO_RCVBUF: {
5404                         ssize_t lvalue;
5405 
5406                         /*
5407                          * If the option has not been set then get a default
5408                          * value from the read queue. This value is
5409                          * returned if the transport fails
5410                          * the T_SVR4_OPTMGMT_REQ.
5411                          *
5412                          * XXX If SO_RCVBUF has been set and this is an
5413                          * XPG 4.2 application then do not ask the transport
5414                          * since the transport might adjust the value and not
5415                          * return exactly what was set by the application.
5416                          * For non-XPG 4.2 application we return the value
5417                          * that the transport is actually using.
5418                          */
5419                         lvalue = so->so_rcvbuf;
5420                         if (lvalue == 0) {
5421                                 mutex_exit(&so->so_lock);
5422                                 (void) strqget(RD(strvp2wq(SOTOV(so))),
5423                                     QHIWAT, 0, &lvalue);
5424                                 mutex_enter(&so->so_lock);
5425                                 dprintso(so, 1,
5426                                     ("got SO_RCVBUF %ld from q\n", lvalue));
5427                         } else if (flags & _SOGETSOCKOPT_XPG4_2) {
5428                                 value = (int)lvalue;
5429                                 option = &value;
5430                                 goto copyout;   /* skip asking transport */
5431                         }
5432                         value = (int)lvalue;
5433                         option = &value;
5434                         len = (t_uscalar_t)sizeof (so->so_rcvbuf);
5435                         break;
5436                 }
5437                 case SO_DOMAIN:
5438                         value = so->so_family;
5439                         option = &value;
5440                         goto copyout; /* No need to issue T_SVR4_OPTMGMT_REQ */
5441 
5442 #ifdef notyet


5488                         break;
5489                 }
5490                 }
5491         }
5492 
5493         mutex_exit(&so->so_lock);
5494 
5495         /* Send request */
5496         optmgmt_req.PRIM_type = T_SVR4_OPTMGMT_REQ;
5497         optmgmt_req.MGMT_flags = T_CHECK;
5498         optmgmt_req.OPT_length = (t_scalar_t)(sizeof (oh) + maxlen);
5499         optmgmt_req.OPT_offset = (t_scalar_t)sizeof (optmgmt_req);
5500 
5501         oh.level = level;
5502         oh.name = option_name;
5503         oh.len = maxlen;
5504 
5505         mp = soallocproto3(&optmgmt_req, sizeof (optmgmt_req),
5506             &oh, sizeof (oh), NULL, maxlen, 0, _ALLOC_SLEEP, cr);
5507         /* Let option management work in the presence of data flow control */
5508         error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
5509             MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0);
5510         mp = NULL;
5511         mutex_enter(&so->so_lock);
5512         if (error) {
5513                 eprintsoline(so, error);
5514                 goto done2;
5515         }
5516         error = sowaitprim(so, T_SVR4_OPTMGMT_REQ, T_OPTMGMT_ACK,
5517             (t_uscalar_t)(sizeof (*optmgmt_ack) + sizeof (*opt_res)), &mp, 0);
5518         if (error) {
5519                 if (option != NULL) {
5520                         /* We have a fallback value */
5521                         error = 0;
5522                         goto copyout;
5523                 }
5524                 eprintsoline(so, error);
5525                 goto done2;
5526         }
5527         ASSERT(mp);
5528         optmgmt_ack = (struct T_optmgmt_ack *)mp->b_rptr;




   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) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2015, Joyent, Inc.
  25  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  26  * Copyright 2022 MNX Cloud, Inc.
  27  */
  28 
  29 #include <sys/types.h>
  30 #include <sys/t_lock.h>
  31 #include <sys/param.h>
  32 #include <sys/systm.h>
  33 #include <sys/buf.h>
  34 #include <sys/conf.h>
  35 #include <sys/cred.h>
  36 #include <sys/kmem.h>
  37 #include <sys/kmem_impl.h>
  38 #include <sys/sysmacros.h>
  39 #include <sys/vfs.h>
  40 #include <sys/vnode.h>
  41 #include <sys/debug.h>
  42 #include <sys/errno.h>
  43 #include <sys/time.h>
  44 #include <sys/file.h>
  45 #include <sys/open.h>
  46 #include <sys/user.h>


 245 sonodeops_t sotpi_sonodeops = {
 246         sotpi_init,             /* sop_init             */
 247         sotpi_accept,           /* sop_accept           */
 248         sotpi_bind,             /* sop_bind             */
 249         sotpi_listen,           /* sop_listen           */
 250         sotpi_connect,          /* sop_connect          */
 251         sotpi_recvmsg,          /* sop_recvmsg          */
 252         sotpi_sendmsg,          /* sop_sendmsg          */
 253         sotpi_sendmblk,         /* sop_sendmblk         */
 254         sotpi_getpeername,      /* sop_getpeername      */
 255         sotpi_getsockname,      /* sop_getsockname      */
 256         sotpi_shutdown,         /* sop_shutdown         */
 257         sotpi_getsockopt,       /* sop_getsockopt       */
 258         sotpi_setsockopt,       /* sop_setsockopt       */
 259         sotpi_ioctl,            /* sop_ioctl            */
 260         sotpi_poll,             /* sop_poll             */
 261         sotpi_close,            /* sop_close            */
 262 };
 263 
 264 /*
 265  * Post-close reality check for NULL v_stream...
 266  *
 267  * Kernel callers (e.g. in procfs) may attempt socket operations, after
 268  * holding the vnode, after it has been closed.  For TPI sockets, post-close
 269  * operations will have a NULL v_stream (which all functions here assume
 270  * or even ASSERT() is non-NULL).  See sotpi_close for where we wipe it out.
 271  *
 272  * If we are in a state where we lost a race to close(), we need to stop ASAP,
 273  * and return the acceptable-as-an-errno EBADF.  Because cleanup may be
 274  * required, this macro only checks the v_stream.
 275  *
 276  * Checking should only be relevant for in-kernel other-thread inspectors.
 277  * Userland ones (i.e. same process that opened the socktpi socket) SHOULD be
 278  * protected by higher-level mechanisms. The only in-kernel inspector in the
 279  * source base is procfs, which only accesses get{sockname,peername,sockopt}().
 280  */
 281 #define SOTPI_VN_NOSTREAM(vn) ((vn)->v_stream == NULL)
 282 
 283 /*
 284  * Return a TPI socket vnode.
 285  *
 286  * Note that sockets assume that the driver will clone (either itself
 287  * or by using the clone driver) i.e. a socket() call will always
 288  * result in a new vnode being created.
 289  */
 290 
 291 /*
 292  * Common create code for socket and accept. If tso is set the values
 293  * from that node is used instead of issuing a T_INFO_REQ.
 294  */
 295 
 296 /* ARGSUSED */
 297 static struct sonode *
 298 sotpi_create(struct sockparams *sp, int family, int type, int protocol,
 299     int version, int sflags, int *errorp, cred_t *cr)
 300 {
 301         struct sonode   *so;
 302         kmem_cache_t    *cp;
 303         int             sfamily = family;


1006                         if (error) {
1007                                 if (error == EEXIST)
1008                                         error = EADDRINUSE;
1009                                 eprintsoline(so, error);
1010                                 goto done;
1011                         }
1012                         /*
1013                          * Establish pointer from the underlying filesystem
1014                          * vnode to the socket node.
1015                          * sti_ux_bound_vp and v_stream->sd_vnode form the
1016                          * cross-linkage between the underlying filesystem
1017                          * node and the socket node.
1018                          */
1019 
1020                         if ((VOP_REALVP(vp, &rvp, NULL) == 0) && (vp != rvp)) {
1021                                 VN_HOLD(rvp);
1022                                 VN_RELE(vp);
1023                                 vp = rvp;
1024                         }
1025 
1026                         ASSERT(SOTOV(so)->v_stream != NULL);
1027                         mutex_enter(&vp->v_lock);
1028                         vp->v_stream = SOTOV(so)->v_stream;
1029                         sti->sti_ux_bound_vp = vp;
1030                         mutex_exit(&vp->v_lock);
1031 
1032                         /*
1033                          * Use the vnode pointer value as a unique address
1034                          * (together with the magic number to avoid conflicts
1035                          * with implicit binds) in the transport provider.
1036                          */
1037                         sti->sti_ux_laddr.soua_vp =
1038                             (void *)sti->sti_ux_bound_vp;
1039                         sti->sti_ux_laddr.soua_magic = SOU_MAGIC_EXPLICIT;
1040                         addr = &sti->sti_ux_laddr;
1041                         addrlen = (t_uscalar_t)sizeof (sti->sti_ux_laddr);
1042                         dprintso(so, 1, ("sobind UNIX: addrlen %d, addr %p\n",
1043                             addrlen,
1044                             (void *)((struct so_ux_addr *)addr)->soua_vp));
1045                         break;
1046                 }


4971                         return (strwrite_common(SOTOV(so), uiop, cr, wflag));
4972                 }
4973         }
4974         return (0);
4975 }
4976 
4977 /*
4978  * Update sti_faddr by asking the transport (unless AF_UNIX).
4979  */
4980 /* ARGSUSED */
4981 int
4982 sotpi_getpeername(struct sonode *so, struct sockaddr *name, socklen_t *namelen,
4983     boolean_t accept, struct cred *cr)
4984 {
4985         struct strbuf   strbuf;
4986         int             error = 0, res;
4987         void            *addr;
4988         t_uscalar_t     addrlen;
4989         k_sigset_t      smask;
4990         sotpi_info_t    *sti = SOTOTPI(so);
4991         vnode_t         *vn;
4992 
4993         dprintso(so, 1, ("sotpi_getpeername(%p) %s\n",
4994             (void *)so, pr_state(so->so_state, so->so_mode)));
4995 
4996         ASSERT(*namelen > 0);
4997         mutex_enter(&so->so_lock);
4998         so_lock_single(so);     /* Set SOLOCKED */
4999         vn = SOTOV(so);
5000         if (SOTPI_VN_NOSTREAM(vn)) {
5001                 error = EBADF;
5002                 goto done;
5003         }
5004 
5005         if (accept) {
5006                 bcopy(sti->sti_faddr_sa, name,
5007                     MIN(*namelen, sti->sti_faddr_len));
5008                 *namelen = sti->sti_faddr_noxlate ? 0: sti->sti_faddr_len;
5009                 goto done;
5010         }
5011 
5012         if (!(so->so_state & SS_ISCONNECTED)) {
5013                 error = ENOTCONN;
5014                 goto done;
5015         }
5016         /* Added this check for X/Open */
5017         if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
5018                 error = EINVAL;
5019                 if (xnet_check_print) {
5020                         printf("sockfs: X/Open getpeername check => EINVAL\n");
5021                 }
5022                 goto done;
5023         }


5048         ASSERT(sti->sti_faddr_sa);
5049         /* Allocate local buffer to use with ioctl */
5050         addrlen = (t_uscalar_t)sti->sti_faddr_maxlen;
5051         mutex_exit(&so->so_lock);
5052         addr = kmem_alloc(addrlen, KM_SLEEP);
5053 
5054         /*
5055          * Issue TI_GETPEERNAME with signals masked.
5056          * Put the result in sti_faddr_sa so that getpeername works after
5057          * a shutdown(output).
5058          * If the ioctl fails (e.g. due to a ECONNRESET) the error is reposted
5059          * back to the socket.
5060          */
5061         strbuf.buf = addr;
5062         strbuf.maxlen = addrlen;
5063         strbuf.len = 0;
5064 
5065         sigintr(&smask, 0);
5066         res = 0;
5067         ASSERT(cr);
5068         error = strioctl(vn, TI_GETPEERNAME, (intptr_t)&strbuf,
5069             0, K_TO_K, cr, &res);
5070         sigunintr(&smask);
5071 
5072         mutex_enter(&so->so_lock);
5073         /*
5074          * If there is an error record the error in so_error put don't fail
5075          * the getpeername. Instead fallback on the recorded
5076          * sti->sti_faddr_sa.
5077          */
5078         if (error) {
5079                 /*
5080                  * Various stream head errors can be returned to the ioctl.
5081                  * However, it is impossible to determine which ones of
5082                  * these are really socket level errors that were incorrectly
5083                  * consumed by the ioctl. Thus this code silently ignores the
5084                  * error - to code explicitly does not reinstate the error
5085                  * using soseterror().
5086                  * Experiments have shows that at least this set of
5087                  * errors are reported and should not be reinstated on the
5088                  * socket:


5113 #endif /* DEBUG */
5114 done:
5115         so_unlock_single(so, SOLOCKED);
5116         mutex_exit(&so->so_lock);
5117         return (error);
5118 }
5119 
5120 /*
5121  * Update sti_laddr by asking the transport (unless AF_UNIX).
5122  */
5123 int
5124 sotpi_getsockname(struct sonode *so, struct sockaddr *name, socklen_t *namelen,
5125     struct cred *cr)
5126 {
5127         struct strbuf   strbuf;
5128         int             error = 0, res;
5129         void            *addr;
5130         t_uscalar_t     addrlen;
5131         k_sigset_t      smask;
5132         sotpi_info_t    *sti = SOTOTPI(so);
5133         vnode_t         *vn;
5134 
5135         dprintso(so, 1, ("sotpi_getsockname(%p) %s\n",
5136             (void *)so, pr_state(so->so_state, so->so_mode)));
5137 
5138         ASSERT(*namelen > 0);
5139         mutex_enter(&so->so_lock);
5140         so_lock_single(so);     /* Set SOLOCKED */
5141         vn = SOTOV(so);
5142         if (SOTPI_VN_NOSTREAM(vn)) {
5143                 error = EBADF;
5144                 goto done;
5145         }
5146 
5147 #ifdef DEBUG
5148 
5149         dprintso(so, 1, ("sotpi_getsockname (local): %s\n",
5150             pr_addr(so->so_family, sti->sti_laddr_sa,
5151             (t_uscalar_t)sti->sti_laddr_len)));
5152 #endif /* DEBUG */
5153         if (sti->sti_laddr_valid) {
5154                 bcopy(sti->sti_laddr_sa, name,
5155                     MIN(*namelen, sti->sti_laddr_len));
5156                 *namelen = sti->sti_laddr_len;
5157                 goto done;
5158         }
5159 
5160         if (so->so_family == AF_UNIX) {
5161                 /*
5162                  * Transport has different name space - return local info. If we
5163                  * have enough space, let consumers know the family.
5164                  */
5165                 if (*namelen >= sizeof (sa_family_t)) {


5179 
5180         /* Allocate local buffer to use with ioctl */
5181         addrlen = (t_uscalar_t)sti->sti_laddr_maxlen;
5182         mutex_exit(&so->so_lock);
5183         addr = kmem_alloc(addrlen, KM_SLEEP);
5184 
5185         /*
5186          * Issue TI_GETMYNAME with signals masked.
5187          * Put the result in sti_laddr_sa so that getsockname works after
5188          * a shutdown(output).
5189          * If the ioctl fails (e.g. due to a ECONNRESET) the error is reposted
5190          * back to the socket.
5191          */
5192         strbuf.buf = addr;
5193         strbuf.maxlen = addrlen;
5194         strbuf.len = 0;
5195 
5196         sigintr(&smask, 0);
5197         res = 0;
5198         ASSERT(cr);
5199         error = strioctl(vn, TI_GETMYNAME, (intptr_t)&strbuf,
5200             0, K_TO_K, cr, &res);
5201         sigunintr(&smask);
5202 
5203         mutex_enter(&so->so_lock);
5204         /*
5205          * If there is an error record the error in so_error put don't fail
5206          * the getsockname. Instead fallback on the recorded
5207          * sti->sti_laddr_sa.
5208          */
5209         if (error) {
5210                 /*
5211                  * Various stream head errors can be returned to the ioctl.
5212                  * However, it is impossible to determine which ones of
5213                  * these are really socket level errors that were incorrectly
5214                  * consumed by the ioctl. Thus this code silently ignores the
5215                  * error - to code explicitly does not reinstate the error
5216                  * using soseterror().
5217                  * Experiments have shows that at least this set of
5218                  * errors are reported and should not be reinstated on the
5219                  * socket:


5253  * On the return most *optlenp bytes are copied to optval.
5254  */
5255 /* ARGSUSED */
5256 int
5257 sotpi_getsockopt(struct sonode *so, int level, int option_name,
5258     void *optval, socklen_t *optlenp, int flags, struct cred *cr)
5259 {
5260         struct T_optmgmt_req    optmgmt_req;
5261         struct T_optmgmt_ack    *optmgmt_ack;
5262         struct opthdr           oh;
5263         struct opthdr           *opt_res;
5264         mblk_t                  *mp = NULL;
5265         int                     error = 0;
5266         void                    *option = NULL; /* Set if fallback value */
5267         t_uscalar_t             maxlen = *optlenp;
5268         t_uscalar_t             len;
5269         uint32_t                value;
5270         struct timeval          tmo_val; /* used for SO_RCVTIMEO, SO_SNDTIMEO */
5271         struct timeval32        tmo_val32;
5272         struct so_snd_bufinfo   snd_bufinfo;    /* used for zero copy */
5273         vnode_t                 *vn;
5274 
5275         dprintso(so, 1, ("sotpi_getsockopt(%p, 0x%x, 0x%x, %p, %p) %s\n",
5276             (void *)so, level, option_name, optval, (void *)optlenp,
5277             pr_state(so->so_state, so->so_mode)));
5278 
5279         mutex_enter(&so->so_lock);
5280         so_lock_single(so);     /* Set SOLOCKED */
5281         vn = SOTOV(so);
5282         if (SOTPI_VN_NOSTREAM(vn)) {
5283                 error = EBADF;
5284                 eprintsoline(so, error);
5285                 goto done2;
5286         }
5287 
5288         /*
5289          * Check for SOL_SOCKET options.
5290          * Certain SOL_SOCKET options are returned directly whereas
5291          * others only provide a default (fallback) value should
5292          * the T_SVR4_OPTMGMT_REQ fail.
5293          */
5294         if (level == SOL_SOCKET) {
5295                 /* Check parameters */
5296                 switch (option_name) {
5297                 case SO_TYPE:
5298                 case SO_ERROR:
5299                 case SO_DEBUG:
5300                 case SO_ACCEPTCONN:
5301                 case SO_REUSEADDR:
5302                 case SO_KEEPALIVE:
5303                 case SO_DONTROUTE:
5304                 case SO_BROADCAST:
5305                 case SO_USELOOPBACK:
5306                 case SO_OOBINLINE:


5411                 /*
5412                  * The following options are only returned by sockfs when the
5413                  * T_SVR4_OPTMGMT_REQ fails.
5414                  */
5415                 case SO_LINGER:
5416                         option = &so->so_linger;
5417                         len = (t_uscalar_t)sizeof (struct linger);
5418                         break;
5419                 case SO_SNDBUF: {
5420                         ssize_t lvalue;
5421 
5422                         /*
5423                          * If the option has not been set then get a default
5424                          * value from the read queue. This value is
5425                          * returned if the transport fails
5426                          * the T_SVR4_OPTMGMT_REQ.
5427                          */
5428                         lvalue = so->so_sndbuf;
5429                         if (lvalue == 0) {
5430                                 mutex_exit(&so->so_lock);
5431                                 (void) strqget(strvp2wq(vn)->q_next,
5432                                     QHIWAT, 0, &lvalue);
5433                                 mutex_enter(&so->so_lock);
5434                                 dprintso(so, 1,
5435                                     ("got SO_SNDBUF %ld from q\n", lvalue));
5436                         }
5437                         value = (int)lvalue;
5438                         option = &value;
5439                         len = (t_uscalar_t)sizeof (so->so_sndbuf);
5440                         break;
5441                 }
5442                 case SO_RCVBUF: {
5443                         ssize_t lvalue;
5444 
5445                         /*
5446                          * If the option has not been set then get a default
5447                          * value from the read queue. This value is
5448                          * returned if the transport fails
5449                          * the T_SVR4_OPTMGMT_REQ.
5450                          *
5451                          * XXX If SO_RCVBUF has been set and this is an
5452                          * XPG 4.2 application then do not ask the transport
5453                          * since the transport might adjust the value and not
5454                          * return exactly what was set by the application.
5455                          * For non-XPG 4.2 application we return the value
5456                          * that the transport is actually using.
5457                          */
5458                         lvalue = so->so_rcvbuf;
5459                         if (lvalue == 0) {
5460                                 mutex_exit(&so->so_lock);
5461                                 (void) strqget(RD(strvp2wq(vn)),
5462                                     QHIWAT, 0, &lvalue);
5463                                 mutex_enter(&so->so_lock);
5464                                 dprintso(so, 1,
5465                                     ("got SO_RCVBUF %ld from q\n", lvalue));
5466                         } else if (flags & _SOGETSOCKOPT_XPG4_2) {
5467                                 value = (int)lvalue;
5468                                 option = &value;
5469                                 goto copyout;   /* skip asking transport */
5470                         }
5471                         value = (int)lvalue;
5472                         option = &value;
5473                         len = (t_uscalar_t)sizeof (so->so_rcvbuf);
5474                         break;
5475                 }
5476                 case SO_DOMAIN:
5477                         value = so->so_family;
5478                         option = &value;
5479                         goto copyout; /* No need to issue T_SVR4_OPTMGMT_REQ */
5480 
5481 #ifdef notyet


5527                         break;
5528                 }
5529                 }
5530         }
5531 
5532         mutex_exit(&so->so_lock);
5533 
5534         /* Send request */
5535         optmgmt_req.PRIM_type = T_SVR4_OPTMGMT_REQ;
5536         optmgmt_req.MGMT_flags = T_CHECK;
5537         optmgmt_req.OPT_length = (t_scalar_t)(sizeof (oh) + maxlen);
5538         optmgmt_req.OPT_offset = (t_scalar_t)sizeof (optmgmt_req);
5539 
5540         oh.level = level;
5541         oh.name = option_name;
5542         oh.len = maxlen;
5543 
5544         mp = soallocproto3(&optmgmt_req, sizeof (optmgmt_req),
5545             &oh, sizeof (oh), NULL, maxlen, 0, _ALLOC_SLEEP, cr);
5546         /* Let option management work in the presence of data flow control */
5547         error = kstrputmsg(vn, mp, NULL, 0, 0,
5548             MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0);
5549         mp = NULL;
5550         mutex_enter(&so->so_lock);
5551         if (error) {
5552                 eprintsoline(so, error);
5553                 goto done2;
5554         }
5555         error = sowaitprim(so, T_SVR4_OPTMGMT_REQ, T_OPTMGMT_ACK,
5556             (t_uscalar_t)(sizeof (*optmgmt_ack) + sizeof (*opt_res)), &mp, 0);
5557         if (error) {
5558                 if (option != NULL) {
5559                         /* We have a fallback value */
5560                         error = 0;
5561                         goto copyout;
5562                 }
5563                 eprintsoline(so, error);
5564                 goto done2;
5565         }
5566         ASSERT(mp);
5567         optmgmt_ack = (struct T_optmgmt_ack *)mp->b_rptr;