1b819cea2SGordon Ross /* 2b819cea2SGordon Ross * CDDL HEADER START 3b819cea2SGordon Ross * 4b819cea2SGordon Ross * The contents of this file are subject to the terms of the 5b819cea2SGordon Ross * Common Development and Distribution License (the "License"). 6b819cea2SGordon Ross * You may not use this file except in compliance with the License. 7b819cea2SGordon Ross * 8b819cea2SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9b819cea2SGordon Ross * or http://www.opensolaris.org/os/licensing. 10b819cea2SGordon Ross * See the License for the specific language governing permissions 11b819cea2SGordon Ross * and limitations under the License. 12b819cea2SGordon Ross * 13b819cea2SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14b819cea2SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15b819cea2SGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16b819cea2SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17b819cea2SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18b819cea2SGordon Ross * 19b819cea2SGordon Ross * CDDL HEADER END 20b819cea2SGordon Ross */ 21b819cea2SGordon Ross 22b819cea2SGordon Ross /* 23b819cea2SGordon Ross * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24*a90cf9f2SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 25b819cea2SGordon Ross */ 26b819cea2SGordon Ross 27b819cea2SGordon Ross #include <sys/types.h> 28b819cea2SGordon Ross #include <sys/systm.h> 29b819cea2SGordon Ross #include <sys/cred.h> 30b819cea2SGordon Ross #include <sys/errno.h> 31b819cea2SGordon Ross #include <sys/socket.h> 32b819cea2SGordon Ross #include <sys/ksocket.h> 33b819cea2SGordon Ross #include <sys/debug.h> 34b819cea2SGordon Ross #include <sys/kmem.h> 35*a90cf9f2SGordon Ross #include <limits.h> 36b819cea2SGordon Ross #include <unistd.h> 37b819cea2SGordon Ross #include <errno.h> 38b819cea2SGordon Ross #include <umem.h> 39b819cea2SGordon Ross 40b819cea2SGordon Ross #define _KSOCKET_MAGIC 0xabcdef09 41b819cea2SGordon Ross 42b819cea2SGordon Ross #define KSOCKET_VALID(ks) (ks->kso_magic == _KSOCKET_MAGIC) 43b819cea2SGordon Ross #define KSTOSO(ks) (ks->kso_fd) 44b819cea2SGordon Ross 45b819cea2SGordon Ross #ifndef SS_CLOSING 46b819cea2SGordon Ross #define SS_CLOSING 0x00010000 47b819cea2SGordon Ross #endif 48b819cea2SGordon Ross 49b819cea2SGordon Ross /* 50b819cea2SGordon Ross * NB: you can't cast this into a sonode like you can with a normal 51b819cea2SGordon Ross * ksocket_t, but no correct code should ever do that anyway. 52b819cea2SGordon Ross * The ksocket_t type is opaque to prevent exactly that. 53b819cea2SGordon Ross */ 54b819cea2SGordon Ross struct __ksocket { 55b819cea2SGordon Ross uint32_t kso_magic; 56b819cea2SGordon Ross uint32_t kso_count; 57b819cea2SGordon Ross uint32_t kso_state; 58b819cea2SGordon Ross int kso_fd; 59b819cea2SGordon Ross kmutex_t kso_lock; 60b819cea2SGordon Ross kcondvar_t kso_closing_cv; 61b819cea2SGordon Ross }; 62b819cea2SGordon Ross 63b819cea2SGordon Ross static umem_cache_t *ksocket_cache = NULL; 64b819cea2SGordon Ross 65b819cea2SGordon Ross /*ARGSUSED*/ 66b819cea2SGordon Ross static int 67b819cea2SGordon Ross _ksocket_ctor(void *buf, void *arg, int flags) 68b819cea2SGordon Ross { 69b819cea2SGordon Ross ksocket_t sock = buf; 70b819cea2SGordon Ross 71b819cea2SGordon Ross bzero(sock, sizeof (*sock)); 72b819cea2SGordon Ross mutex_init(&sock->kso_lock, NULL, MUTEX_DEFAULT, NULL); 73b819cea2SGordon Ross cv_init(&sock->kso_closing_cv, NULL, CV_DEFAULT, NULL); 74b819cea2SGordon Ross return (0); 75b819cea2SGordon Ross } 76b819cea2SGordon Ross 77b819cea2SGordon Ross /*ARGSUSED*/ 78b819cea2SGordon Ross static void 79b819cea2SGordon Ross _ksocket_dtor(void *buf, void *arg) 80b819cea2SGordon Ross { 81b819cea2SGordon Ross ksocket_t sock = buf; 82b819cea2SGordon Ross 83b819cea2SGordon Ross mutex_destroy(&sock->kso_lock); 84b819cea2SGordon Ross cv_destroy(&sock->kso_closing_cv); 85b819cea2SGordon Ross } 86b819cea2SGordon Ross 87b819cea2SGordon Ross #pragma init(_ksocket_init) 88b819cea2SGordon Ross int 89b819cea2SGordon Ross _ksocket_init(void) 90b819cea2SGordon Ross { 91b819cea2SGordon Ross ksocket_cache = umem_cache_create("ksocket", 92b819cea2SGordon Ross sizeof (struct __ksocket), 0, 93b819cea2SGordon Ross _ksocket_ctor, _ksocket_dtor, NULL, NULL, NULL, 0); 94b819cea2SGordon Ross VERIFY(ksocket_cache != NULL); 95b819cea2SGordon Ross return (0); 96b819cea2SGordon Ross } 97b819cea2SGordon Ross 98b819cea2SGordon Ross #pragma fini(_ksocket_fini) 99b819cea2SGordon Ross int 100b819cea2SGordon Ross _ksocket_fini(void) 101b819cea2SGordon Ross { 102b819cea2SGordon Ross umem_cache_destroy(ksocket_cache); 103b819cea2SGordon Ross return (0); 104b819cea2SGordon Ross } 105b819cea2SGordon Ross 106b819cea2SGordon Ross static ksocket_t 107b819cea2SGordon Ross _ksocket_create(int fd) 108b819cea2SGordon Ross { 109b819cea2SGordon Ross ksocket_t ks; 110b819cea2SGordon Ross 111b819cea2SGordon Ross ks = umem_cache_alloc(ksocket_cache, 0); 112b819cea2SGordon Ross VERIFY(ks != NULL); 113b819cea2SGordon Ross ks->kso_magic = _KSOCKET_MAGIC; 114b819cea2SGordon Ross ks->kso_count = 1; 115b819cea2SGordon Ross ks->kso_fd = fd; 116b819cea2SGordon Ross return (ks); 117b819cea2SGordon Ross } 118b819cea2SGordon Ross 119b819cea2SGordon Ross static void 120b819cea2SGordon Ross _ksocket_destroy(ksocket_t ks) 121b819cea2SGordon Ross { 122b819cea2SGordon Ross ASSERT(ks->kso_count == 1); 123b819cea2SGordon Ross umem_cache_free(ksocket_cache, ks); 124b819cea2SGordon Ross } 125b819cea2SGordon Ross 126b819cea2SGordon Ross int 127b819cea2SGordon Ross ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags, 128b819cea2SGordon Ross struct cred *cr) 129b819cea2SGordon Ross { 130b819cea2SGordon Ross int fd; 131b819cea2SGordon Ross ksocket_t ks; 132b819cea2SGordon Ross 133b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 134b819cea2SGordon Ross ASSERT(cr != NULL); 135b819cea2SGordon Ross 136b819cea2SGordon Ross ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP); 137b819cea2SGordon Ross 138b819cea2SGordon Ross fd = socket(domain, type, protocol); 139b819cea2SGordon Ross if (fd < 0) { 140b819cea2SGordon Ross *ksp = NULL; 141b819cea2SGordon Ross return (errno); 142b819cea2SGordon Ross } 143b819cea2SGordon Ross 144b819cea2SGordon Ross ks = _ksocket_create(fd); 145b819cea2SGordon Ross *ksp = ks; 146b819cea2SGordon Ross return (0); 147b819cea2SGordon Ross } 148b819cea2SGordon Ross 149b819cea2SGordon Ross /* 150b819cea2SGordon Ross * This is marked NODIRECT so the main program linking with this library 151b819cea2SGordon Ross * can provide its own "bind helper" function. See: fksmbd_ksock.c 152b819cea2SGordon Ross */ 153b819cea2SGordon Ross /* ARGSUSED */ 154b819cea2SGordon Ross int 155b819cea2SGordon Ross ksocket_bind_helper(int fd, struct sockaddr *addr, uint_t addrlen) 156b819cea2SGordon Ross { 157b819cea2SGordon Ross return (EACCES); 158b819cea2SGordon Ross } 159b819cea2SGordon Ross 160b819cea2SGordon Ross int 161b819cea2SGordon Ross ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen, 162b819cea2SGordon Ross struct cred *cr) 163b819cea2SGordon Ross { 164b819cea2SGordon Ross int err = 0; 165b819cea2SGordon Ross 166b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 167b819cea2SGordon Ross ASSERT(cr != NULL); 168b819cea2SGordon Ross 169b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 170b819cea2SGordon Ross return (ENOTSOCK); 171b819cea2SGordon Ross 172b819cea2SGordon Ross if (bind(KSTOSO(ks), addr, addrlen) != 0) 173b819cea2SGordon Ross err = errno; 174b819cea2SGordon Ross 175b819cea2SGordon Ross if (err == EACCES) { 176b819cea2SGordon Ross err = ksocket_bind_helper(KSTOSO(ks), addr, addrlen); 177b819cea2SGordon Ross } 178b819cea2SGordon Ross 179b819cea2SGordon Ross return (err); 180b819cea2SGordon Ross } 181b819cea2SGordon Ross 182b819cea2SGordon Ross int 183b819cea2SGordon Ross ksocket_listen(ksocket_t ks, int backlog, struct cred *cr) 184b819cea2SGordon Ross { 185b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 186b819cea2SGordon Ross ASSERT(cr != NULL); 187b819cea2SGordon Ross 188b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 189b819cea2SGordon Ross return (ENOTSOCK); 190b819cea2SGordon Ross 191b819cea2SGordon Ross if (listen(KSTOSO(ks), backlog) != 0) 192b819cea2SGordon Ross return (errno); 193b819cea2SGordon Ross 194b819cea2SGordon Ross return (0); 195b819cea2SGordon Ross } 196b819cea2SGordon Ross 197b819cea2SGordon Ross int 198b819cea2SGordon Ross ksocket_accept(ksocket_t ks, struct sockaddr *addr, 199b819cea2SGordon Ross socklen_t *addrlenp, ksocket_t *nks, struct cred *cr) 200b819cea2SGordon Ross { 201b819cea2SGordon Ross int fd; 202b819cea2SGordon Ross 203b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 204b819cea2SGordon Ross ASSERT(cr != NULL); 205b819cea2SGordon Ross 206b819cea2SGordon Ross *nks = NULL; 207b819cea2SGordon Ross 208b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 209b819cea2SGordon Ross return (ENOTSOCK); 210b819cea2SGordon Ross 211b819cea2SGordon Ross if (addr != NULL && addrlenp == NULL) 212b819cea2SGordon Ross return (EFAULT); 213b819cea2SGordon Ross 214b819cea2SGordon Ross fd = accept(KSTOSO(ks), addr, addrlenp); 215b819cea2SGordon Ross if (fd < 0) 216b819cea2SGordon Ross return (errno); 217b819cea2SGordon Ross 218b819cea2SGordon Ross *nks = _ksocket_create(fd); 219b819cea2SGordon Ross 220b819cea2SGordon Ross return (0); 221b819cea2SGordon Ross } 222b819cea2SGordon Ross 223b819cea2SGordon Ross int 224b819cea2SGordon Ross ksocket_connect(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen, 225b819cea2SGordon Ross struct cred *cr) 226b819cea2SGordon Ross { 227b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 228b819cea2SGordon Ross ASSERT(cr != NULL); 229b819cea2SGordon Ross 230b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 231b819cea2SGordon Ross return (ENOTSOCK); 232b819cea2SGordon Ross 233b819cea2SGordon Ross if (connect(KSTOSO(ks), addr, addrlen) != 0) 234b819cea2SGordon Ross return (errno); 235b819cea2SGordon Ross 236b819cea2SGordon Ross return (0); 237b819cea2SGordon Ross } 238b819cea2SGordon Ross 239b819cea2SGordon Ross int 240b819cea2SGordon Ross ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags, 241b819cea2SGordon Ross size_t *sent, struct cred *cr) 242b819cea2SGordon Ross { 243b819cea2SGordon Ross ssize_t error; 244b819cea2SGordon Ross 245b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 246b819cea2SGordon Ross ASSERT(cr != NULL); 247b819cea2SGordon Ross 248b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 249b819cea2SGordon Ross if (sent != NULL) 250b819cea2SGordon Ross *sent = 0; 251b819cea2SGordon Ross return (ENOTSOCK); 252b819cea2SGordon Ross } 253b819cea2SGordon Ross 254b819cea2SGordon Ross error = send(KSTOSO(ks), msg, msglen, flags); 255b819cea2SGordon Ross if (error < 0) { 256b819cea2SGordon Ross if (sent != NULL) 257b819cea2SGordon Ross *sent = 0; 258b819cea2SGordon Ross return (errno); 259b819cea2SGordon Ross } 260b819cea2SGordon Ross 261b819cea2SGordon Ross if (sent != NULL) 262b819cea2SGordon Ross *sent = (size_t)error; 263b819cea2SGordon Ross return (0); 264b819cea2SGordon Ross } 265b819cea2SGordon Ross 266b819cea2SGordon Ross int 267b819cea2SGordon Ross ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags, 268b819cea2SGordon Ross struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr) 269b819cea2SGordon Ross { 270b819cea2SGordon Ross ssize_t error; 271b819cea2SGordon Ross 272b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 273b819cea2SGordon Ross ASSERT(cr != NULL); 274b819cea2SGordon Ross 275b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 276b819cea2SGordon Ross if (sent != NULL) 277b819cea2SGordon Ross *sent = 0; 278b819cea2SGordon Ross return (ENOTSOCK); 279b819cea2SGordon Ross } 280b819cea2SGordon Ross 281b819cea2SGordon Ross error = sendto(KSTOSO(ks), msg, msglen, flags, name, namelen); 282b819cea2SGordon Ross if (error < 0) { 283b819cea2SGordon Ross if (sent != NULL) 284b819cea2SGordon Ross *sent = 0; 285b819cea2SGordon Ross return (errno); 286b819cea2SGordon Ross } 287b819cea2SGordon Ross 288b819cea2SGordon Ross if (sent != NULL) 289b819cea2SGordon Ross *sent = (size_t)error; 290b819cea2SGordon Ross return (0); 291b819cea2SGordon Ross } 292b819cea2SGordon Ross 293b819cea2SGordon Ross int 294b819cea2SGordon Ross ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags, 295b819cea2SGordon Ross size_t *sent, struct cred *cr) 296b819cea2SGordon Ross { 297*a90cf9f2SGordon Ross uio_t uio; 298*a90cf9f2SGordon Ross ssize_t len; 299b819cea2SGordon Ross 300b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 301b819cea2SGordon Ross ASSERT(cr != NULL); 302b819cea2SGordon Ross 303b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 304b819cea2SGordon Ross if (sent != NULL) 305b819cea2SGordon Ross *sent = 0; 306b819cea2SGordon Ross return (ENOTSOCK); 307b819cea2SGordon Ross } 308b819cea2SGordon Ross 309*a90cf9f2SGordon Ross /* socksyscalls.c uses MSG_MAXIOVLEN (local macro), both are 16 */ 310*a90cf9f2SGordon Ross ASSERT3U(msg->msg_iovlen, <=, IOV_MAX); 311*a90cf9f2SGordon Ross len = sendmsg(KSTOSO(ks), msg, flags); 312*a90cf9f2SGordon Ross if (len < 0) { 313b819cea2SGordon Ross if (sent != NULL) 314b819cea2SGordon Ross *sent = 0; 315b819cea2SGordon Ross return (errno); 316b819cea2SGordon Ross } 317b819cea2SGordon Ross 318*a90cf9f2SGordon Ross /* 319*a90cf9f2SGordon Ross * The user-level sendmsg() does NOT update msg->iov like 320*a90cf9f2SGordon Ross * ksocket_sendmsg(). It's unclear whether that's a bug 321*a90cf9f2SGordon Ross * or if that was intentional. Anyway, update it here. 322*a90cf9f2SGordon Ross */ 323*a90cf9f2SGordon Ross if (msg->msg_iov != NULL) { 324*a90cf9f2SGordon Ross bzero(&uio, sizeof (uio)); 325*a90cf9f2SGordon Ross uio.uio_iov = msg->msg_iov; 326*a90cf9f2SGordon Ross uio.uio_iovcnt = msg->msg_iovlen; 327*a90cf9f2SGordon Ross uio.uio_resid = len; 328*a90cf9f2SGordon Ross 329*a90cf9f2SGordon Ross uioskip(&uio, len); 330*a90cf9f2SGordon Ross ASSERT(uio.uio_resid == 0); 331*a90cf9f2SGordon Ross 332*a90cf9f2SGordon Ross msg->msg_iov = uio.uio_iov; 333*a90cf9f2SGordon Ross msg->msg_iovlen = uio.uio_iovcnt; 334*a90cf9f2SGordon Ross } 335*a90cf9f2SGordon Ross 336b819cea2SGordon Ross if (sent != NULL) 337*a90cf9f2SGordon Ross *sent = (size_t)len; 338b819cea2SGordon Ross return (0); 339b819cea2SGordon Ross } 340b819cea2SGordon Ross 341b819cea2SGordon Ross int 342b819cea2SGordon Ross ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags, 343b819cea2SGordon Ross size_t *recvd, struct cred *cr) 344b819cea2SGordon Ross { 345b819cea2SGordon Ross ssize_t error; 346b819cea2SGordon Ross 347b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 348b819cea2SGordon Ross ASSERT(cr != NULL); 349b819cea2SGordon Ross 350b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 351b819cea2SGordon Ross if (recvd != NULL) 352b819cea2SGordon Ross *recvd = 0; 353b819cea2SGordon Ross return (ENOTSOCK); 354b819cea2SGordon Ross } 355b819cea2SGordon Ross 356b819cea2SGordon Ross error = recv(KSTOSO(ks), msg, msglen, flags); 357b819cea2SGordon Ross if (error < 0) { 358b819cea2SGordon Ross if (recvd != NULL) 359b819cea2SGordon Ross *recvd = 0; 360b819cea2SGordon Ross return (errno); 361b819cea2SGordon Ross } 362b819cea2SGordon Ross 363b819cea2SGordon Ross if (recvd != NULL) 364b819cea2SGordon Ross *recvd = (size_t)error; 365b819cea2SGordon Ross return (0); 366b819cea2SGordon Ross } 367b819cea2SGordon Ross 368b819cea2SGordon Ross int 369b819cea2SGordon Ross ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags, 370b819cea2SGordon Ross struct sockaddr *name, socklen_t *namelen, size_t *recvd, struct cred *cr) 371b819cea2SGordon Ross { 372b819cea2SGordon Ross ssize_t error; 373b819cea2SGordon Ross 374b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 375b819cea2SGordon Ross ASSERT(cr != NULL); 376b819cea2SGordon Ross 377b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 378b819cea2SGordon Ross if (recvd != NULL) 379b819cea2SGordon Ross *recvd = 0; 380b819cea2SGordon Ross return (ENOTSOCK); 381b819cea2SGordon Ross } 382b819cea2SGordon Ross 383b819cea2SGordon Ross error = recvfrom(KSTOSO(ks), msg, msglen, flags, name, namelen); 384b819cea2SGordon Ross if (error != 0) { 385b819cea2SGordon Ross if (recvd != NULL) 386b819cea2SGordon Ross *recvd = 0; 387b819cea2SGordon Ross return (errno); 388b819cea2SGordon Ross } 389b819cea2SGordon Ross 390b819cea2SGordon Ross if (recvd != NULL) 391b819cea2SGordon Ross *recvd = (ssize_t)error; 392b819cea2SGordon Ross return (0); 393b819cea2SGordon Ross } 394b819cea2SGordon Ross 395b819cea2SGordon Ross int 396b819cea2SGordon Ross ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recvd, 397b819cea2SGordon Ross struct cred *cr) 398b819cea2SGordon Ross { 399b819cea2SGordon Ross ssize_t error; 400b819cea2SGordon Ross 401b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 402b819cea2SGordon Ross ASSERT(cr != NULL); 403b819cea2SGordon Ross 404b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 405b819cea2SGordon Ross if (recvd != NULL) 406b819cea2SGordon Ross *recvd = 0; 407b819cea2SGordon Ross return (ENOTSOCK); 408b819cea2SGordon Ross } 409b819cea2SGordon Ross 410b819cea2SGordon Ross error = recvmsg(KSTOSO(ks), msg, flags); 411b819cea2SGordon Ross if (error < 0) { 412b819cea2SGordon Ross if (recvd != NULL) 413b819cea2SGordon Ross *recvd = 0; 414b819cea2SGordon Ross return (errno); 415b819cea2SGordon Ross } 416b819cea2SGordon Ross 417b819cea2SGordon Ross if (recvd != NULL) 418b819cea2SGordon Ross *recvd = (size_t)error; 419b819cea2SGordon Ross return (0); 420b819cea2SGordon Ross } 421b819cea2SGordon Ross 422b819cea2SGordon Ross int 423b819cea2SGordon Ross ksocket_shutdown(ksocket_t ks, int how, struct cred *cr) 424b819cea2SGordon Ross { 425b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 426b819cea2SGordon Ross ASSERT(cr != NULL); 427b819cea2SGordon Ross 428b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 429b819cea2SGordon Ross return (ENOTSOCK); 430b819cea2SGordon Ross 431b819cea2SGordon Ross if (shutdown(KSTOSO(ks), how) != 0) 432b819cea2SGordon Ross return (errno); 433b819cea2SGordon Ross 434b819cea2SGordon Ross return (0); 435b819cea2SGordon Ross } 436b819cea2SGordon Ross 437b819cea2SGordon Ross int 438b819cea2SGordon Ross ksocket_close(ksocket_t ks, struct cred *cr) 439b819cea2SGordon Ross { 440b819cea2SGordon Ross int fd; 441b819cea2SGordon Ross 442b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 443b819cea2SGordon Ross ASSERT(cr != NULL); 444b819cea2SGordon Ross 445b819cea2SGordon Ross mutex_enter(&ks->kso_lock); 446b819cea2SGordon Ross 447b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 448b819cea2SGordon Ross mutex_exit(&ks->kso_lock); 449b819cea2SGordon Ross return (ENOTSOCK); 450b819cea2SGordon Ross } 451b819cea2SGordon Ross 452b819cea2SGordon Ross ks->kso_state |= SS_CLOSING; 453b819cea2SGordon Ross 454b819cea2SGordon Ross /* 455b819cea2SGordon Ross * The real ksocket wakes up everything. 456b819cea2SGordon Ross * It seems the only way we can do that 457b819cea2SGordon Ross * is to go ahead and close the FD. 458b819cea2SGordon Ross */ 459b819cea2SGordon Ross fd = ks->kso_fd; 460b819cea2SGordon Ross ks->kso_fd = -1; 461b819cea2SGordon Ross (void) close(fd); 462b819cea2SGordon Ross 463b819cea2SGordon Ross while (ks->kso_count > 1) 464b819cea2SGordon Ross cv_wait(&ks->kso_closing_cv, &ks->kso_lock); 465b819cea2SGordon Ross 466b819cea2SGordon Ross mutex_exit(&ks->kso_lock); 467b819cea2SGordon Ross _ksocket_destroy(ks); 468b819cea2SGordon Ross 469b819cea2SGordon Ross return (0); 470b819cea2SGordon Ross } 471b819cea2SGordon Ross 472b819cea2SGordon Ross int 473b819cea2SGordon Ross ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 474b819cea2SGordon Ross struct cred *cr) 475b819cea2SGordon Ross { 476b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 477b819cea2SGordon Ross ASSERT(cr != NULL); 478b819cea2SGordon Ross 479b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 480b819cea2SGordon Ross return (ENOTSOCK); 481b819cea2SGordon Ross 482b819cea2SGordon Ross if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 483b819cea2SGordon Ross return (EFAULT); 484b819cea2SGordon Ross 485b819cea2SGordon Ross if (getsockname(KSTOSO(ks), addr, addrlen) != 0) 486b819cea2SGordon Ross return (errno); 487b819cea2SGordon Ross 488b819cea2SGordon Ross return (0); 489b819cea2SGordon Ross } 490b819cea2SGordon Ross 491b819cea2SGordon Ross int 492b819cea2SGordon Ross ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 493b819cea2SGordon Ross struct cred *cr) 494b819cea2SGordon Ross { 495b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 496b819cea2SGordon Ross ASSERT(cr != NULL); 497b819cea2SGordon Ross 498b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 499b819cea2SGordon Ross return (ENOTSOCK); 500b819cea2SGordon Ross 501b819cea2SGordon Ross if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 502b819cea2SGordon Ross return (EFAULT); 503b819cea2SGordon Ross 504b819cea2SGordon Ross if (getpeername(KSTOSO(ks), addr, addrlen) != 0) 505b819cea2SGordon Ross return (errno); 506b819cea2SGordon Ross 507b819cea2SGordon Ross return (0); 508b819cea2SGordon Ross } 509b819cea2SGordon Ross 510b819cea2SGordon Ross int 511b819cea2SGordon Ross ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval, 512b819cea2SGordon Ross int optlen, struct cred *cr) 513b819cea2SGordon Ross { 514b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 515b819cea2SGordon Ross ASSERT(cr != NULL); 516b819cea2SGordon Ross 517b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 518b819cea2SGordon Ross return (ENOTSOCK); 519b819cea2SGordon Ross 520b819cea2SGordon Ross if (optval == NULL) 521b819cea2SGordon Ross optlen = 0; 522b819cea2SGordon Ross 523b819cea2SGordon Ross if (setsockopt(KSTOSO(ks), level, optname, optval, optlen) != 0) 524b819cea2SGordon Ross return (errno); 525b819cea2SGordon Ross 526b819cea2SGordon Ross return (0); 527b819cea2SGordon Ross } 528b819cea2SGordon Ross 52968b2bbf2SGordon Ross int 53068b2bbf2SGordon Ross ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvp, struct cred *cr) 53168b2bbf2SGordon Ross { 53268b2bbf2SGordon Ross int rval; 53368b2bbf2SGordon Ross 53468b2bbf2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 53568b2bbf2SGordon Ross ASSERT(cr != NULL); 53668b2bbf2SGordon Ross 53768b2bbf2SGordon Ross if (!KSOCKET_VALID(ks)) 53868b2bbf2SGordon Ross return (ENOTSOCK); 53968b2bbf2SGordon Ross 54068b2bbf2SGordon Ross rval = ioctl(KSTOSO(ks), cmd, arg); 54168b2bbf2SGordon Ross if (rvp != NULL) 54268b2bbf2SGordon Ross *rvp = rval; 54368b2bbf2SGordon Ross 54468b2bbf2SGordon Ross if (rval != 0) 54568b2bbf2SGordon Ross rval = errno; 54668b2bbf2SGordon Ross 54768b2bbf2SGordon Ross return (rval); 54868b2bbf2SGordon Ross } 54968b2bbf2SGordon Ross 550b819cea2SGordon Ross void 551b819cea2SGordon Ross ksocket_hold(ksocket_t ks) 552b819cea2SGordon Ross { 553b819cea2SGordon Ross if (!mutex_owned(&ks->kso_lock)) { 554b819cea2SGordon Ross mutex_enter(&ks->kso_lock); 555b819cea2SGordon Ross ks->kso_count++; 556b819cea2SGordon Ross mutex_exit(&ks->kso_lock); 557b819cea2SGordon Ross } else 558b819cea2SGordon Ross ks->kso_count++; 559b819cea2SGordon Ross } 560b819cea2SGordon Ross 561b819cea2SGordon Ross void 562b819cea2SGordon Ross ksocket_rele(ksocket_t ks) 563b819cea2SGordon Ross { 564b819cea2SGordon Ross /* 565b819cea2SGordon Ross * When so_count equals 1 means no thread working on this ksocket 566b819cea2SGordon Ross */ 567b819cea2SGordon Ross VERIFY3U(ks->kso_count, >, 1); 568b819cea2SGordon Ross 569b819cea2SGordon Ross if (!mutex_owned(&ks->kso_lock)) { 570b819cea2SGordon Ross mutex_enter(&ks->kso_lock); 571b819cea2SGordon Ross if (--ks->kso_count == 1) 572b819cea2SGordon Ross cv_signal(&ks->kso_closing_cv); 573b819cea2SGordon Ross mutex_exit(&ks->kso_lock); 574b819cea2SGordon Ross } else { 575b819cea2SGordon Ross if (--ks->kso_count == 1) 576b819cea2SGordon Ross cv_signal(&ks->kso_closing_cv); 577b819cea2SGordon Ross } 578b819cea2SGordon Ross } 579