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*68b2bbf2SGordon Ross * Copyright 2014 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> 35b819cea2SGordon Ross #include <unistd.h> 36b819cea2SGordon Ross #include <errno.h> 37b819cea2SGordon Ross #include <umem.h> 38b819cea2SGordon Ross 39b819cea2SGordon Ross #define _KSOCKET_MAGIC 0xabcdef09 40b819cea2SGordon Ross 41b819cea2SGordon Ross #define KSOCKET_VALID(ks) (ks->kso_magic == _KSOCKET_MAGIC) 42b819cea2SGordon Ross #define KSTOSO(ks) (ks->kso_fd) 43b819cea2SGordon Ross 44b819cea2SGordon Ross #ifndef SS_CLOSING 45b819cea2SGordon Ross #define SS_CLOSING 0x00010000 46b819cea2SGordon Ross #endif 47b819cea2SGordon Ross 48b819cea2SGordon Ross /* 49b819cea2SGordon Ross * NB: you can't cast this into a sonode like you can with a normal 50b819cea2SGordon Ross * ksocket_t, but no correct code should ever do that anyway. 51b819cea2SGordon Ross * The ksocket_t type is opaque to prevent exactly that. 52b819cea2SGordon Ross */ 53b819cea2SGordon Ross struct __ksocket { 54b819cea2SGordon Ross uint32_t kso_magic; 55b819cea2SGordon Ross uint32_t kso_count; 56b819cea2SGordon Ross uint32_t kso_state; 57b819cea2SGordon Ross int kso_fd; 58b819cea2SGordon Ross kmutex_t kso_lock; 59b819cea2SGordon Ross kcondvar_t kso_closing_cv; 60b819cea2SGordon Ross }; 61b819cea2SGordon Ross 62b819cea2SGordon Ross static umem_cache_t *ksocket_cache = NULL; 63b819cea2SGordon Ross 64b819cea2SGordon Ross /*ARGSUSED*/ 65b819cea2SGordon Ross static int 66b819cea2SGordon Ross _ksocket_ctor(void *buf, void *arg, int flags) 67b819cea2SGordon Ross { 68b819cea2SGordon Ross ksocket_t sock = buf; 69b819cea2SGordon Ross 70b819cea2SGordon Ross bzero(sock, sizeof (*sock)); 71b819cea2SGordon Ross mutex_init(&sock->kso_lock, NULL, MUTEX_DEFAULT, NULL); 72b819cea2SGordon Ross cv_init(&sock->kso_closing_cv, NULL, CV_DEFAULT, NULL); 73b819cea2SGordon Ross return (0); 74b819cea2SGordon Ross } 75b819cea2SGordon Ross 76b819cea2SGordon Ross /*ARGSUSED*/ 77b819cea2SGordon Ross static void 78b819cea2SGordon Ross _ksocket_dtor(void *buf, void *arg) 79b819cea2SGordon Ross { 80b819cea2SGordon Ross ksocket_t sock = buf; 81b819cea2SGordon Ross 82b819cea2SGordon Ross mutex_destroy(&sock->kso_lock); 83b819cea2SGordon Ross cv_destroy(&sock->kso_closing_cv); 84b819cea2SGordon Ross } 85b819cea2SGordon Ross 86b819cea2SGordon Ross #pragma init(_ksocket_init) 87b819cea2SGordon Ross int 88b819cea2SGordon Ross _ksocket_init(void) 89b819cea2SGordon Ross { 90b819cea2SGordon Ross ksocket_cache = umem_cache_create("ksocket", 91b819cea2SGordon Ross sizeof (struct __ksocket), 0, 92b819cea2SGordon Ross _ksocket_ctor, _ksocket_dtor, NULL, NULL, NULL, 0); 93b819cea2SGordon Ross VERIFY(ksocket_cache != NULL); 94b819cea2SGordon Ross return (0); 95b819cea2SGordon Ross } 96b819cea2SGordon Ross 97b819cea2SGordon Ross #pragma fini(_ksocket_fini) 98b819cea2SGordon Ross int 99b819cea2SGordon Ross _ksocket_fini(void) 100b819cea2SGordon Ross { 101b819cea2SGordon Ross umem_cache_destroy(ksocket_cache); 102b819cea2SGordon Ross return (0); 103b819cea2SGordon Ross } 104b819cea2SGordon Ross 105b819cea2SGordon Ross static ksocket_t 106b819cea2SGordon Ross _ksocket_create(int fd) 107b819cea2SGordon Ross { 108b819cea2SGordon Ross ksocket_t ks; 109b819cea2SGordon Ross 110b819cea2SGordon Ross ks = umem_cache_alloc(ksocket_cache, 0); 111b819cea2SGordon Ross VERIFY(ks != NULL); 112b819cea2SGordon Ross ks->kso_magic = _KSOCKET_MAGIC; 113b819cea2SGordon Ross ks->kso_count = 1; 114b819cea2SGordon Ross ks->kso_fd = fd; 115b819cea2SGordon Ross return (ks); 116b819cea2SGordon Ross } 117b819cea2SGordon Ross 118b819cea2SGordon Ross static void 119b819cea2SGordon Ross _ksocket_destroy(ksocket_t ks) 120b819cea2SGordon Ross { 121b819cea2SGordon Ross ASSERT(ks->kso_count == 1); 122b819cea2SGordon Ross umem_cache_free(ksocket_cache, ks); 123b819cea2SGordon Ross } 124b819cea2SGordon Ross 125b819cea2SGordon Ross int 126b819cea2SGordon Ross ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags, 127b819cea2SGordon Ross struct cred *cr) 128b819cea2SGordon Ross { 129b819cea2SGordon Ross int fd; 130b819cea2SGordon Ross ksocket_t ks; 131b819cea2SGordon Ross 132b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 133b819cea2SGordon Ross ASSERT(cr != NULL); 134b819cea2SGordon Ross 135b819cea2SGordon Ross ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP); 136b819cea2SGordon Ross 137b819cea2SGordon Ross fd = socket(domain, type, protocol); 138b819cea2SGordon Ross if (fd < 0) { 139b819cea2SGordon Ross *ksp = NULL; 140b819cea2SGordon Ross return (errno); 141b819cea2SGordon Ross } 142b819cea2SGordon Ross 143b819cea2SGordon Ross ks = _ksocket_create(fd); 144b819cea2SGordon Ross *ksp = ks; 145b819cea2SGordon Ross return (0); 146b819cea2SGordon Ross } 147b819cea2SGordon Ross 148b819cea2SGordon Ross /* 149b819cea2SGordon Ross * This is marked NODIRECT so the main program linking with this library 150b819cea2SGordon Ross * can provide its own "bind helper" function. See: fksmbd_ksock.c 151b819cea2SGordon Ross */ 152b819cea2SGordon Ross /* ARGSUSED */ 153b819cea2SGordon Ross int 154b819cea2SGordon Ross ksocket_bind_helper(int fd, struct sockaddr *addr, uint_t addrlen) 155b819cea2SGordon Ross { 156b819cea2SGordon Ross return (EACCES); 157b819cea2SGordon Ross } 158b819cea2SGordon Ross 159b819cea2SGordon Ross int 160b819cea2SGordon Ross ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen, 161b819cea2SGordon Ross struct cred *cr) 162b819cea2SGordon Ross { 163b819cea2SGordon Ross int err = 0; 164b819cea2SGordon Ross 165b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 166b819cea2SGordon Ross ASSERT(cr != NULL); 167b819cea2SGordon Ross 168b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 169b819cea2SGordon Ross return (ENOTSOCK); 170b819cea2SGordon Ross 171b819cea2SGordon Ross if (bind(KSTOSO(ks), addr, addrlen) != 0) 172b819cea2SGordon Ross err = errno; 173b819cea2SGordon Ross 174b819cea2SGordon Ross if (err == EACCES) { 175b819cea2SGordon Ross err = ksocket_bind_helper(KSTOSO(ks), addr, addrlen); 176b819cea2SGordon Ross } 177b819cea2SGordon Ross 178b819cea2SGordon Ross return (err); 179b819cea2SGordon Ross } 180b819cea2SGordon Ross 181b819cea2SGordon Ross int 182b819cea2SGordon Ross ksocket_listen(ksocket_t ks, int backlog, struct cred *cr) 183b819cea2SGordon Ross { 184b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 185b819cea2SGordon Ross ASSERT(cr != NULL); 186b819cea2SGordon Ross 187b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 188b819cea2SGordon Ross return (ENOTSOCK); 189b819cea2SGordon Ross 190b819cea2SGordon Ross if (listen(KSTOSO(ks), backlog) != 0) 191b819cea2SGordon Ross return (errno); 192b819cea2SGordon Ross 193b819cea2SGordon Ross return (0); 194b819cea2SGordon Ross } 195b819cea2SGordon Ross 196b819cea2SGordon Ross int 197b819cea2SGordon Ross ksocket_accept(ksocket_t ks, struct sockaddr *addr, 198b819cea2SGordon Ross socklen_t *addrlenp, ksocket_t *nks, struct cred *cr) 199b819cea2SGordon Ross { 200b819cea2SGordon Ross int fd; 201b819cea2SGordon Ross 202b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 203b819cea2SGordon Ross ASSERT(cr != NULL); 204b819cea2SGordon Ross 205b819cea2SGordon Ross *nks = NULL; 206b819cea2SGordon Ross 207b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 208b819cea2SGordon Ross return (ENOTSOCK); 209b819cea2SGordon Ross 210b819cea2SGordon Ross if (addr != NULL && addrlenp == NULL) 211b819cea2SGordon Ross return (EFAULT); 212b819cea2SGordon Ross 213b819cea2SGordon Ross fd = accept(KSTOSO(ks), addr, addrlenp); 214b819cea2SGordon Ross if (fd < 0) 215b819cea2SGordon Ross return (errno); 216b819cea2SGordon Ross 217b819cea2SGordon Ross *nks = _ksocket_create(fd); 218b819cea2SGordon Ross 219b819cea2SGordon Ross return (0); 220b819cea2SGordon Ross } 221b819cea2SGordon Ross 222b819cea2SGordon Ross int 223b819cea2SGordon Ross ksocket_connect(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen, 224b819cea2SGordon Ross struct cred *cr) 225b819cea2SGordon Ross { 226b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 227b819cea2SGordon Ross ASSERT(cr != NULL); 228b819cea2SGordon Ross 229b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 230b819cea2SGordon Ross return (ENOTSOCK); 231b819cea2SGordon Ross 232b819cea2SGordon Ross if (connect(KSTOSO(ks), addr, addrlen) != 0) 233b819cea2SGordon Ross return (errno); 234b819cea2SGordon Ross 235b819cea2SGordon Ross return (0); 236b819cea2SGordon Ross } 237b819cea2SGordon Ross 238b819cea2SGordon Ross int 239b819cea2SGordon Ross ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags, 240b819cea2SGordon Ross size_t *sent, struct cred *cr) 241b819cea2SGordon Ross { 242b819cea2SGordon Ross ssize_t error; 243b819cea2SGordon Ross 244b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 245b819cea2SGordon Ross ASSERT(cr != NULL); 246b819cea2SGordon Ross 247b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 248b819cea2SGordon Ross if (sent != NULL) 249b819cea2SGordon Ross *sent = 0; 250b819cea2SGordon Ross return (ENOTSOCK); 251b819cea2SGordon Ross } 252b819cea2SGordon Ross 253b819cea2SGordon Ross error = send(KSTOSO(ks), msg, msglen, flags); 254b819cea2SGordon Ross if (error < 0) { 255b819cea2SGordon Ross if (sent != NULL) 256b819cea2SGordon Ross *sent = 0; 257b819cea2SGordon Ross return (errno); 258b819cea2SGordon Ross } 259b819cea2SGordon Ross 260b819cea2SGordon Ross if (sent != NULL) 261b819cea2SGordon Ross *sent = (size_t)error; 262b819cea2SGordon Ross return (0); 263b819cea2SGordon Ross } 264b819cea2SGordon Ross 265b819cea2SGordon Ross int 266b819cea2SGordon Ross ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags, 267b819cea2SGordon Ross struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr) 268b819cea2SGordon Ross { 269b819cea2SGordon Ross ssize_t error; 270b819cea2SGordon Ross 271b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 272b819cea2SGordon Ross ASSERT(cr != NULL); 273b819cea2SGordon Ross 274b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 275b819cea2SGordon Ross if (sent != NULL) 276b819cea2SGordon Ross *sent = 0; 277b819cea2SGordon Ross return (ENOTSOCK); 278b819cea2SGordon Ross } 279b819cea2SGordon Ross 280b819cea2SGordon Ross error = sendto(KSTOSO(ks), msg, msglen, flags, name, namelen); 281b819cea2SGordon Ross if (error < 0) { 282b819cea2SGordon Ross if (sent != NULL) 283b819cea2SGordon Ross *sent = 0; 284b819cea2SGordon Ross return (errno); 285b819cea2SGordon Ross } 286b819cea2SGordon Ross 287b819cea2SGordon Ross if (sent != NULL) 288b819cea2SGordon Ross *sent = (size_t)error; 289b819cea2SGordon Ross return (0); 290b819cea2SGordon Ross } 291b819cea2SGordon Ross 292b819cea2SGordon Ross int 293b819cea2SGordon Ross ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags, 294b819cea2SGordon Ross size_t *sent, struct cred *cr) 295b819cea2SGordon Ross { 296b819cea2SGordon Ross ssize_t error; 297b819cea2SGordon Ross 298b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 299b819cea2SGordon Ross ASSERT(cr != NULL); 300b819cea2SGordon Ross 301b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 302b819cea2SGordon Ross if (sent != NULL) 303b819cea2SGordon Ross *sent = 0; 304b819cea2SGordon Ross return (ENOTSOCK); 305b819cea2SGordon Ross } 306b819cea2SGordon Ross 307b819cea2SGordon Ross error = sendmsg(KSTOSO(ks), msg, flags); 308b819cea2SGordon Ross if (error < 0) { 309b819cea2SGordon Ross if (sent != NULL) 310b819cea2SGordon Ross *sent = 0; 311b819cea2SGordon Ross return (errno); 312b819cea2SGordon Ross } 313b819cea2SGordon Ross 314b819cea2SGordon Ross if (sent != NULL) 315b819cea2SGordon Ross *sent = (size_t)error; 316b819cea2SGordon Ross return (0); 317b819cea2SGordon Ross } 318b819cea2SGordon Ross 319b819cea2SGordon Ross int 320b819cea2SGordon Ross ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags, 321b819cea2SGordon Ross size_t *recvd, struct cred *cr) 322b819cea2SGordon Ross { 323b819cea2SGordon Ross ssize_t error; 324b819cea2SGordon Ross 325b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 326b819cea2SGordon Ross ASSERT(cr != NULL); 327b819cea2SGordon Ross 328b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 329b819cea2SGordon Ross if (recvd != NULL) 330b819cea2SGordon Ross *recvd = 0; 331b819cea2SGordon Ross return (ENOTSOCK); 332b819cea2SGordon Ross } 333b819cea2SGordon Ross 334b819cea2SGordon Ross error = recv(KSTOSO(ks), msg, msglen, flags); 335b819cea2SGordon Ross if (error < 0) { 336b819cea2SGordon Ross if (recvd != NULL) 337b819cea2SGordon Ross *recvd = 0; 338b819cea2SGordon Ross return (errno); 339b819cea2SGordon Ross } 340b819cea2SGordon Ross 341b819cea2SGordon Ross if (recvd != NULL) 342b819cea2SGordon Ross *recvd = (size_t)error; 343b819cea2SGordon Ross return (0); 344b819cea2SGordon Ross } 345b819cea2SGordon Ross 346b819cea2SGordon Ross int 347b819cea2SGordon Ross ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags, 348b819cea2SGordon Ross struct sockaddr *name, socklen_t *namelen, size_t *recvd, struct cred *cr) 349b819cea2SGordon Ross { 350b819cea2SGordon Ross ssize_t error; 351b819cea2SGordon Ross 352b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 353b819cea2SGordon Ross ASSERT(cr != NULL); 354b819cea2SGordon Ross 355b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 356b819cea2SGordon Ross if (recvd != NULL) 357b819cea2SGordon Ross *recvd = 0; 358b819cea2SGordon Ross return (ENOTSOCK); 359b819cea2SGordon Ross } 360b819cea2SGordon Ross 361b819cea2SGordon Ross error = recvfrom(KSTOSO(ks), msg, msglen, flags, name, namelen); 362b819cea2SGordon Ross if (error != 0) { 363b819cea2SGordon Ross if (recvd != NULL) 364b819cea2SGordon Ross *recvd = 0; 365b819cea2SGordon Ross return (errno); 366b819cea2SGordon Ross } 367b819cea2SGordon Ross 368b819cea2SGordon Ross if (recvd != NULL) 369b819cea2SGordon Ross *recvd = (ssize_t)error; 370b819cea2SGordon Ross return (0); 371b819cea2SGordon Ross } 372b819cea2SGordon Ross 373b819cea2SGordon Ross int 374b819cea2SGordon Ross ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recvd, 375b819cea2SGordon Ross struct cred *cr) 376b819cea2SGordon Ross { 377b819cea2SGordon Ross ssize_t error; 378b819cea2SGordon Ross 379b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 380b819cea2SGordon Ross ASSERT(cr != NULL); 381b819cea2SGordon Ross 382b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 383b819cea2SGordon Ross if (recvd != NULL) 384b819cea2SGordon Ross *recvd = 0; 385b819cea2SGordon Ross return (ENOTSOCK); 386b819cea2SGordon Ross } 387b819cea2SGordon Ross 388b819cea2SGordon Ross error = recvmsg(KSTOSO(ks), msg, flags); 389b819cea2SGordon Ross if (error < 0) { 390b819cea2SGordon Ross if (recvd != NULL) 391b819cea2SGordon Ross *recvd = 0; 392b819cea2SGordon Ross return (errno); 393b819cea2SGordon Ross } 394b819cea2SGordon Ross 395b819cea2SGordon Ross if (recvd != NULL) 396b819cea2SGordon Ross *recvd = (size_t)error; 397b819cea2SGordon Ross return (0); 398b819cea2SGordon Ross } 399b819cea2SGordon Ross 400b819cea2SGordon Ross int 401b819cea2SGordon Ross ksocket_shutdown(ksocket_t ks, int how, struct cred *cr) 402b819cea2SGordon Ross { 403b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 404b819cea2SGordon Ross ASSERT(cr != NULL); 405b819cea2SGordon Ross 406b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 407b819cea2SGordon Ross return (ENOTSOCK); 408b819cea2SGordon Ross 409b819cea2SGordon Ross if (shutdown(KSTOSO(ks), how) != 0) 410b819cea2SGordon Ross return (errno); 411b819cea2SGordon Ross 412b819cea2SGordon Ross return (0); 413b819cea2SGordon Ross } 414b819cea2SGordon Ross 415b819cea2SGordon Ross int 416b819cea2SGordon Ross ksocket_close(ksocket_t ks, struct cred *cr) 417b819cea2SGordon Ross { 418b819cea2SGordon Ross int fd; 419b819cea2SGordon Ross 420b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 421b819cea2SGordon Ross ASSERT(cr != NULL); 422b819cea2SGordon Ross 423b819cea2SGordon Ross mutex_enter(&ks->kso_lock); 424b819cea2SGordon Ross 425b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) { 426b819cea2SGordon Ross mutex_exit(&ks->kso_lock); 427b819cea2SGordon Ross return (ENOTSOCK); 428b819cea2SGordon Ross } 429b819cea2SGordon Ross 430b819cea2SGordon Ross ks->kso_state |= SS_CLOSING; 431b819cea2SGordon Ross 432b819cea2SGordon Ross /* 433b819cea2SGordon Ross * The real ksocket wakes up everything. 434b819cea2SGordon Ross * It seems the only way we can do that 435b819cea2SGordon Ross * is to go ahead and close the FD. 436b819cea2SGordon Ross */ 437b819cea2SGordon Ross fd = ks->kso_fd; 438b819cea2SGordon Ross ks->kso_fd = -1; 439b819cea2SGordon Ross (void) close(fd); 440b819cea2SGordon Ross 441b819cea2SGordon Ross while (ks->kso_count > 1) 442b819cea2SGordon Ross cv_wait(&ks->kso_closing_cv, &ks->kso_lock); 443b819cea2SGordon Ross 444b819cea2SGordon Ross mutex_exit(&ks->kso_lock); 445b819cea2SGordon Ross _ksocket_destroy(ks); 446b819cea2SGordon Ross 447b819cea2SGordon Ross return (0); 448b819cea2SGordon Ross } 449b819cea2SGordon Ross 450b819cea2SGordon Ross int 451b819cea2SGordon Ross ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 452b819cea2SGordon Ross struct cred *cr) 453b819cea2SGordon Ross { 454b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 455b819cea2SGordon Ross ASSERT(cr != NULL); 456b819cea2SGordon Ross 457b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 458b819cea2SGordon Ross return (ENOTSOCK); 459b819cea2SGordon Ross 460b819cea2SGordon Ross if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 461b819cea2SGordon Ross return (EFAULT); 462b819cea2SGordon Ross 463b819cea2SGordon Ross if (getsockname(KSTOSO(ks), addr, addrlen) != 0) 464b819cea2SGordon Ross return (errno); 465b819cea2SGordon Ross 466b819cea2SGordon Ross return (0); 467b819cea2SGordon Ross } 468b819cea2SGordon Ross 469b819cea2SGordon Ross int 470b819cea2SGordon Ross ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 471b819cea2SGordon Ross struct cred *cr) 472b819cea2SGordon Ross { 473b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 474b819cea2SGordon Ross ASSERT(cr != NULL); 475b819cea2SGordon Ross 476b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 477b819cea2SGordon Ross return (ENOTSOCK); 478b819cea2SGordon Ross 479b819cea2SGordon Ross if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 480b819cea2SGordon Ross return (EFAULT); 481b819cea2SGordon Ross 482b819cea2SGordon Ross if (getpeername(KSTOSO(ks), addr, addrlen) != 0) 483b819cea2SGordon Ross return (errno); 484b819cea2SGordon Ross 485b819cea2SGordon Ross return (0); 486b819cea2SGordon Ross } 487b819cea2SGordon Ross 488b819cea2SGordon Ross int 489b819cea2SGordon Ross ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval, 490b819cea2SGordon Ross int optlen, struct cred *cr) 491b819cea2SGordon Ross { 492b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 493b819cea2SGordon Ross ASSERT(cr != NULL); 494b819cea2SGordon Ross 495b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) 496b819cea2SGordon Ross return (ENOTSOCK); 497b819cea2SGordon Ross 498b819cea2SGordon Ross if (optval == NULL) 499b819cea2SGordon Ross optlen = 0; 500b819cea2SGordon Ross 501b819cea2SGordon Ross if (setsockopt(KSTOSO(ks), level, optname, optval, optlen) != 0) 502b819cea2SGordon Ross return (errno); 503b819cea2SGordon Ross 504b819cea2SGordon Ross return (0); 505b819cea2SGordon Ross } 506b819cea2SGordon Ross 507*68b2bbf2SGordon Ross int 508*68b2bbf2SGordon Ross ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvp, struct cred *cr) 509*68b2bbf2SGordon Ross { 510*68b2bbf2SGordon Ross int rval; 511*68b2bbf2SGordon Ross 512*68b2bbf2SGordon Ross /* All Solaris components should pass a cred for this operation. */ 513*68b2bbf2SGordon Ross ASSERT(cr != NULL); 514*68b2bbf2SGordon Ross 515*68b2bbf2SGordon Ross if (!KSOCKET_VALID(ks)) 516*68b2bbf2SGordon Ross return (ENOTSOCK); 517*68b2bbf2SGordon Ross 518*68b2bbf2SGordon Ross rval = ioctl(KSTOSO(ks), cmd, arg); 519*68b2bbf2SGordon Ross if (rvp != NULL) 520*68b2bbf2SGordon Ross *rvp = rval; 521*68b2bbf2SGordon Ross 522*68b2bbf2SGordon Ross if (rval != 0) 523*68b2bbf2SGordon Ross rval = errno; 524*68b2bbf2SGordon Ross 525*68b2bbf2SGordon Ross return (rval); 526*68b2bbf2SGordon Ross } 527*68b2bbf2SGordon Ross 528b819cea2SGordon Ross void 529b819cea2SGordon Ross ksocket_hold(ksocket_t ks) 530b819cea2SGordon Ross { 531b819cea2SGordon Ross if (!mutex_owned(&ks->kso_lock)) { 532b819cea2SGordon Ross mutex_enter(&ks->kso_lock); 533b819cea2SGordon Ross ks->kso_count++; 534b819cea2SGordon Ross mutex_exit(&ks->kso_lock); 535b819cea2SGordon Ross } else 536b819cea2SGordon Ross ks->kso_count++; 537b819cea2SGordon Ross } 538b819cea2SGordon Ross 539b819cea2SGordon Ross void 540b819cea2SGordon Ross ksocket_rele(ksocket_t ks) 541b819cea2SGordon Ross { 542b819cea2SGordon Ross /* 543b819cea2SGordon Ross * When so_count equals 1 means no thread working on this ksocket 544b819cea2SGordon Ross */ 545b819cea2SGordon Ross VERIFY3U(ks->kso_count, >, 1); 546b819cea2SGordon Ross 547b819cea2SGordon Ross if (!mutex_owned(&ks->kso_lock)) { 548b819cea2SGordon Ross mutex_enter(&ks->kso_lock); 549b819cea2SGordon Ross if (--ks->kso_count == 1) 550b819cea2SGordon Ross cv_signal(&ks->kso_closing_cv); 551b819cea2SGordon Ross mutex_exit(&ks->kso_lock); 552b819cea2SGordon Ross } else { 553b819cea2SGordon Ross if (--ks->kso_count == 1) 554b819cea2SGordon Ross cv_signal(&ks->kso_closing_cv); 555b819cea2SGordon Ross } 556b819cea2SGordon Ross } 557