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