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