10f1702c5SYu Xiangning /* 20f1702c5SYu Xiangning * CDDL HEADER START 30f1702c5SYu Xiangning * 40f1702c5SYu Xiangning * The contents of this file are subject to the terms of the 50f1702c5SYu Xiangning * Common Development and Distribution License (the "License"). 60f1702c5SYu Xiangning * You may not use this file except in compliance with the License. 70f1702c5SYu Xiangning * 80f1702c5SYu Xiangning * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90f1702c5SYu Xiangning * or http://www.opensolaris.org/os/licensing. 100f1702c5SYu Xiangning * See the License for the specific language governing permissions 110f1702c5SYu Xiangning * and limitations under the License. 120f1702c5SYu Xiangning * 130f1702c5SYu Xiangning * When distributing Covered Code, include this CDDL HEADER in each 140f1702c5SYu Xiangning * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150f1702c5SYu Xiangning * If applicable, add the following below this CDDL HEADER, with the 160f1702c5SYu Xiangning * fields enclosed by brackets "[]" replaced with your own identifying 170f1702c5SYu Xiangning * information: Portions Copyright [yyyy] [name of copyright owner] 180f1702c5SYu Xiangning * 190f1702c5SYu Xiangning * CDDL HEADER END 200f1702c5SYu Xiangning */ 210f1702c5SYu Xiangning 220f1702c5SYu Xiangning /* 23*de8c4a14SErik Nordmark * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 240f1702c5SYu Xiangning * Use is subject to license terms. 250f1702c5SYu Xiangning */ 260f1702c5SYu Xiangning 270f1702c5SYu Xiangning #include <sys/file.h> 280f1702c5SYu Xiangning #include <sys/stropts.h> 290f1702c5SYu Xiangning #include <sys/socket.h> 300f1702c5SYu Xiangning #include <sys/socketvar.h> 310f1702c5SYu Xiangning #include <sys/sysmacros.h> 320f1702c5SYu Xiangning #include <sys/filio.h> /* FIO* ioctls */ 330f1702c5SYu Xiangning #include <sys/sockio.h> /* SIOC* ioctls */ 340f1702c5SYu Xiangning #include <sys/cmn_err.h> 350f1702c5SYu Xiangning #include <sys/ksocket.h> 360f1702c5SYu Xiangning #include <io/ksocket/ksocket_impl.h> 370f1702c5SYu Xiangning #include <fs/sockfs/sockcommon.h> 380f1702c5SYu Xiangning 390f1702c5SYu Xiangning #define SOCKETMOD_TCP "tcp" 400f1702c5SYu Xiangning #define SOCKETMOD_UDP "udp" 410f1702c5SYu Xiangning /* 420f1702c5SYu Xiangning * Kernel Sockets 430f1702c5SYu Xiangning * 440f1702c5SYu Xiangning * Mostly a wrapper around the private socket_* functions. 450f1702c5SYu Xiangning */ 460f1702c5SYu Xiangning int 470f1702c5SYu Xiangning ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags, 480f1702c5SYu Xiangning struct cred *cr) 490f1702c5SYu Xiangning { 500f1702c5SYu Xiangning static const int version = SOV_DEFAULT; 510f1702c5SYu Xiangning int error = 0; 520f1702c5SYu Xiangning struct sonode *so; 530f1702c5SYu Xiangning *ksp = NULL; 540f1702c5SYu Xiangning 55*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 56*de8c4a14SErik Nordmark ASSERT(cr != NULL); 57*de8c4a14SErik Nordmark 580f1702c5SYu Xiangning if (domain == AF_NCA || domain == AF_UNIX) 590f1702c5SYu Xiangning return (EAFNOSUPPORT); 600f1702c5SYu Xiangning 610f1702c5SYu Xiangning ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP); 620f1702c5SYu Xiangning so = socket_create(domain, type, protocol, NULL, NULL, version, flags, 630f1702c5SYu Xiangning cr, &error); 640f1702c5SYu Xiangning if (so == NULL) { 650f1702c5SYu Xiangning if (error == EAFNOSUPPORT) { 660f1702c5SYu Xiangning char *mod = NULL; 670f1702c5SYu Xiangning 680f1702c5SYu Xiangning /* 690f1702c5SYu Xiangning * Could be that root file sytem is not loaded or 700f1702c5SYu Xiangning * soconfig has not run yet. 710f1702c5SYu Xiangning */ 720f1702c5SYu Xiangning if (type == SOCK_STREAM && (domain == AF_INET || 730f1702c5SYu Xiangning domain == AF_INET6) && (protocol == 0 || 740f1702c5SYu Xiangning protocol == IPPROTO_TCP)) { 750f1702c5SYu Xiangning mod = SOCKETMOD_TCP; 760f1702c5SYu Xiangning } else if (type == SOCK_DGRAM && (domain == AF_INET || 770f1702c5SYu Xiangning domain == AF_INET6) && (protocol == 0 || 780f1702c5SYu Xiangning protocol == IPPROTO_UDP)) { 790f1702c5SYu Xiangning mod = SOCKETMOD_UDP; 800f1702c5SYu Xiangning } else { 810f1702c5SYu Xiangning return (EAFNOSUPPORT); 820f1702c5SYu Xiangning } 830f1702c5SYu Xiangning 840f1702c5SYu Xiangning so = socket_create(domain, type, protocol, NULL, 850f1702c5SYu Xiangning mod, version, flags, cr, &error); 860f1702c5SYu Xiangning if (so == NULL) 870f1702c5SYu Xiangning return (error); 880f1702c5SYu Xiangning } else { 890f1702c5SYu Xiangning return (error); 900f1702c5SYu Xiangning } 910f1702c5SYu Xiangning } 920f1702c5SYu Xiangning 930f1702c5SYu Xiangning so->so_mode |= SM_KERNEL; 940f1702c5SYu Xiangning 950f1702c5SYu Xiangning *ksp = SOTOKS(so); 960f1702c5SYu Xiangning 970f1702c5SYu Xiangning return (0); 980f1702c5SYu Xiangning } 990f1702c5SYu Xiangning int 1000f1702c5SYu Xiangning ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen, 1010f1702c5SYu Xiangning struct cred *cr) 1020f1702c5SYu Xiangning { 1030f1702c5SYu Xiangning int error; 1040f1702c5SYu Xiangning 105*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 106*de8c4a14SErik Nordmark ASSERT(cr != NULL); 107*de8c4a14SErik Nordmark 1080f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 1090f1702c5SYu Xiangning return (ENOTSOCK); 1100f1702c5SYu Xiangning 1110f1702c5SYu Xiangning error = socket_bind(KSTOSO(ks), addr, addrlen, _SOBIND_SOCKBSD, cr); 1120f1702c5SYu Xiangning 1130f1702c5SYu Xiangning return (error); 1140f1702c5SYu Xiangning } 1150f1702c5SYu Xiangning 1160f1702c5SYu Xiangning int 1170f1702c5SYu Xiangning ksocket_listen(ksocket_t ks, int backlog, struct cred *cr) 1180f1702c5SYu Xiangning { 119*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 120*de8c4a14SErik Nordmark ASSERT(cr != NULL); 121*de8c4a14SErik Nordmark 1220f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 1230f1702c5SYu Xiangning return (ENOTSOCK); 1240f1702c5SYu Xiangning 1250f1702c5SYu Xiangning return (socket_listen(KSTOSO(ks), backlog, cr)); 1260f1702c5SYu Xiangning } 1270f1702c5SYu Xiangning 1280f1702c5SYu Xiangning int 1290f1702c5SYu Xiangning ksocket_accept(ksocket_t ks, struct sockaddr *addr, 1300f1702c5SYu Xiangning socklen_t *addrlenp, ksocket_t *nks, struct cred *cr) 1310f1702c5SYu Xiangning { 1320f1702c5SYu Xiangning int error; 1330f1702c5SYu Xiangning struct sonode *nso = NULL; 1340f1702c5SYu Xiangning 135*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 136*de8c4a14SErik Nordmark ASSERT(cr != NULL); 137*de8c4a14SErik Nordmark 1380f1702c5SYu Xiangning *nks = NULL; 1390f1702c5SYu Xiangning 1400f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 1410f1702c5SYu Xiangning return (ENOTSOCK); 1420f1702c5SYu Xiangning 1430f1702c5SYu Xiangning if (addr != NULL && addrlenp == NULL) 1440f1702c5SYu Xiangning return (EFAULT); 1450f1702c5SYu Xiangning 1460f1702c5SYu Xiangning error = socket_accept(KSTOSO(ks), KSOCKET_FMODE(ks), cr, &nso); 1470f1702c5SYu Xiangning if (error != 0) 1480f1702c5SYu Xiangning return (error); 1490f1702c5SYu Xiangning 1500f1702c5SYu Xiangning ASSERT(nso != NULL); 1510f1702c5SYu Xiangning 1520f1702c5SYu Xiangning nso->so_mode |= SM_KERNEL; 1530f1702c5SYu Xiangning 1540f1702c5SYu Xiangning if (addr != NULL && addrlenp != NULL) { 1550f1702c5SYu Xiangning error = socket_getpeername(nso, addr, addrlenp, B_TRUE, cr); 1560f1702c5SYu Xiangning if (error != 0) { 1570f1702c5SYu Xiangning (void) socket_close(nso, 0, cr); 1580f1702c5SYu Xiangning socket_destroy(nso); 1590f1702c5SYu Xiangning return ((error == ENOTCONN) ? ECONNABORTED : error); 1600f1702c5SYu Xiangning } 1610f1702c5SYu Xiangning } 1620f1702c5SYu Xiangning 1630f1702c5SYu Xiangning *nks = SOTOKS(nso); 1640f1702c5SYu Xiangning 1650f1702c5SYu Xiangning return (error); 1660f1702c5SYu Xiangning } 1670f1702c5SYu Xiangning 1680f1702c5SYu Xiangning int 1690f1702c5SYu Xiangning ksocket_connect(ksocket_t ks, const struct sockaddr *addr, socklen_t addrlen, 1700f1702c5SYu Xiangning struct cred *cr) 1710f1702c5SYu Xiangning { 172*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 173*de8c4a14SErik Nordmark ASSERT(cr != NULL); 174*de8c4a14SErik Nordmark 1750f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 1760f1702c5SYu Xiangning return (ENOTSOCK); 1770f1702c5SYu Xiangning 1780f1702c5SYu Xiangning return (socket_connect(KSTOSO(ks), addr, addrlen, 1790f1702c5SYu Xiangning KSOCKET_FMODE(ks), 0, cr)); 1800f1702c5SYu Xiangning } 1810f1702c5SYu Xiangning 1820f1702c5SYu Xiangning int 1830f1702c5SYu Xiangning ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags, 1840f1702c5SYu Xiangning size_t *sent, struct cred *cr) 1850f1702c5SYu Xiangning { 1860f1702c5SYu Xiangning int error; 1870f1702c5SYu Xiangning struct nmsghdr msghdr; 1880f1702c5SYu Xiangning struct uio auio; 1890f1702c5SYu Xiangning struct iovec iov; 1900f1702c5SYu Xiangning 191*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 192*de8c4a14SErik Nordmark ASSERT(cr != NULL); 193*de8c4a14SErik Nordmark 1940f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) { 1950f1702c5SYu Xiangning if (sent != NULL) 1960f1702c5SYu Xiangning *sent = 0; 1970f1702c5SYu Xiangning return (ENOTSOCK); 1980f1702c5SYu Xiangning } 1990f1702c5SYu Xiangning 2000f1702c5SYu Xiangning iov.iov_base = msg; 2010f1702c5SYu Xiangning iov.iov_len = msglen; 2020f1702c5SYu Xiangning 2030f1702c5SYu Xiangning bzero(&auio, sizeof (struct uio)); 2040f1702c5SYu Xiangning auio.uio_loffset = 0; 2050f1702c5SYu Xiangning auio.uio_iov = &iov; 2060f1702c5SYu Xiangning auio.uio_iovcnt = 1; 2070f1702c5SYu Xiangning auio.uio_resid = msglen; 2080f1702c5SYu Xiangning if (flags & MSG_USERSPACE) 2090f1702c5SYu Xiangning auio.uio_segflg = UIO_USERSPACE; 2100f1702c5SYu Xiangning else 2110f1702c5SYu Xiangning auio.uio_segflg = UIO_SYSSPACE; 2120f1702c5SYu Xiangning auio.uio_extflg = UIO_COPY_DEFAULT; 2130f1702c5SYu Xiangning auio.uio_limit = 0; 2140f1702c5SYu Xiangning auio.uio_fmode = KSOCKET_FMODE(ks); 2150f1702c5SYu Xiangning 2160f1702c5SYu Xiangning msghdr.msg_name = NULL; 2170f1702c5SYu Xiangning msghdr.msg_namelen = 0; 2180f1702c5SYu Xiangning msghdr.msg_control = NULL; 2190f1702c5SYu Xiangning msghdr.msg_controllen = 0; 2200f1702c5SYu Xiangning msghdr.msg_flags = flags | MSG_EOR; 2210f1702c5SYu Xiangning 2220f1702c5SYu Xiangning error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr); 2230f1702c5SYu Xiangning if (error != 0) { 2240f1702c5SYu Xiangning if (sent != NULL) 2250f1702c5SYu Xiangning *sent = 0; 2260f1702c5SYu Xiangning return (error); 2270f1702c5SYu Xiangning } 2280f1702c5SYu Xiangning 2290f1702c5SYu Xiangning if (sent != NULL) 2300f1702c5SYu Xiangning *sent = msglen - auio.uio_resid; 2310f1702c5SYu Xiangning return (0); 2320f1702c5SYu Xiangning } 2330f1702c5SYu Xiangning 2340f1702c5SYu Xiangning int 2350f1702c5SYu Xiangning ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags, 2360f1702c5SYu Xiangning struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr) 2370f1702c5SYu Xiangning { 2380f1702c5SYu Xiangning int error; 2390f1702c5SYu Xiangning struct nmsghdr msghdr; 2400f1702c5SYu Xiangning struct uio auio; 2410f1702c5SYu Xiangning struct iovec iov; 2420f1702c5SYu Xiangning 243*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 244*de8c4a14SErik Nordmark ASSERT(cr != NULL); 245*de8c4a14SErik Nordmark 2460f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) { 2470f1702c5SYu Xiangning if (sent != NULL) 2480f1702c5SYu Xiangning *sent = 0; 2490f1702c5SYu Xiangning return (ENOTSOCK); 2500f1702c5SYu Xiangning } 2510f1702c5SYu Xiangning 2520f1702c5SYu Xiangning iov.iov_base = msg; 2530f1702c5SYu Xiangning iov.iov_len = msglen; 2540f1702c5SYu Xiangning 2550f1702c5SYu Xiangning bzero(&auio, sizeof (struct uio)); 2560f1702c5SYu Xiangning auio.uio_loffset = 0; 2570f1702c5SYu Xiangning auio.uio_iov = &iov; 2580f1702c5SYu Xiangning auio.uio_iovcnt = 1; 2590f1702c5SYu Xiangning auio.uio_resid = msglen; 2600f1702c5SYu Xiangning if (flags & MSG_USERSPACE) 2610f1702c5SYu Xiangning auio.uio_segflg = UIO_USERSPACE; 2620f1702c5SYu Xiangning else 2630f1702c5SYu Xiangning auio.uio_segflg = UIO_SYSSPACE; 2640f1702c5SYu Xiangning auio.uio_extflg = UIO_COPY_DEFAULT; 2650f1702c5SYu Xiangning auio.uio_limit = 0; 2660f1702c5SYu Xiangning auio.uio_fmode = KSOCKET_FMODE(ks); 2670f1702c5SYu Xiangning 2680f1702c5SYu Xiangning msghdr.msg_iov = &iov; 2690f1702c5SYu Xiangning msghdr.msg_iovlen = 1; 2700f1702c5SYu Xiangning msghdr.msg_name = (char *)name; 2710f1702c5SYu Xiangning msghdr.msg_namelen = namelen; 2720f1702c5SYu Xiangning msghdr.msg_control = NULL; 2730f1702c5SYu Xiangning msghdr.msg_controllen = 0; 2740f1702c5SYu Xiangning msghdr.msg_flags = flags | MSG_EOR; 2750f1702c5SYu Xiangning 2760f1702c5SYu Xiangning error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr); 2770f1702c5SYu Xiangning if (error != 0) { 2780f1702c5SYu Xiangning if (sent != NULL) 2790f1702c5SYu Xiangning *sent = 0; 2800f1702c5SYu Xiangning return (error); 2810f1702c5SYu Xiangning } 2820f1702c5SYu Xiangning if (sent != NULL) 2830f1702c5SYu Xiangning *sent = msglen - auio.uio_resid; 2840f1702c5SYu Xiangning return (0); 2850f1702c5SYu Xiangning } 2860f1702c5SYu Xiangning 2870f1702c5SYu Xiangning int 2880f1702c5SYu Xiangning ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags, 2890f1702c5SYu Xiangning size_t *sent, struct cred *cr) 2900f1702c5SYu Xiangning { 2910f1702c5SYu Xiangning int error; 2920f1702c5SYu Xiangning ssize_t len; 2930f1702c5SYu Xiangning int i; 2940f1702c5SYu Xiangning struct uio auio; 2950f1702c5SYu Xiangning 296*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 297*de8c4a14SErik Nordmark ASSERT(cr != NULL); 298*de8c4a14SErik Nordmark 2990f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) { 3000f1702c5SYu Xiangning if (sent != NULL) 3010f1702c5SYu Xiangning *sent = 0; 3020f1702c5SYu Xiangning return (ENOTSOCK); 3030f1702c5SYu Xiangning } 3040f1702c5SYu Xiangning 3050f1702c5SYu Xiangning bzero(&auio, sizeof (struct uio)); 3060f1702c5SYu Xiangning auio.uio_loffset = 0; 3070f1702c5SYu Xiangning auio.uio_iov = msg->msg_iov; 3080f1702c5SYu Xiangning auio.uio_iovcnt = msg->msg_iovlen; 3090f1702c5SYu Xiangning if (flags & MSG_USERSPACE) 3100f1702c5SYu Xiangning auio.uio_segflg = UIO_USERSPACE; 3110f1702c5SYu Xiangning else 3120f1702c5SYu Xiangning auio.uio_segflg = UIO_SYSSPACE; 3130f1702c5SYu Xiangning auio.uio_extflg = UIO_COPY_DEFAULT; 3140f1702c5SYu Xiangning auio.uio_limit = 0; 3150f1702c5SYu Xiangning auio.uio_fmode = KSOCKET_FMODE(ks); 3160f1702c5SYu Xiangning len = 0; 3170f1702c5SYu Xiangning for (i = 0; i < msg->msg_iovlen; i++) { 3180f1702c5SYu Xiangning ssize_t iovlen; 3190f1702c5SYu Xiangning iovlen = (msg->msg_iov)[i].iov_len; 3200f1702c5SYu Xiangning len += iovlen; 3210f1702c5SYu Xiangning if (len < 0 || iovlen < 0) 3220f1702c5SYu Xiangning return (EINVAL); 3230f1702c5SYu Xiangning } 3240f1702c5SYu Xiangning auio.uio_resid = len; 3250f1702c5SYu Xiangning 3260f1702c5SYu Xiangning msg->msg_flags = flags | MSG_EOR; 3270f1702c5SYu Xiangning 3280f1702c5SYu Xiangning error = socket_sendmsg(KSTOSO(ks), msg, &auio, cr); 3290f1702c5SYu Xiangning if (error != 0) { 3300f1702c5SYu Xiangning if (sent != NULL) 3310f1702c5SYu Xiangning *sent = 0; 3320f1702c5SYu Xiangning return (error); 3330f1702c5SYu Xiangning } 3340f1702c5SYu Xiangning 3350f1702c5SYu Xiangning if (sent != NULL) 3360f1702c5SYu Xiangning *sent = len - auio.uio_resid; 3370f1702c5SYu Xiangning return (0); 3380f1702c5SYu Xiangning } 3390f1702c5SYu Xiangning 3400f1702c5SYu Xiangning 3410f1702c5SYu Xiangning int 3420f1702c5SYu Xiangning ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags, 3430f1702c5SYu Xiangning size_t *recv, struct cred *cr) 3440f1702c5SYu Xiangning { 3450f1702c5SYu Xiangning int error; 3460f1702c5SYu Xiangning struct nmsghdr msghdr; 3470f1702c5SYu Xiangning struct uio auio; 3480f1702c5SYu Xiangning struct iovec iov; 3490f1702c5SYu Xiangning 350*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 351*de8c4a14SErik Nordmark ASSERT(cr != NULL); 352*de8c4a14SErik Nordmark 3530f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) { 3540f1702c5SYu Xiangning if (recv != NULL) 3550f1702c5SYu Xiangning *recv = 0; 3560f1702c5SYu Xiangning return (ENOTSOCK); 3570f1702c5SYu Xiangning } 3580f1702c5SYu Xiangning 3590f1702c5SYu Xiangning iov.iov_base = msg; 3600f1702c5SYu Xiangning iov.iov_len = msglen; 3610f1702c5SYu Xiangning 3620f1702c5SYu Xiangning bzero(&auio, sizeof (struct uio)); 3630f1702c5SYu Xiangning auio.uio_loffset = 0; 3640f1702c5SYu Xiangning auio.uio_iov = &iov; 3650f1702c5SYu Xiangning auio.uio_iovcnt = 1; 3660f1702c5SYu Xiangning auio.uio_resid = msglen; 3670f1702c5SYu Xiangning if (flags & MSG_USERSPACE) 3680f1702c5SYu Xiangning auio.uio_segflg = UIO_USERSPACE; 3690f1702c5SYu Xiangning else 3700f1702c5SYu Xiangning auio.uio_segflg = UIO_SYSSPACE; 3710f1702c5SYu Xiangning auio.uio_extflg = UIO_COPY_DEFAULT; 3720f1702c5SYu Xiangning auio.uio_limit = 0; 3730f1702c5SYu Xiangning auio.uio_fmode = KSOCKET_FMODE(ks); 3740f1702c5SYu Xiangning 3750f1702c5SYu Xiangning msghdr.msg_name = NULL; 3760f1702c5SYu Xiangning msghdr.msg_namelen = 0; 3770f1702c5SYu Xiangning msghdr.msg_control = NULL; 3780f1702c5SYu Xiangning msghdr.msg_controllen = 0; 3790f1702c5SYu Xiangning msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 3800f1702c5SYu Xiangning MSG_DONTWAIT | MSG_USERSPACE); 3810f1702c5SYu Xiangning 3820f1702c5SYu Xiangning error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr); 3830f1702c5SYu Xiangning if (error != 0) { 3840f1702c5SYu Xiangning if (recv != NULL) 3850f1702c5SYu Xiangning *recv = 0; 3860f1702c5SYu Xiangning return (error); 3870f1702c5SYu Xiangning } 3880f1702c5SYu Xiangning 3890f1702c5SYu Xiangning if (recv != NULL) 3900f1702c5SYu Xiangning *recv = msglen - auio.uio_resid; 3910f1702c5SYu Xiangning return (0); 3920f1702c5SYu Xiangning } 3930f1702c5SYu Xiangning 3940f1702c5SYu Xiangning int 3950f1702c5SYu Xiangning ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags, 3960f1702c5SYu Xiangning struct sockaddr *name, socklen_t *namelen, size_t *recv, struct cred *cr) 3970f1702c5SYu Xiangning { 3980f1702c5SYu Xiangning int error; 3990f1702c5SYu Xiangning struct nmsghdr msghdr; 4000f1702c5SYu Xiangning struct uio auio; 4010f1702c5SYu Xiangning struct iovec iov; 4020f1702c5SYu Xiangning 403*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 404*de8c4a14SErik Nordmark ASSERT(cr != NULL); 405*de8c4a14SErik Nordmark 4060f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) { 4070f1702c5SYu Xiangning if (recv != NULL) 4080f1702c5SYu Xiangning *recv = 0; 4090f1702c5SYu Xiangning return (ENOTSOCK); 4100f1702c5SYu Xiangning } 4110f1702c5SYu Xiangning 4120f1702c5SYu Xiangning iov.iov_base = msg; 4130f1702c5SYu Xiangning iov.iov_len = msglen; 4140f1702c5SYu Xiangning 4150f1702c5SYu Xiangning bzero(&auio, sizeof (struct uio)); 4160f1702c5SYu Xiangning auio.uio_loffset = 0; 4170f1702c5SYu Xiangning auio.uio_iov = &iov; 4180f1702c5SYu Xiangning auio.uio_iovcnt = 1; 4190f1702c5SYu Xiangning auio.uio_resid = msglen; 4200f1702c5SYu Xiangning if (flags & MSG_USERSPACE) 4210f1702c5SYu Xiangning auio.uio_segflg = UIO_USERSPACE; 4220f1702c5SYu Xiangning else 4230f1702c5SYu Xiangning auio.uio_segflg = UIO_SYSSPACE; 4240f1702c5SYu Xiangning auio.uio_extflg = UIO_COPY_DEFAULT; 4250f1702c5SYu Xiangning auio.uio_limit = 0; 4260f1702c5SYu Xiangning auio.uio_fmode = KSOCKET_FMODE(ks); 4270f1702c5SYu Xiangning 4280f1702c5SYu Xiangning msghdr.msg_name = (char *)name; 4290f1702c5SYu Xiangning msghdr.msg_namelen = *namelen; 4300f1702c5SYu Xiangning msghdr.msg_control = NULL; 4310f1702c5SYu Xiangning msghdr.msg_controllen = 0; 4320f1702c5SYu Xiangning msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 4330f1702c5SYu Xiangning MSG_DONTWAIT | MSG_USERSPACE); 4340f1702c5SYu Xiangning 4350f1702c5SYu Xiangning error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr); 4360f1702c5SYu Xiangning if (error != 0) { 4370f1702c5SYu Xiangning if (recv != NULL) 4380f1702c5SYu Xiangning *recv = 0; 4390f1702c5SYu Xiangning return (error); 4400f1702c5SYu Xiangning } 4410f1702c5SYu Xiangning if (recv != NULL) 4420f1702c5SYu Xiangning *recv = msglen - auio.uio_resid; 4430f1702c5SYu Xiangning 4440f1702c5SYu Xiangning bcopy(msghdr.msg_name, name, msghdr.msg_namelen); 4450f1702c5SYu Xiangning bcopy(&msghdr.msg_namelen, namelen, sizeof (msghdr.msg_namelen)); 4460f1702c5SYu Xiangning return (0); 4470f1702c5SYu Xiangning } 4480f1702c5SYu Xiangning 4490f1702c5SYu Xiangning int 4500f1702c5SYu Xiangning ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recv, 4510f1702c5SYu Xiangning struct cred *cr) 4520f1702c5SYu Xiangning { 4530f1702c5SYu Xiangning int error; 4540f1702c5SYu Xiangning ssize_t len; 4550f1702c5SYu Xiangning int i; 4560f1702c5SYu Xiangning struct uio auio; 4570f1702c5SYu Xiangning 458*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 459*de8c4a14SErik Nordmark ASSERT(cr != NULL); 460*de8c4a14SErik Nordmark 4610f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) { 4620f1702c5SYu Xiangning if (recv != NULL) 4630f1702c5SYu Xiangning *recv = 0; 4640f1702c5SYu Xiangning return (ENOTSOCK); 4650f1702c5SYu Xiangning } 4660f1702c5SYu Xiangning 4670f1702c5SYu Xiangning bzero(&auio, sizeof (struct uio)); 4680f1702c5SYu Xiangning auio.uio_loffset = 0; 4690f1702c5SYu Xiangning auio.uio_iov = msg->msg_iov; 4700f1702c5SYu Xiangning auio.uio_iovcnt = msg->msg_iovlen; 4710f1702c5SYu Xiangning if (msg->msg_flags & MSG_USERSPACE) 4720f1702c5SYu Xiangning auio.uio_segflg = UIO_USERSPACE; 4730f1702c5SYu Xiangning else 4740f1702c5SYu Xiangning auio.uio_segflg = UIO_SYSSPACE; 4750f1702c5SYu Xiangning auio.uio_extflg = UIO_COPY_DEFAULT; 4760f1702c5SYu Xiangning auio.uio_limit = 0; 4770f1702c5SYu Xiangning auio.uio_fmode = KSOCKET_FMODE(ks); 4780f1702c5SYu Xiangning len = 0; 4790f1702c5SYu Xiangning 4800f1702c5SYu Xiangning for (i = 0; i < msg->msg_iovlen; i++) { 4810f1702c5SYu Xiangning ssize_t iovlen; 4820f1702c5SYu Xiangning iovlen = (msg->msg_iov)[i].iov_len; 4830f1702c5SYu Xiangning len += iovlen; 4840f1702c5SYu Xiangning if (len < 0 || iovlen < 0) 4850f1702c5SYu Xiangning return (EINVAL); 4860f1702c5SYu Xiangning } 4870f1702c5SYu Xiangning auio.uio_resid = len; 4880f1702c5SYu Xiangning 4890f1702c5SYu Xiangning msg->msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 4900f1702c5SYu Xiangning MSG_DONTWAIT | MSG_USERSPACE); 4910f1702c5SYu Xiangning 4920f1702c5SYu Xiangning error = socket_recvmsg(KSTOSO(ks), msg, &auio, cr); 4930f1702c5SYu Xiangning if (error != 0) { 4940f1702c5SYu Xiangning if (recv != NULL) 4950f1702c5SYu Xiangning *recv = 0; 4960f1702c5SYu Xiangning return (error); 4970f1702c5SYu Xiangning } 4980f1702c5SYu Xiangning if (recv != NULL) 4990f1702c5SYu Xiangning *recv = len - auio.uio_resid; 5000f1702c5SYu Xiangning return (0); 5010f1702c5SYu Xiangning 5020f1702c5SYu Xiangning } 5030f1702c5SYu Xiangning 5040f1702c5SYu Xiangning int 5050f1702c5SYu Xiangning ksocket_shutdown(ksocket_t ks, int how, struct cred *cr) 5060f1702c5SYu Xiangning { 5070f1702c5SYu Xiangning struct sonode *so; 5080f1702c5SYu Xiangning 509*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 510*de8c4a14SErik Nordmark ASSERT(cr != NULL); 511*de8c4a14SErik Nordmark 5120f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 5130f1702c5SYu Xiangning return (ENOTSOCK); 5140f1702c5SYu Xiangning 5150f1702c5SYu Xiangning so = KSTOSO(ks); 5160f1702c5SYu Xiangning 5170f1702c5SYu Xiangning return (socket_shutdown(so, how, cr)); 5180f1702c5SYu Xiangning } 5190f1702c5SYu Xiangning 5200f1702c5SYu Xiangning int 5210f1702c5SYu Xiangning ksocket_close(ksocket_t ks, struct cred *cr) 5220f1702c5SYu Xiangning { 5230f1702c5SYu Xiangning struct sonode *so; 5240f1702c5SYu Xiangning so = KSTOSO(ks); 5250f1702c5SYu Xiangning 526*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 527*de8c4a14SErik Nordmark ASSERT(cr != NULL); 528*de8c4a14SErik Nordmark 5290f1702c5SYu Xiangning mutex_enter(&so->so_lock); 5300f1702c5SYu Xiangning 5310f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) { 5320f1702c5SYu Xiangning mutex_exit(&so->so_lock); 5330f1702c5SYu Xiangning return (ENOTSOCK); 5340f1702c5SYu Xiangning } 5350f1702c5SYu Xiangning 5360f1702c5SYu Xiangning so->so_state |= SS_CLOSING; 5370f1702c5SYu Xiangning 5380f1702c5SYu Xiangning if (so->so_count > 1) { 5390f1702c5SYu Xiangning mutex_enter(&so->so_acceptq_lock); 5400f1702c5SYu Xiangning cv_broadcast(&so->so_acceptq_cv); 5410f1702c5SYu Xiangning mutex_exit(&so->so_acceptq_lock); 5420f1702c5SYu Xiangning cv_broadcast(&so->so_rcv_cv); 5430f1702c5SYu Xiangning cv_broadcast(&so->so_state_cv); 5440f1702c5SYu Xiangning cv_broadcast(&so->so_want_cv); 5450f1702c5SYu Xiangning cv_broadcast(&so->so_snd_cv); 5460f1702c5SYu Xiangning cv_broadcast(&so->so_copy_cv); 5470f1702c5SYu Xiangning } 5480f1702c5SYu Xiangning while (so->so_count > 1) 5490f1702c5SYu Xiangning cv_wait(&so->so_closing_cv, &so->so_lock); 5500f1702c5SYu Xiangning 5510f1702c5SYu Xiangning mutex_exit(&so->so_lock); 5520f1702c5SYu Xiangning /* Remove callbacks, if any */ 5530f1702c5SYu Xiangning (void) ksocket_setcallbacks(ks, NULL, NULL, cr); 5540f1702c5SYu Xiangning 5550f1702c5SYu Xiangning (void) socket_close(so, 0, cr); 5560f1702c5SYu Xiangning socket_destroy(so); 5570f1702c5SYu Xiangning 5580f1702c5SYu Xiangning return (0); 5590f1702c5SYu Xiangning } 5600f1702c5SYu Xiangning 5610f1702c5SYu Xiangning int 5620f1702c5SYu Xiangning ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 5630f1702c5SYu Xiangning struct cred *cr) 5640f1702c5SYu Xiangning { 5650f1702c5SYu Xiangning struct sonode *so; 5660f1702c5SYu Xiangning 567*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 568*de8c4a14SErik Nordmark ASSERT(cr != NULL); 569*de8c4a14SErik Nordmark 5700f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 5710f1702c5SYu Xiangning return (ENOTSOCK); 5720f1702c5SYu Xiangning 5730f1702c5SYu Xiangning so = KSTOSO(ks); 5740f1702c5SYu Xiangning 5750f1702c5SYu Xiangning if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 5760f1702c5SYu Xiangning return (EFAULT); 5770f1702c5SYu Xiangning 5780f1702c5SYu Xiangning return (socket_getsockname(so, addr, addrlen, cr)); 5790f1702c5SYu Xiangning } 5800f1702c5SYu Xiangning 5810f1702c5SYu Xiangning int 5820f1702c5SYu Xiangning ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 5830f1702c5SYu Xiangning struct cred *cr) 5840f1702c5SYu Xiangning { 5850f1702c5SYu Xiangning struct sonode *so; 5860f1702c5SYu Xiangning 587*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 588*de8c4a14SErik Nordmark ASSERT(cr != NULL); 589*de8c4a14SErik Nordmark 5900f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 5910f1702c5SYu Xiangning return (ENOTSOCK); 5920f1702c5SYu Xiangning 5930f1702c5SYu Xiangning so = KSTOSO(ks); 5940f1702c5SYu Xiangning 5950f1702c5SYu Xiangning if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 5960f1702c5SYu Xiangning return (EFAULT); 5970f1702c5SYu Xiangning 5980f1702c5SYu Xiangning return (socket_getpeername(so, addr, addrlen, B_FALSE, cr)); 5990f1702c5SYu Xiangning } 6000f1702c5SYu Xiangning 6010f1702c5SYu Xiangning int 6020f1702c5SYu Xiangning ksocket_getsockopt(ksocket_t ks, int level, int optname, void *optval, 6030f1702c5SYu Xiangning int *optlen, struct cred *cr) 6040f1702c5SYu Xiangning { 6050f1702c5SYu Xiangning struct sonode *so; 6060f1702c5SYu Xiangning 607*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 608*de8c4a14SErik Nordmark ASSERT(cr != NULL); 609*de8c4a14SErik Nordmark 6100f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 6110f1702c5SYu Xiangning return (ENOTSOCK); 6120f1702c5SYu Xiangning 6130f1702c5SYu Xiangning so = KSTOSO(ks); 6140f1702c5SYu Xiangning 6150f1702c5SYu Xiangning if (optlen == NULL) 6160f1702c5SYu Xiangning return (EFAULT); 6170f1702c5SYu Xiangning if (*optlen > SO_MAXARGSIZE) 6180f1702c5SYu Xiangning return (EINVAL); 6190f1702c5SYu Xiangning 6200f1702c5SYu Xiangning return (socket_getsockopt(so, level, optname, optval, 6210f1702c5SYu Xiangning (socklen_t *)optlen, 0, cr)); 6220f1702c5SYu Xiangning } 6230f1702c5SYu Xiangning 6240f1702c5SYu Xiangning int 6250f1702c5SYu Xiangning ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval, 6260f1702c5SYu Xiangning int optlen, struct cred *cr) 6270f1702c5SYu Xiangning { 6280f1702c5SYu Xiangning struct sonode *so; 6290f1702c5SYu Xiangning 630*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 631*de8c4a14SErik Nordmark ASSERT(cr != NULL); 632*de8c4a14SErik Nordmark 6330f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 6340f1702c5SYu Xiangning return (ENOTSOCK); 6350f1702c5SYu Xiangning 6360f1702c5SYu Xiangning so = KSTOSO(ks); 6370f1702c5SYu Xiangning 6380f1702c5SYu Xiangning if (optval == NULL) 6390f1702c5SYu Xiangning optlen = 0; 6400f1702c5SYu Xiangning 6410f1702c5SYu Xiangning return (socket_setsockopt(so, level, optname, optval, 6420f1702c5SYu Xiangning (t_uscalar_t)optlen, cr)); 6430f1702c5SYu Xiangning } 6440f1702c5SYu Xiangning 6450f1702c5SYu Xiangning /* ARGSUSED */ 6460f1702c5SYu Xiangning int 6470f1702c5SYu Xiangning ksocket_setcallbacks(ksocket_t ks, ksocket_callbacks_t *cb, void *arg, 6480f1702c5SYu Xiangning struct cred *cr) 6490f1702c5SYu Xiangning { 6500f1702c5SYu Xiangning struct sonode *so; 6510f1702c5SYu Xiangning 652*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 653*de8c4a14SErik Nordmark ASSERT(cr != NULL); 654*de8c4a14SErik Nordmark 6550f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 6560f1702c5SYu Xiangning return (ENOTSOCK); 6570f1702c5SYu Xiangning 6580f1702c5SYu Xiangning so = KSTOSO(ks); 6590f1702c5SYu Xiangning 6600f1702c5SYu Xiangning if (cb == NULL && arg != NULL) 6610f1702c5SYu Xiangning return (EFAULT); 6620f1702c5SYu Xiangning if (cb == NULL) { 6630f1702c5SYu Xiangning mutex_enter(&so->so_lock); 6640f1702c5SYu Xiangning bzero(&(so->so_ksock_callbacks), sizeof (ksocket_callbacks_t)); 6650f1702c5SYu Xiangning so->so_ksock_cb_arg = NULL; 6660f1702c5SYu Xiangning mutex_exit(&so->so_lock); 6670f1702c5SYu Xiangning } else { 6680f1702c5SYu Xiangning mutex_enter(&so->so_lock); 6690f1702c5SYu Xiangning SETCALLBACK(so, cb, connected, KSOCKET_CB_CONNECTED) 6700f1702c5SYu Xiangning SETCALLBACK(so, cb, connectfailed, KSOCKET_CB_CONNECTFAILED) 6710f1702c5SYu Xiangning SETCALLBACK(so, cb, disconnected, KSOCKET_CB_DISCONNECTED) 6720f1702c5SYu Xiangning SETCALLBACK(so, cb, newdata, KSOCKET_CB_NEWDATA) 6730f1702c5SYu Xiangning SETCALLBACK(so, cb, newconn, KSOCKET_CB_NEWCONN) 6740f1702c5SYu Xiangning SETCALLBACK(so, cb, cansend, KSOCKET_CB_CANSEND) 6750f1702c5SYu Xiangning SETCALLBACK(so, cb, oobdata, KSOCKET_CB_OOBDATA) 6760f1702c5SYu Xiangning SETCALLBACK(so, cb, cantsendmore, KSOCKET_CB_CANTSENDMORE) 6770f1702c5SYu Xiangning SETCALLBACK(so, cb, cantrecvmore, KSOCKET_CB_CANTRECVMORE) 6780f1702c5SYu Xiangning so->so_ksock_cb_arg = arg; 6790f1702c5SYu Xiangning mutex_exit(&so->so_lock); 6800f1702c5SYu Xiangning } 6810f1702c5SYu Xiangning return (0); 6820f1702c5SYu Xiangning } 6830f1702c5SYu Xiangning 6840f1702c5SYu Xiangning int 6850f1702c5SYu Xiangning ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvalp, struct cred *cr) 6860f1702c5SYu Xiangning { 6870f1702c5SYu Xiangning struct sonode *so; 6880f1702c5SYu Xiangning int rval; 6890f1702c5SYu Xiangning 690*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 691*de8c4a14SErik Nordmark ASSERT(cr != NULL); 692*de8c4a14SErik Nordmark 6930f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 6940f1702c5SYu Xiangning return (ENOTSOCK); 6950f1702c5SYu Xiangning 6960f1702c5SYu Xiangning so = KSTOSO(ks); 6970f1702c5SYu Xiangning 6980f1702c5SYu Xiangning switch (cmd) { 6990f1702c5SYu Xiangning default: 7000f1702c5SYu Xiangning /* STREAM iotcls are not supported */ 7010f1702c5SYu Xiangning if ((cmd & 0xffffff00U) == STR) { 7020f1702c5SYu Xiangning rval = EOPNOTSUPP; 7030f1702c5SYu Xiangning } else { 7040f1702c5SYu Xiangning rval = socket_ioctl(so, cmd, arg, 7050f1702c5SYu Xiangning KSOCKET_FMODE(ks) | FKIOCTL, cr, rvalp); 7060f1702c5SYu Xiangning } 7070f1702c5SYu Xiangning break; 7080f1702c5SYu Xiangning case FIOASYNC: 7090f1702c5SYu Xiangning case SIOCSPGRP: 7100f1702c5SYu Xiangning case FIOSETOWN: 7110f1702c5SYu Xiangning case SIOCGPGRP: 7120f1702c5SYu Xiangning case FIOGETOWN: 7130f1702c5SYu Xiangning rval = EOPNOTSUPP; 7140f1702c5SYu Xiangning break; 7150f1702c5SYu Xiangning } 7160f1702c5SYu Xiangning 7170f1702c5SYu Xiangning return (rval); 7180f1702c5SYu Xiangning } 7190f1702c5SYu Xiangning 7200f1702c5SYu Xiangning int 7210f1702c5SYu Xiangning ksocket_sendmblk(ksocket_t ks, struct nmsghdr *msg, int flags, 7220f1702c5SYu Xiangning mblk_t **mpp, cred_t *cr) 7230f1702c5SYu Xiangning { 7240f1702c5SYu Xiangning struct sonode *so; 7250f1702c5SYu Xiangning int i_val; 7260f1702c5SYu Xiangning socklen_t val_len; 7270f1702c5SYu Xiangning mblk_t *mp = *mpp; 7280f1702c5SYu Xiangning int error; 7290f1702c5SYu Xiangning 730*de8c4a14SErik Nordmark /* All Solaris components should pass a cred for this operation. */ 731*de8c4a14SErik Nordmark ASSERT(cr != NULL); 732*de8c4a14SErik Nordmark 7330f1702c5SYu Xiangning if (!KSOCKET_VALID(ks)) 7340f1702c5SYu Xiangning return (ENOTSOCK); 7350f1702c5SYu Xiangning 7360f1702c5SYu Xiangning so = KSTOSO(ks); 7370f1702c5SYu Xiangning 7380f1702c5SYu Xiangning if (flags & MSG_MBLK_QUICKRELE) { 7390f1702c5SYu Xiangning error = socket_getsockopt(so, SOL_SOCKET, SO_SND_COPYAVOID, 740*de8c4a14SErik Nordmark &i_val, &val_len, 0, cr); 7410f1702c5SYu Xiangning if (error != 0) 7420f1702c5SYu Xiangning return (error); 7430f1702c5SYu Xiangning 7440f1702c5SYu Xiangning /* Zero copy is not enable */ 7450f1702c5SYu Xiangning if (i_val == 0) 7460f1702c5SYu Xiangning return (ECANCELED); 7470f1702c5SYu Xiangning 7480f1702c5SYu Xiangning for (; mp != NULL; mp = mp->b_cont) 7490f1702c5SYu Xiangning mp->b_datap->db_struioflag |= STRUIO_ZC; 7500f1702c5SYu Xiangning } 7510f1702c5SYu Xiangning 7520f1702c5SYu Xiangning error = socket_sendmblk(so, msg, flags, cr, mpp); 7530f1702c5SYu Xiangning 7540f1702c5SYu Xiangning return (error); 7550f1702c5SYu Xiangning } 7560f1702c5SYu Xiangning 7570f1702c5SYu Xiangning 7580f1702c5SYu Xiangning void 7590f1702c5SYu Xiangning ksocket_hold(ksocket_t ks) 7600f1702c5SYu Xiangning { 7610f1702c5SYu Xiangning struct sonode *so; 7620f1702c5SYu Xiangning so = KSTOSO(ks); 7630f1702c5SYu Xiangning 7640f1702c5SYu Xiangning if (!mutex_owned(&so->so_lock)) { 7650f1702c5SYu Xiangning mutex_enter(&so->so_lock); 7660f1702c5SYu Xiangning so->so_count++; 7670f1702c5SYu Xiangning mutex_exit(&so->so_lock); 7680f1702c5SYu Xiangning } else 7690f1702c5SYu Xiangning so->so_count++; 7700f1702c5SYu Xiangning } 7710f1702c5SYu Xiangning 7720f1702c5SYu Xiangning void 7730f1702c5SYu Xiangning ksocket_rele(ksocket_t ks) 7740f1702c5SYu Xiangning { 7750f1702c5SYu Xiangning struct sonode *so; 7760f1702c5SYu Xiangning 7770f1702c5SYu Xiangning so = KSTOSO(ks); 7780f1702c5SYu Xiangning /* 7790f1702c5SYu Xiangning * When so_count equals 1 means no thread working on this ksocket 7800f1702c5SYu Xiangning */ 7810f1702c5SYu Xiangning if (so->so_count < 2) 7820f1702c5SYu Xiangning cmn_err(CE_PANIC, "ksocket_rele: sonode ref count 0 or 1"); 7830f1702c5SYu Xiangning 7840f1702c5SYu Xiangning if (!mutex_owned(&so->so_lock)) { 7850f1702c5SYu Xiangning mutex_enter(&so->so_lock); 7860f1702c5SYu Xiangning if (--so->so_count == 1) 7870f1702c5SYu Xiangning cv_signal(&so->so_closing_cv); 7880f1702c5SYu Xiangning mutex_exit(&so->so_lock); 7890f1702c5SYu Xiangning } else { 7900f1702c5SYu Xiangning if (--so->so_count == 1) 7910f1702c5SYu Xiangning cv_signal(&so->so_closing_cv); 7920f1702c5SYu Xiangning } 7930f1702c5SYu Xiangning } 794