Print this page
OS-3752 Increase IOV_MAX to at least 1024
OS-3404 lx brand must support sendmsg() with IOV_MAX of 1024


   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) 1995, 2010, Oracle and/or its affiliates. All rights reserved.


  24  */
  25 
  26 /* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
  27 /*
  28  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/t_lock.h>
  33 #include <sys/param.h>
  34 #include <sys/systm.h>
  35 #include <sys/buf.h>
  36 #include <sys/conf.h>
  37 #include <sys/cred.h>
  38 #include <sys/kmem.h>
  39 #include <sys/sysmacros.h>
  40 #include <sys/vfs.h>
  41 #include <sys/vnode.h>
  42 #include <sys/debug.h>
  43 #include <sys/errno.h>
  44 #include <sys/time.h>
  45 #include <sys/file.h>
  46 #include <sys/user.h>
  47 #include <sys/stream.h>
  48 #include <sys/strsubr.h>
  49 #include <sys/strsun.h>
  50 #include <sys/sunddi.h>
  51 #include <sys/esunddi.h>
  52 #include <sys/flock.h>
  53 #include <sys/modctl.h>
  54 #include <sys/cmn_err.h>
  55 #include <sys/vmsystm.h>
  56 #include <sys/policy.h>

  57 
  58 #include <sys/socket.h>
  59 #include <sys/socketvar.h>
  60 
  61 #include <sys/isa_defs.h>
  62 #include <sys/inttypes.h>
  63 #include <sys/systm.h>
  64 #include <sys/cpuvar.h>
  65 #include <sys/filio.h>
  66 #include <sys/sendfile.h>
  67 #include <sys/ddi.h>
  68 #include <vm/seg.h>
  69 #include <vm/seg_map.h>
  70 #include <vm/seg_kpm.h>
  71 
  72 #include <fs/sockfs/nl7c.h>
  73 #include <fs/sockfs/sockcommon.h>
  74 #include <fs/sockfs/sockfilter_impl.h>
  75 #include <fs/sockfs/socktpi.h>
  76 
  77 #ifdef SOCK_TEST
  78 int do_useracc = 1;             /* Controlled by setting SO_DEBUG to 4 */
  79 #else
  80 #define do_useracc      1
  81 #endif /* SOCK_TEST */
  82 
  83 extern int      xnet_truncate_print;
  84 
  85 extern void     nl7c_init(void);
  86 extern int      sockfs_defer_nl7c_init;
  87 
  88 /*
  89  * Note: DEF_IOV_MAX is defined and used as it is in "fs/vncalls.c"
  90  *       as there isn't a formal definition of IOV_MAX ???
  91  */
  92 #define MSG_MAXIOVLEN   16
  93 
  94 /*
  95  * Kernel component of socket creation.
  96  *
  97  * The socket library determines which version number to use.
  98  * First the library calls this with a NULL devpath. If this fails
  99  * to find a transport (using solookup) the library will look in /etc/netconfig
 100  * for the appropriate transport. If one is found it will pass in the
 101  * devpath for the kernel to use.
 102  */
 103 int
 104 so_socket(int family, int type_w_flags, int protocol, char *devpath,
 105     int version)
 106 {
 107         struct sonode *so;
 108         vnode_t *vp;
 109         struct file *fp;
 110         int fd;
 111         int error;
 112         int type;
 113 
 114         type = type_w_flags & SOCK_TYPE_MASK;


1009         } else {
1010                 lmsg.msg_namelen = 0;
1011         }
1012         lmsg.msg_controllen = 0;
1013         lmsg.msg_flags = 0;
1014 
1015         return (recvit(sock, &lmsg, &auio, flags, namelenp, NULL, NULL));
1016 }
1017 
1018 /*
1019  * Uses the MSG_XPG4_2 flag to determine if the caller is using
1020  * struct omsghdr or struct nmsghdr.
1021  */
1022 ssize_t
1023 recvmsg(int sock, struct nmsghdr *msg, int flags)
1024 {
1025         STRUCT_DECL(nmsghdr, u_lmsg);
1026         STRUCT_HANDLE(nmsghdr, umsgptr);
1027         struct nmsghdr lmsg;
1028         struct uio auio;
1029         struct iovec aiov[MSG_MAXIOVLEN];

1030         int iovcnt;
1031         ssize_t len;
1032         int i;
1033         int *flagsp;
1034         model_t model;
1035 
1036         dprint(1, ("recvmsg(%d, %p, %d)\n",
1037             sock, (void *)msg, flags));
1038 
1039         model = get_udatamodel();
1040         STRUCT_INIT(u_lmsg, model);
1041         STRUCT_SET_HANDLE(umsgptr, model, msg);
1042 
1043         if (flags & MSG_XPG4_2) {
1044                 if (copyin(msg, STRUCT_BUF(u_lmsg), STRUCT_SIZE(u_lmsg)))
1045                         return (set_errno(EFAULT));
1046                 flagsp = STRUCT_FADDR(umsgptr, msg_flags);
1047         } else {
1048                 /*
1049                  * Assumes that nmsghdr and omsghdr are identically shaped
1050                  * except for the added msg_flags field.
1051                  */


1054                         return (set_errno(EFAULT));
1055                 STRUCT_FSET(u_lmsg, msg_flags, 0);
1056                 flagsp = NULL;
1057         }
1058 
1059         /*
1060          * Code below us will kmem_alloc memory and hang it
1061          * off msg_control and msg_name fields. This forces
1062          * us to copy the structure to its native form.
1063          */
1064         lmsg.msg_name = STRUCT_FGETP(u_lmsg, msg_name);
1065         lmsg.msg_namelen = STRUCT_FGET(u_lmsg, msg_namelen);
1066         lmsg.msg_iov = STRUCT_FGETP(u_lmsg, msg_iov);
1067         lmsg.msg_iovlen = STRUCT_FGET(u_lmsg, msg_iovlen);
1068         lmsg.msg_control = STRUCT_FGETP(u_lmsg, msg_control);
1069         lmsg.msg_controllen = STRUCT_FGET(u_lmsg, msg_controllen);
1070         lmsg.msg_flags = STRUCT_FGET(u_lmsg, msg_flags);
1071 
1072         iovcnt = lmsg.msg_iovlen;
1073 
1074         if (iovcnt <= 0 || iovcnt > MSG_MAXIOVLEN) {
1075                 return (set_errno(EMSGSIZE));
1076         }
1077 





1078 #ifdef _SYSCALL32_IMPL
1079         /*
1080          * 32-bit callers need to have their iovec expanded, while ensuring
1081          * that they can't move more than 2Gbytes of data in a single call.
1082          */
1083         if (model == DATAMODEL_ILP32) {
1084                 struct iovec32 aiov32[MSG_MAXIOVLEN];

1085                 ssize32_t count32;
1086 
1087                 if (copyin((struct iovec32 *)lmsg.msg_iov, aiov32,
1088                     iovcnt * sizeof (struct iovec32)))








1089                         return (set_errno(EFAULT));

1090 
1091                 count32 = 0;
1092                 for (i = 0; i < iovcnt; i++) {
1093                         ssize32_t iovlen32;
1094 
1095                         iovlen32 = aiov32[i].iov_len;
1096                         count32 += iovlen32;
1097                         if (iovlen32 < 0 || count32 < 0)





1098                                 return (set_errno(EINVAL));


1099                         aiov[i].iov_len = iovlen32;
1100                         aiov[i].iov_base =
1101                             (caddr_t)(uintptr_t)aiov32[i].iov_base;
1102                 }



1103         } else
1104 #endif /* _SYSCALL32_IMPL */
1105         if (copyin(lmsg.msg_iov, aiov, iovcnt * sizeof (struct iovec))) {



1106                 return (set_errno(EFAULT));
1107         }
1108         len = 0;
1109         for (i = 0; i < iovcnt; i++) {
1110                 ssize_t iovlen = aiov[i].iov_len;
1111                 len += iovlen;
1112                 if (iovlen < 0 || len < 0) {



1113                         return (set_errno(EINVAL));
1114                 }
1115         }
1116         auio.uio_loffset = 0;
1117         auio.uio_iov = aiov;
1118         auio.uio_iovcnt = iovcnt;
1119         auio.uio_resid = len;
1120         auio.uio_segflg = UIO_USERSPACE;
1121         auio.uio_limit = 0;
1122 
1123         if (lmsg.msg_control != NULL &&
1124             (do_useracc == 0 ||
1125             useracc(lmsg.msg_control, lmsg.msg_controllen,
1126             B_WRITE) != 0)) {



1127                 return (set_errno(EFAULT));
1128         }
1129 
1130         return (recvit(sock, &lmsg, &auio, flags,
1131             STRUCT_FADDR(umsgptr, msg_namelen),
1132             STRUCT_FADDR(umsgptr, msg_controllen), flagsp));





1133 }
1134 
1135 /*
1136  * Common send function.
1137  */
1138 static ssize_t
1139 sendit(int sock, struct nmsghdr *msg, struct uio *uiop, int flags)
1140 {
1141         struct sonode *so;
1142         file_t *fp;
1143         void *name;
1144         socklen_t namelen;
1145         void *control;
1146         socklen_t controllen;
1147         ssize_t len;
1148         int error;
1149 
1150         if ((so = getsonode(sock, &error, &fp)) == NULL)
1151                 return (set_errno(error));
1152 


1250         if (!(flags & MSG_XPG4_2)) {
1251                 /*
1252                  * In order to be compatible with the libsocket/sockmod
1253                  * implementation we set EOR for all send* calls.
1254                  */
1255                 flags |= MSG_EOR;
1256         }
1257         return (sendit(sock, &lmsg, &auio, flags));
1258 }
1259 
1260 /*
1261  * Uses the MSG_XPG4_2 flag to determine if the caller is using
1262  * struct omsghdr or struct nmsghdr.
1263  */
1264 ssize_t
1265 sendmsg(int sock, struct nmsghdr *msg, int flags)
1266 {
1267         struct nmsghdr lmsg;
1268         STRUCT_DECL(nmsghdr, u_lmsg);
1269         struct uio auio;
1270         struct iovec aiov[MSG_MAXIOVLEN];

1271         int iovcnt;
1272         ssize_t len;
1273         int i;
1274         model_t model;
1275 
1276         dprint(1, ("sendmsg(%d, %p, %d)\n", sock, (void *)msg, flags));
1277 
1278         model = get_udatamodel();
1279         STRUCT_INIT(u_lmsg, model);
1280 
1281         if (flags & MSG_XPG4_2) {
1282                 if (copyin(msg, (char *)STRUCT_BUF(u_lmsg),
1283                     STRUCT_SIZE(u_lmsg)))
1284                         return (set_errno(EFAULT));
1285         } else {
1286                 /*
1287                  * Assumes that nmsghdr and omsghdr are identically shaped
1288                  * except for the added msg_flags field.
1289                  */
1290                 if (copyin(msg, (char *)STRUCT_BUF(u_lmsg),
1291                     SIZEOF_STRUCT(omsghdr, model)))
1292                         return (set_errno(EFAULT));


1295                  * implementation we set EOR for all send* calls.
1296                  */
1297                 flags |= MSG_EOR;
1298         }
1299 
1300         /*
1301          * Code below us will kmem_alloc memory and hang it
1302          * off msg_control and msg_name fields. This forces
1303          * us to copy the structure to its native form.
1304          */
1305         lmsg.msg_name = STRUCT_FGETP(u_lmsg, msg_name);
1306         lmsg.msg_namelen = STRUCT_FGET(u_lmsg, msg_namelen);
1307         lmsg.msg_iov = STRUCT_FGETP(u_lmsg, msg_iov);
1308         lmsg.msg_iovlen = STRUCT_FGET(u_lmsg, msg_iovlen);
1309         lmsg.msg_control = STRUCT_FGETP(u_lmsg, msg_control);
1310         lmsg.msg_controllen = STRUCT_FGET(u_lmsg, msg_controllen);
1311         lmsg.msg_flags = STRUCT_FGET(u_lmsg, msg_flags);
1312 
1313         iovcnt = lmsg.msg_iovlen;
1314 
1315         if (iovcnt <= 0 || iovcnt > MSG_MAXIOVLEN) {
1316                 /*
1317                  * Unless this is XPG 4.2 we allow iovcnt == 0 to
1318                  * be compatible with SunOS 4.X and 4.4BSD.
1319                  */
1320                 if (iovcnt != 0 || (flags & MSG_XPG4_2))
1321                         return (set_errno(EMSGSIZE));
1322         }
1323 





1324 #ifdef _SYSCALL32_IMPL
1325         /*
1326          * 32-bit callers need to have their iovec expanded, while ensuring
1327          * that they can't move more than 2Gbytes of data in a single call.
1328          */
1329         if (model == DATAMODEL_ILP32) {
1330                 struct iovec32 aiov32[MSG_MAXIOVLEN];

1331                 ssize32_t count32;
1332 




1333                 if (iovcnt != 0 &&
1334                     copyin((struct iovec32 *)lmsg.msg_iov, aiov32,
1335                     iovcnt * sizeof (struct iovec32)))




1336                         return (set_errno(EFAULT));

1337 
1338                 count32 = 0;
1339                 for (i = 0; i < iovcnt; i++) {
1340                         ssize32_t iovlen32;
1341 
1342                         iovlen32 = aiov32[i].iov_len;
1343                         count32 += iovlen32;
1344                         if (iovlen32 < 0 || count32 < 0)





1345                                 return (set_errno(EINVAL));


1346                         aiov[i].iov_len = iovlen32;
1347                         aiov[i].iov_base =
1348                             (caddr_t)(uintptr_t)aiov32[i].iov_base;
1349                 }



1350         } else
1351 #endif /* _SYSCALL32_IMPL */
1352         if (iovcnt != 0 &&
1353             copyin(lmsg.msg_iov, aiov,
1354             (unsigned)iovcnt * sizeof (struct iovec))) {



1355                 return (set_errno(EFAULT));
1356         }
1357         len = 0;
1358         for (i = 0; i < iovcnt; i++) {
1359                 ssize_t iovlen = aiov[i].iov_len;
1360                 len += iovlen;
1361                 if (iovlen < 0 || len < 0) {



1362                         return (set_errno(EINVAL));
1363                 }
1364         }
1365         auio.uio_loffset = 0;
1366         auio.uio_iov = aiov;
1367         auio.uio_iovcnt = iovcnt;
1368         auio.uio_resid = len;
1369         auio.uio_segflg = UIO_USERSPACE;
1370         auio.uio_limit = 0;
1371 
1372         return (sendit(sock, &lmsg, &auio, flags));





1373 }
1374 
1375 ssize_t
1376 sendto(int sock, void *buffer, size_t len, int flags,
1377     struct sockaddr *name, socklen_t namelen)
1378 {
1379         struct nmsghdr lmsg;
1380         struct uio auio;
1381         struct iovec aiov[1];
1382 
1383         dprint(1, ("sendto(%d, %p, %ld, %d, %p, %d)\n",
1384             sock, buffer, len, flags, (void *)name, namelen));
1385 
1386         if ((ssize_t)len < 0) {
1387                 return (set_errno(EINVAL));
1388         }
1389 
1390         aiov[0].iov_base = buffer;
1391         aiov[0].iov_len = len;
1392         auio.uio_loffset = 0;




   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) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
  25  * Copyright 2015, Joyent, Inc.  All rights reserved.
  26  */
  27 
  28 /* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
  29 /*
  30  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  31  */
  32 
  33 #include <sys/types.h>
  34 #include <sys/t_lock.h>
  35 #include <sys/param.h>
  36 #include <sys/systm.h>
  37 #include <sys/buf.h>
  38 #include <sys/conf.h>
  39 #include <sys/cred.h>
  40 #include <sys/kmem.h>
  41 #include <sys/sysmacros.h>
  42 #include <sys/vfs.h>
  43 #include <sys/vnode.h>
  44 #include <sys/debug.h>
  45 #include <sys/errno.h>
  46 #include <sys/time.h>
  47 #include <sys/file.h>
  48 #include <sys/user.h>
  49 #include <sys/stream.h>
  50 #include <sys/strsubr.h>
  51 #include <sys/strsun.h>
  52 #include <sys/sunddi.h>
  53 #include <sys/esunddi.h>
  54 #include <sys/flock.h>
  55 #include <sys/modctl.h>
  56 #include <sys/cmn_err.h>
  57 #include <sys/vmsystm.h>
  58 #include <sys/policy.h>
  59 #include <sys/limits.h>
  60 
  61 #include <sys/socket.h>
  62 #include <sys/socketvar.h>
  63 
  64 #include <sys/isa_defs.h>
  65 #include <sys/inttypes.h>
  66 #include <sys/systm.h>
  67 #include <sys/cpuvar.h>
  68 #include <sys/filio.h>
  69 #include <sys/sendfile.h>
  70 #include <sys/ddi.h>
  71 #include <vm/seg.h>
  72 #include <vm/seg_map.h>
  73 #include <vm/seg_kpm.h>
  74 
  75 #include <fs/sockfs/nl7c.h>
  76 #include <fs/sockfs/sockcommon.h>
  77 #include <fs/sockfs/sockfilter_impl.h>
  78 #include <fs/sockfs/socktpi.h>
  79 
  80 #ifdef SOCK_TEST
  81 int do_useracc = 1;             /* Controlled by setting SO_DEBUG to 4 */
  82 #else
  83 #define do_useracc      1
  84 #endif /* SOCK_TEST */
  85 
  86 extern int      xnet_truncate_print;
  87 
  88 extern void     nl7c_init(void);
  89 extern int      sockfs_defer_nl7c_init;
  90 
  91 /*






  92  * Kernel component of socket creation.
  93  *
  94  * The socket library determines which version number to use.
  95  * First the library calls this with a NULL devpath. If this fails
  96  * to find a transport (using solookup) the library will look in /etc/netconfig
  97  * for the appropriate transport. If one is found it will pass in the
  98  * devpath for the kernel to use.
  99  */
 100 int
 101 so_socket(int family, int type_w_flags, int protocol, char *devpath,
 102     int version)
 103 {
 104         struct sonode *so;
 105         vnode_t *vp;
 106         struct file *fp;
 107         int fd;
 108         int error;
 109         int type;
 110 
 111         type = type_w_flags & SOCK_TYPE_MASK;


1006         } else {
1007                 lmsg.msg_namelen = 0;
1008         }
1009         lmsg.msg_controllen = 0;
1010         lmsg.msg_flags = 0;
1011 
1012         return (recvit(sock, &lmsg, &auio, flags, namelenp, NULL, NULL));
1013 }
1014 
1015 /*
1016  * Uses the MSG_XPG4_2 flag to determine if the caller is using
1017  * struct omsghdr or struct nmsghdr.
1018  */
1019 ssize_t
1020 recvmsg(int sock, struct nmsghdr *msg, int flags)
1021 {
1022         STRUCT_DECL(nmsghdr, u_lmsg);
1023         STRUCT_HANDLE(nmsghdr, umsgptr);
1024         struct nmsghdr lmsg;
1025         struct uio auio;
1026         struct iovec buf[IOV_MAX_STACK], *aiov = buf;
1027         ssize_t iovsize = 0;
1028         int iovcnt;
1029         ssize_t len, rval;
1030         int i;
1031         int *flagsp;
1032         model_t model;
1033 
1034         dprint(1, ("recvmsg(%d, %p, %d)\n",
1035             sock, (void *)msg, flags));
1036 
1037         model = get_udatamodel();
1038         STRUCT_INIT(u_lmsg, model);
1039         STRUCT_SET_HANDLE(umsgptr, model, msg);
1040 
1041         if (flags & MSG_XPG4_2) {
1042                 if (copyin(msg, STRUCT_BUF(u_lmsg), STRUCT_SIZE(u_lmsg)))
1043                         return (set_errno(EFAULT));
1044                 flagsp = STRUCT_FADDR(umsgptr, msg_flags);
1045         } else {
1046                 /*
1047                  * Assumes that nmsghdr and omsghdr are identically shaped
1048                  * except for the added msg_flags field.
1049                  */


1052                         return (set_errno(EFAULT));
1053                 STRUCT_FSET(u_lmsg, msg_flags, 0);
1054                 flagsp = NULL;
1055         }
1056 
1057         /*
1058          * Code below us will kmem_alloc memory and hang it
1059          * off msg_control and msg_name fields. This forces
1060          * us to copy the structure to its native form.
1061          */
1062         lmsg.msg_name = STRUCT_FGETP(u_lmsg, msg_name);
1063         lmsg.msg_namelen = STRUCT_FGET(u_lmsg, msg_namelen);
1064         lmsg.msg_iov = STRUCT_FGETP(u_lmsg, msg_iov);
1065         lmsg.msg_iovlen = STRUCT_FGET(u_lmsg, msg_iovlen);
1066         lmsg.msg_control = STRUCT_FGETP(u_lmsg, msg_control);
1067         lmsg.msg_controllen = STRUCT_FGET(u_lmsg, msg_controllen);
1068         lmsg.msg_flags = STRUCT_FGET(u_lmsg, msg_flags);
1069 
1070         iovcnt = lmsg.msg_iovlen;
1071 
1072         if (iovcnt <= 0 || iovcnt > IOV_MAX) {
1073                 return (set_errno(EMSGSIZE));
1074         }
1075 
1076         if (iovcnt > IOV_MAX_STACK) {
1077                 iovsize = iovcnt * sizeof (struct iovec);
1078                 aiov = kmem_alloc(iovsize, KM_SLEEP);
1079         }
1080 
1081 #ifdef _SYSCALL32_IMPL
1082         /*
1083          * 32-bit callers need to have their iovec expanded, while ensuring
1084          * that they can't move more than 2Gbytes of data in a single call.
1085          */
1086         if (model == DATAMODEL_ILP32) {
1087                 struct iovec32 buf32[IOV_MAX_STACK], *aiov32 = buf32;
1088                 ssize_t iov32size;
1089                 ssize32_t count32;
1090 
1091                 iov32size = iovcnt * sizeof (struct iovec32);
1092                 if (iovsize != 0)
1093                         aiov32 = kmem_alloc(iov32size, KM_SLEEP);
1094 
1095                 if (copyin((struct iovec32 *)lmsg.msg_iov, aiov32, iov32size)) {
1096                         if (iovsize != 0) {
1097                                 kmem_free(aiov32, iov32size);
1098                                 kmem_free(aiov, iovsize);
1099                         }
1100 
1101                         return (set_errno(EFAULT));
1102                 }
1103 
1104                 count32 = 0;
1105                 for (i = 0; i < iovcnt; i++) {
1106                         ssize32_t iovlen32;
1107 
1108                         iovlen32 = aiov32[i].iov_len;
1109                         count32 += iovlen32;
1110                         if (iovlen32 < 0 || count32 < 0) {
1111                                 if (iovsize != 0) {
1112                                         kmem_free(aiov32, iov32size);
1113                                         kmem_free(aiov, iovsize);
1114                                 }
1115 
1116                                 return (set_errno(EINVAL));
1117                         }
1118 
1119                         aiov[i].iov_len = iovlen32;
1120                         aiov[i].iov_base =
1121                             (caddr_t)(uintptr_t)aiov32[i].iov_base;
1122                 }
1123 
1124                 if (iovsize != 0)
1125                         kmem_free(aiov32, iov32size);
1126         } else
1127 #endif /* _SYSCALL32_IMPL */
1128         if (copyin(lmsg.msg_iov, aiov, iovcnt * sizeof (struct iovec))) {
1129                 if (iovsize != 0)
1130                         kmem_free(aiov, iovsize);
1131 
1132                 return (set_errno(EFAULT));
1133         }
1134         len = 0;
1135         for (i = 0; i < iovcnt; i++) {
1136                 ssize_t iovlen = aiov[i].iov_len;
1137                 len += iovlen;
1138                 if (iovlen < 0 || len < 0) {
1139                         if (iovsize != 0)
1140                                 kmem_free(aiov, iovsize);
1141 
1142                         return (set_errno(EINVAL));
1143                 }
1144         }
1145         auio.uio_loffset = 0;
1146         auio.uio_iov = aiov;
1147         auio.uio_iovcnt = iovcnt;
1148         auio.uio_resid = len;
1149         auio.uio_segflg = UIO_USERSPACE;
1150         auio.uio_limit = 0;
1151 
1152         if (lmsg.msg_control != NULL &&
1153             (do_useracc == 0 ||
1154             useracc(lmsg.msg_control, lmsg.msg_controllen,
1155             B_WRITE) != 0)) {
1156                 if (iovsize != 0)
1157                         kmem_free(aiov, iovsize);
1158 
1159                 return (set_errno(EFAULT));
1160         }
1161 
1162         rval = recvit(sock, &lmsg, &auio, flags,
1163             STRUCT_FADDR(umsgptr, msg_namelen),
1164             STRUCT_FADDR(umsgptr, msg_controllen), flagsp);
1165 
1166         if (iovsize != 0)
1167                 kmem_free(aiov, iovsize);
1168 
1169         return (rval);
1170 }
1171 
1172 /*
1173  * Common send function.
1174  */
1175 static ssize_t
1176 sendit(int sock, struct nmsghdr *msg, struct uio *uiop, int flags)
1177 {
1178         struct sonode *so;
1179         file_t *fp;
1180         void *name;
1181         socklen_t namelen;
1182         void *control;
1183         socklen_t controllen;
1184         ssize_t len;
1185         int error;
1186 
1187         if ((so = getsonode(sock, &error, &fp)) == NULL)
1188                 return (set_errno(error));
1189 


1287         if (!(flags & MSG_XPG4_2)) {
1288                 /*
1289                  * In order to be compatible with the libsocket/sockmod
1290                  * implementation we set EOR for all send* calls.
1291                  */
1292                 flags |= MSG_EOR;
1293         }
1294         return (sendit(sock, &lmsg, &auio, flags));
1295 }
1296 
1297 /*
1298  * Uses the MSG_XPG4_2 flag to determine if the caller is using
1299  * struct omsghdr or struct nmsghdr.
1300  */
1301 ssize_t
1302 sendmsg(int sock, struct nmsghdr *msg, int flags)
1303 {
1304         struct nmsghdr lmsg;
1305         STRUCT_DECL(nmsghdr, u_lmsg);
1306         struct uio auio;
1307         struct iovec buf[IOV_MAX_STACK], *aiov = buf;
1308         ssize_t iovsize = 0;
1309         int iovcnt;
1310         ssize_t len, rval;
1311         int i;
1312         model_t model;
1313 
1314         dprint(1, ("sendmsg(%d, %p, %d)\n", sock, (void *)msg, flags));
1315 
1316         model = get_udatamodel();
1317         STRUCT_INIT(u_lmsg, model);
1318 
1319         if (flags & MSG_XPG4_2) {
1320                 if (copyin(msg, (char *)STRUCT_BUF(u_lmsg),
1321                     STRUCT_SIZE(u_lmsg)))
1322                         return (set_errno(EFAULT));
1323         } else {
1324                 /*
1325                  * Assumes that nmsghdr and omsghdr are identically shaped
1326                  * except for the added msg_flags field.
1327                  */
1328                 if (copyin(msg, (char *)STRUCT_BUF(u_lmsg),
1329                     SIZEOF_STRUCT(omsghdr, model)))
1330                         return (set_errno(EFAULT));


1333                  * implementation we set EOR for all send* calls.
1334                  */
1335                 flags |= MSG_EOR;
1336         }
1337 
1338         /*
1339          * Code below us will kmem_alloc memory and hang it
1340          * off msg_control and msg_name fields. This forces
1341          * us to copy the structure to its native form.
1342          */
1343         lmsg.msg_name = STRUCT_FGETP(u_lmsg, msg_name);
1344         lmsg.msg_namelen = STRUCT_FGET(u_lmsg, msg_namelen);
1345         lmsg.msg_iov = STRUCT_FGETP(u_lmsg, msg_iov);
1346         lmsg.msg_iovlen = STRUCT_FGET(u_lmsg, msg_iovlen);
1347         lmsg.msg_control = STRUCT_FGETP(u_lmsg, msg_control);
1348         lmsg.msg_controllen = STRUCT_FGET(u_lmsg, msg_controllen);
1349         lmsg.msg_flags = STRUCT_FGET(u_lmsg, msg_flags);
1350 
1351         iovcnt = lmsg.msg_iovlen;
1352 
1353         if (iovcnt <= 0 || iovcnt > IOV_MAX) {
1354                 /*
1355                  * Unless this is XPG 4.2 we allow iovcnt == 0 to
1356                  * be compatible with SunOS 4.X and 4.4BSD.
1357                  */
1358                 if (iovcnt != 0 || (flags & MSG_XPG4_2))
1359                         return (set_errno(EMSGSIZE));
1360         }
1361 
1362         if (iovcnt > IOV_MAX_STACK) {
1363                 iovsize = iovcnt * sizeof (struct iovec);
1364                 aiov = kmem_alloc(iovsize, KM_SLEEP);
1365         }
1366 
1367 #ifdef _SYSCALL32_IMPL
1368         /*
1369          * 32-bit callers need to have their iovec expanded, while ensuring
1370          * that they can't move more than 2Gbytes of data in a single call.
1371          */
1372         if (model == DATAMODEL_ILP32) {
1373                 struct iovec32 buf32[IOV_MAX_STACK], *aiov32 = buf32;
1374                 ssize_t iov32size;
1375                 ssize32_t count32;
1376 
1377                 iov32size = iovcnt * sizeof (struct iovec32);
1378                 if (iovsize != 0)
1379                         aiov32 = kmem_alloc(iov32size, KM_SLEEP);
1380 
1381                 if (iovcnt != 0 &&
1382                     copyin((struct iovec32 *)lmsg.msg_iov, aiov32, iov32size)) {
1383                         if (iovsize != 0) {
1384                                 kmem_free(aiov32, iov32size);
1385                                 kmem_free(aiov, iovsize);
1386                         }
1387 
1388                         return (set_errno(EFAULT));
1389                 }
1390 
1391                 count32 = 0;
1392                 for (i = 0; i < iovcnt; i++) {
1393                         ssize32_t iovlen32;
1394 
1395                         iovlen32 = aiov32[i].iov_len;
1396                         count32 += iovlen32;
1397                         if (iovlen32 < 0 || count32 < 0) {
1398                                 if (iovsize != 0) {
1399                                         kmem_free(aiov32, iov32size);
1400                                         kmem_free(aiov, iovsize);
1401                                 }
1402 
1403                                 return (set_errno(EINVAL));
1404                         }
1405 
1406                         aiov[i].iov_len = iovlen32;
1407                         aiov[i].iov_base =
1408                             (caddr_t)(uintptr_t)aiov32[i].iov_base;
1409                 }
1410 
1411                 if (iovsize != 0)
1412                         kmem_free(aiov32, iov32size);
1413         } else
1414 #endif /* _SYSCALL32_IMPL */
1415         if (iovcnt != 0 &&
1416             copyin(lmsg.msg_iov, aiov,
1417             (unsigned)iovcnt * sizeof (struct iovec))) {
1418                 if (iovsize != 0)
1419                         kmem_free(aiov, iovsize);
1420 
1421                 return (set_errno(EFAULT));
1422         }
1423         len = 0;
1424         for (i = 0; i < iovcnt; i++) {
1425                 ssize_t iovlen = aiov[i].iov_len;
1426                 len += iovlen;
1427                 if (iovlen < 0 || len < 0) {
1428                         if (iovsize != 0)
1429                                 kmem_free(aiov, iovsize);
1430 
1431                         return (set_errno(EINVAL));
1432                 }
1433         }
1434         auio.uio_loffset = 0;
1435         auio.uio_iov = aiov;
1436         auio.uio_iovcnt = iovcnt;
1437         auio.uio_resid = len;
1438         auio.uio_segflg = UIO_USERSPACE;
1439         auio.uio_limit = 0;
1440 
1441         rval = sendit(sock, &lmsg, &auio, flags);
1442 
1443         if (iovsize != 0)
1444                 kmem_free(aiov, iovsize);
1445 
1446         return (rval);
1447 }
1448 
1449 ssize_t
1450 sendto(int sock, void *buffer, size_t len, int flags,
1451     struct sockaddr *name, socklen_t namelen)
1452 {
1453         struct nmsghdr lmsg;
1454         struct uio auio;
1455         struct iovec aiov[1];
1456 
1457         dprint(1, ("sendto(%d, %p, %ld, %d, %p, %d)\n",
1458             sock, buffer, len, flags, (void *)name, namelen));
1459 
1460         if ((ssize_t)len < 0) {
1461                 return (set_errno(EINVAL));
1462         }
1463 
1464         aiov[0].iov_base = buffer;
1465         aiov[0].iov_len = len;
1466         auio.uio_loffset = 0;