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 2011 Nexenta Systems, Inc. All rights reserved. 24 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 25 * Copyright 2015, Joyent, Inc. 26 * Copyright 2022 Garrett D'Amore 27 */ 28 29 #include <sys/file.h> 30 #include <sys/stropts.h> 31 #include <sys/socket.h> 32 #include <sys/socketvar.h> 33 #include <sys/sysmacros.h> 34 #include <sys/filio.h> /* FIO* ioctls */ 35 #include <sys/sockio.h> /* SIOC* ioctls */ 36 #include <sys/poll_impl.h> 37 #include <sys/cmn_err.h> 38 #include <sys/ksocket.h> 39 #include <io/ksocket/ksocket_impl.h> 40 #include <fs/sockfs/sockcommon.h> 41 42 #define SOCKETMOD_TCP "tcp" 43 #define SOCKETMOD_UDP "udp" 44 /* 45 * Kernel Sockets 46 * 47 * Mostly a wrapper around the private socket_* functions. 48 */ 49 int 50 ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags, 51 struct cred *cr) 52 { 53 static const int version = SOV_DEFAULT; 54 int error = 0; 55 struct sonode *so; 56 *ksp = NULL; 57 58 /* All Solaris components should pass a cred for this operation. */ 59 ASSERT(cr != NULL); 60 61 ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP); 62 so = socket_create(domain, type, protocol, NULL, NULL, version, flags, 63 cr, &error); 64 if (so == NULL) { 65 if (error == EAFNOSUPPORT) { 66 char *mod = NULL; 67 68 /* 69 * Could be that root file system is not loaded or 70 * soconfig has not run yet. 71 */ 72 if (type == SOCK_STREAM && (domain == AF_INET || 73 domain == AF_INET6) && (protocol == 0 || 74 protocol == IPPROTO_TCP)) { 75 mod = SOCKETMOD_TCP; 76 } else if (type == SOCK_DGRAM && (domain == AF_INET || 77 domain == AF_INET6) && (protocol == 0 || 78 protocol == IPPROTO_UDP)) { 79 mod = SOCKETMOD_UDP; 80 } else { 81 return (EAFNOSUPPORT); 82 } 83 84 so = socket_create(domain, type, protocol, NULL, 85 mod, version, flags, cr, &error); 86 if (so == NULL) 87 return (error); 88 } else { 89 return (error); 90 } 91 } 92 93 so->so_mode |= SM_KERNEL; 94 95 *ksp = SOTOKS(so); 96 97 return (0); 98 } 99 int 100 ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen, 101 struct cred *cr) 102 { 103 int error; 104 105 /* All Solaris components should pass a cred for this operation. */ 106 ASSERT(cr != NULL); 107 108 if (!KSOCKET_VALID(ks)) 109 return (ENOTSOCK); 110 111 error = socket_bind(KSTOSO(ks), addr, addrlen, _SOBIND_SOCKBSD, cr); 112 113 return (error); 114 } 115 116 int 117 ksocket_listen(ksocket_t ks, int backlog, struct cred *cr) 118 { 119 /* All Solaris components should pass a cred for this operation. */ 120 ASSERT(cr != NULL); 121 122 if (!KSOCKET_VALID(ks)) 123 return (ENOTSOCK); 124 125 return (socket_listen(KSTOSO(ks), backlog, cr)); 126 } 127 128 int 129 ksocket_accept(ksocket_t ks, struct sockaddr *addr, 130 socklen_t *addrlenp, ksocket_t *nks, struct cred *cr) 131 { 132 int error; 133 struct sonode *nso = NULL; 134 135 /* All Solaris components should pass a cred for this operation. */ 136 ASSERT(cr != NULL); 137 138 *nks = NULL; 139 140 if (!KSOCKET_VALID(ks)) 141 return (ENOTSOCK); 142 143 if (addr != NULL && addrlenp == NULL) 144 return (EFAULT); 145 146 error = socket_accept(KSTOSO(ks), KSOCKET_FMODE(ks), cr, &nso); 147 if (error != 0) 148 return (error); 149 150 ASSERT(nso != NULL); 151 152 nso->so_mode |= SM_KERNEL; 153 154 if (addr != NULL && addrlenp != NULL) { 155 error = socket_getpeername(nso, addr, addrlenp, B_TRUE, cr); 156 if (error != 0) { 157 (void) socket_close(nso, 0, cr); 158 socket_destroy(nso); 159 return ((error == ENOTCONN) ? ECONNABORTED : error); 160 } 161 } 162 163 *nks = SOTOKS(nso); 164 165 return (error); 166 } 167 168 int 169 ksocket_connect(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen, 170 struct cred *cr) 171 { 172 /* All Solaris components should pass a cred for this operation. */ 173 ASSERT(cr != NULL); 174 175 if (!KSOCKET_VALID(ks)) 176 return (ENOTSOCK); 177 178 return (socket_connect(KSTOSO(ks), addr, addrlen, 179 KSOCKET_FMODE(ks), 0, cr)); 180 } 181 182 int 183 ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags, 184 size_t *sent, struct cred *cr) 185 { 186 int error; 187 struct nmsghdr msghdr; 188 struct uio auio; 189 struct iovec iov; 190 191 /* All Solaris components should pass a cred for this operation. */ 192 ASSERT(cr != NULL); 193 194 if (!KSOCKET_VALID(ks)) { 195 if (sent != NULL) 196 *sent = 0; 197 return (ENOTSOCK); 198 } 199 200 iov.iov_base = msg; 201 iov.iov_len = msglen; 202 203 bzero(&auio, sizeof (struct uio)); 204 auio.uio_loffset = 0; 205 auio.uio_iov = &iov; 206 auio.uio_iovcnt = 1; 207 auio.uio_resid = msglen; 208 if (flags & MSG_USERSPACE) 209 auio.uio_segflg = UIO_USERSPACE; 210 else 211 auio.uio_segflg = UIO_SYSSPACE; 212 auio.uio_extflg = UIO_COPY_DEFAULT; 213 auio.uio_limit = 0; 214 auio.uio_fmode = KSOCKET_FMODE(ks); 215 216 msghdr.msg_name = NULL; 217 msghdr.msg_namelen = 0; 218 msghdr.msg_control = NULL; 219 msghdr.msg_controllen = 0; 220 msghdr.msg_flags = flags | MSG_EOR; 221 222 error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr); 223 if (error != 0) { 224 if (sent != NULL) 225 *sent = 0; 226 return (error); 227 } 228 229 if (sent != NULL) 230 *sent = msglen - auio.uio_resid; 231 return (0); 232 } 233 234 int 235 ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags, 236 struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr) 237 { 238 int error; 239 struct nmsghdr msghdr; 240 struct uio auio; 241 struct iovec iov; 242 243 /* All Solaris components should pass a cred for this operation. */ 244 ASSERT(cr != NULL); 245 246 if (!KSOCKET_VALID(ks)) { 247 if (sent != NULL) 248 *sent = 0; 249 return (ENOTSOCK); 250 } 251 252 iov.iov_base = msg; 253 iov.iov_len = msglen; 254 255 bzero(&auio, sizeof (struct uio)); 256 auio.uio_loffset = 0; 257 auio.uio_iov = &iov; 258 auio.uio_iovcnt = 1; 259 auio.uio_resid = msglen; 260 if (flags & MSG_USERSPACE) 261 auio.uio_segflg = UIO_USERSPACE; 262 else 263 auio.uio_segflg = UIO_SYSSPACE; 264 auio.uio_extflg = UIO_COPY_DEFAULT; 265 auio.uio_limit = 0; 266 auio.uio_fmode = KSOCKET_FMODE(ks); 267 268 msghdr.msg_iov = &iov; 269 msghdr.msg_iovlen = 1; 270 msghdr.msg_name = (char *)name; 271 msghdr.msg_namelen = namelen; 272 msghdr.msg_control = NULL; 273 msghdr.msg_controllen = 0; 274 msghdr.msg_flags = flags | MSG_EOR; 275 276 error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr); 277 if (error != 0) { 278 if (sent != NULL) 279 *sent = 0; 280 return (error); 281 } 282 if (sent != NULL) 283 *sent = msglen - auio.uio_resid; 284 return (0); 285 } 286 287 int 288 ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags, 289 size_t *sent, struct cred *cr) 290 { 291 int error; 292 ssize_t len; 293 int i; 294 struct uio auio; 295 296 /* All Solaris components should pass a cred for this operation. */ 297 ASSERT(cr != NULL); 298 299 if (!KSOCKET_VALID(ks)) { 300 if (sent != NULL) 301 *sent = 0; 302 return (ENOTSOCK); 303 } 304 305 bzero(&auio, sizeof (struct uio)); 306 auio.uio_loffset = 0; 307 auio.uio_iov = msg->msg_iov; 308 auio.uio_iovcnt = msg->msg_iovlen; 309 if (flags & MSG_USERSPACE) 310 auio.uio_segflg = UIO_USERSPACE; 311 else 312 auio.uio_segflg = UIO_SYSSPACE; 313 auio.uio_extflg = UIO_COPY_DEFAULT; 314 auio.uio_limit = 0; 315 auio.uio_fmode = KSOCKET_FMODE(ks); 316 len = 0; 317 for (i = 0; i < msg->msg_iovlen; i++) { 318 ssize_t iovlen; 319 iovlen = (msg->msg_iov)[i].iov_len; 320 len += iovlen; 321 if (len < 0 || iovlen < 0) 322 return (EINVAL); 323 } 324 auio.uio_resid = len; 325 326 msg->msg_flags = flags | MSG_EOR; 327 328 error = socket_sendmsg(KSTOSO(ks), msg, &auio, cr); 329 if (error != 0) { 330 if (sent != NULL) 331 *sent = 0; 332 return (error); 333 } 334 335 if (sent != NULL) 336 *sent = len - auio.uio_resid; 337 return (0); 338 } 339 340 341 int 342 ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags, 343 size_t *recv, struct cred *cr) 344 { 345 int error; 346 struct nmsghdr msghdr; 347 struct uio auio; 348 struct iovec iov; 349 350 /* All Solaris components should pass a cred for this operation. */ 351 ASSERT(cr != NULL); 352 353 if (!KSOCKET_VALID(ks)) { 354 if (recv != NULL) 355 *recv = 0; 356 return (ENOTSOCK); 357 } 358 359 iov.iov_base = msg; 360 iov.iov_len = msglen; 361 362 bzero(&auio, sizeof (struct uio)); 363 auio.uio_loffset = 0; 364 auio.uio_iov = &iov; 365 auio.uio_iovcnt = 1; 366 auio.uio_resid = msglen; 367 if (flags & MSG_USERSPACE) 368 auio.uio_segflg = UIO_USERSPACE; 369 else 370 auio.uio_segflg = UIO_SYSSPACE; 371 auio.uio_extflg = UIO_COPY_DEFAULT; 372 auio.uio_limit = 0; 373 auio.uio_fmode = KSOCKET_FMODE(ks); 374 375 msghdr.msg_name = NULL; 376 msghdr.msg_namelen = 0; 377 msghdr.msg_control = NULL; 378 msghdr.msg_controllen = 0; 379 msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 380 MSG_DONTWAIT | MSG_USERSPACE); 381 382 error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr); 383 if (error != 0) { 384 if (recv != NULL) 385 *recv = 0; 386 return (error); 387 } 388 389 if (recv != NULL) 390 *recv = msglen - auio.uio_resid; 391 return (0); 392 } 393 394 int 395 ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags, 396 struct sockaddr *name, socklen_t *namelen, size_t *recv, struct cred *cr) 397 { 398 int error; 399 struct nmsghdr msghdr; 400 struct uio auio; 401 struct iovec iov; 402 403 /* All Solaris components should pass a cred for this operation. */ 404 ASSERT(cr != NULL); 405 406 if (!KSOCKET_VALID(ks)) { 407 if (recv != NULL) 408 *recv = 0; 409 return (ENOTSOCK); 410 } 411 412 iov.iov_base = msg; 413 iov.iov_len = msglen; 414 415 bzero(&auio, sizeof (struct uio)); 416 auio.uio_loffset = 0; 417 auio.uio_iov = &iov; 418 auio.uio_iovcnt = 1; 419 auio.uio_resid = msglen; 420 if (flags & MSG_USERSPACE) 421 auio.uio_segflg = UIO_USERSPACE; 422 else 423 auio.uio_segflg = UIO_SYSSPACE; 424 auio.uio_extflg = UIO_COPY_DEFAULT; 425 auio.uio_limit = 0; 426 auio.uio_fmode = KSOCKET_FMODE(ks); 427 428 msghdr.msg_name = (char *)name; 429 msghdr.msg_namelen = *namelen; 430 msghdr.msg_control = NULL; 431 msghdr.msg_controllen = 0; 432 msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 433 MSG_DONTWAIT | MSG_USERSPACE); 434 435 error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr); 436 if (error != 0) { 437 if (recv != NULL) 438 *recv = 0; 439 return (error); 440 } 441 if (recv != NULL) 442 *recv = msglen - auio.uio_resid; 443 444 bcopy(msghdr.msg_name, name, msghdr.msg_namelen); 445 bcopy(&msghdr.msg_namelen, namelen, sizeof (msghdr.msg_namelen)); 446 return (0); 447 } 448 449 int 450 ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recv, 451 struct cred *cr) 452 { 453 int error; 454 ssize_t len; 455 int i; 456 struct uio auio; 457 458 /* All Solaris components should pass a cred for this operation. */ 459 ASSERT(cr != NULL); 460 461 if (!KSOCKET_VALID(ks)) { 462 if (recv != NULL) 463 *recv = 0; 464 return (ENOTSOCK); 465 } 466 467 bzero(&auio, sizeof (struct uio)); 468 auio.uio_loffset = 0; 469 auio.uio_iov = msg->msg_iov; 470 auio.uio_iovcnt = msg->msg_iovlen; 471 if (msg->msg_flags & MSG_USERSPACE) 472 auio.uio_segflg = UIO_USERSPACE; 473 else 474 auio.uio_segflg = UIO_SYSSPACE; 475 auio.uio_extflg = UIO_COPY_DEFAULT; 476 auio.uio_limit = 0; 477 auio.uio_fmode = KSOCKET_FMODE(ks); 478 len = 0; 479 480 for (i = 0; i < msg->msg_iovlen; i++) { 481 ssize_t iovlen; 482 iovlen = (msg->msg_iov)[i].iov_len; 483 len += iovlen; 484 if (len < 0 || iovlen < 0) 485 return (EINVAL); 486 } 487 auio.uio_resid = len; 488 489 msg->msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 490 MSG_DONTWAIT | MSG_USERSPACE); 491 492 error = socket_recvmsg(KSTOSO(ks), msg, &auio, cr); 493 if (error != 0) { 494 if (recv != NULL) 495 *recv = 0; 496 return (error); 497 } 498 if (recv != NULL) 499 *recv = len - auio.uio_resid; 500 return (0); 501 502 } 503 504 int 505 ksocket_shutdown(ksocket_t ks, int how, struct cred *cr) 506 { 507 struct sonode *so; 508 509 /* All Solaris components should pass a cred for this operation. */ 510 ASSERT(cr != NULL); 511 512 if (!KSOCKET_VALID(ks)) 513 return (ENOTSOCK); 514 515 so = KSTOSO(ks); 516 517 return (socket_shutdown(so, how, cr)); 518 } 519 520 int 521 ksocket_close(ksocket_t ks, struct cred *cr) 522 { 523 struct sonode *so; 524 so = KSTOSO(ks); 525 526 /* All Solaris components should pass a cred for this operation. */ 527 ASSERT(cr != NULL); 528 529 mutex_enter(&so->so_lock); 530 531 if (!KSOCKET_VALID(ks)) { 532 mutex_exit(&so->so_lock); 533 return (ENOTSOCK); 534 } 535 536 so->so_state |= SS_CLOSING; 537 538 if (so->so_count > 1) { 539 mutex_enter(&so->so_acceptq_lock); 540 cv_broadcast(&so->so_acceptq_cv); 541 mutex_exit(&so->so_acceptq_lock); 542 cv_broadcast(&so->so_rcv_cv); 543 cv_broadcast(&so->so_state_cv); 544 cv_broadcast(&so->so_single_cv); 545 cv_broadcast(&so->so_read_cv); 546 cv_broadcast(&so->so_snd_cv); 547 cv_broadcast(&so->so_copy_cv); 548 } 549 while (so->so_count > 1) 550 cv_wait(&so->so_closing_cv, &so->so_lock); 551 552 mutex_exit(&so->so_lock); 553 /* Remove callbacks, if any */ 554 (void) ksocket_setcallbacks(ks, NULL, NULL, cr); 555 556 (void) socket_close(so, 0, cr); 557 socket_destroy(so); 558 559 return (0); 560 } 561 562 int 563 ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 564 struct cred *cr) 565 { 566 struct sonode *so; 567 568 /* All Solaris components should pass a cred for this operation. */ 569 ASSERT(cr != NULL); 570 571 if (!KSOCKET_VALID(ks)) 572 return (ENOTSOCK); 573 574 so = KSTOSO(ks); 575 576 if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 577 return (EFAULT); 578 579 return (socket_getsockname(so, addr, addrlen, cr)); 580 } 581 582 int 583 ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 584 struct cred *cr) 585 { 586 struct sonode *so; 587 588 /* All Solaris components should pass a cred for this operation. */ 589 ASSERT(cr != NULL); 590 591 if (!KSOCKET_VALID(ks)) 592 return (ENOTSOCK); 593 594 so = KSTOSO(ks); 595 596 if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 597 return (EFAULT); 598 599 return (socket_getpeername(so, addr, addrlen, B_FALSE, cr)); 600 } 601 602 int 603 ksocket_getsockopt(ksocket_t ks, int level, int optname, void *optval, 604 int *optlen, struct cred *cr) 605 { 606 struct sonode *so; 607 608 /* All Solaris components should pass a cred for this operation. */ 609 ASSERT(cr != NULL); 610 611 if (!KSOCKET_VALID(ks)) 612 return (ENOTSOCK); 613 614 so = KSTOSO(ks); 615 616 if (optlen == NULL) 617 return (EFAULT); 618 if (*optlen > SO_MAXARGSIZE) 619 return (EINVAL); 620 621 return (socket_getsockopt(so, level, optname, optval, 622 (socklen_t *)optlen, 0, cr)); 623 } 624 625 int 626 ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval, 627 int optlen, struct cred *cr) 628 { 629 struct sonode *so; 630 631 /* All Solaris components should pass a cred for this operation. */ 632 ASSERT(cr != NULL); 633 634 if (!KSOCKET_VALID(ks)) 635 return (ENOTSOCK); 636 637 so = KSTOSO(ks); 638 639 if (optval == NULL) 640 optlen = 0; 641 642 return (socket_setsockopt(so, level, optname, optval, 643 (t_uscalar_t)optlen, cr)); 644 } 645 646 /* ARGSUSED */ 647 int 648 ksocket_setcallbacks(ksocket_t ks, ksocket_callbacks_t *cb, void *arg, 649 struct cred *cr) 650 { 651 struct sonode *so; 652 653 /* All Solaris components should pass a cred for this operation. */ 654 ASSERT(cr != NULL); 655 656 if (!KSOCKET_VALID(ks)) 657 return (ENOTSOCK); 658 659 so = KSTOSO(ks); 660 661 if (cb == NULL && arg != NULL) 662 return (EFAULT); 663 if (cb == NULL) { 664 mutex_enter(&so->so_lock); 665 bzero(&(so->so_ksock_callbacks), sizeof (ksocket_callbacks_t)); 666 so->so_ksock_cb_arg = NULL; 667 mutex_exit(&so->so_lock); 668 } else { 669 mutex_enter(&so->so_lock); 670 SETCALLBACK(so, cb, connected, KSOCKET_CB_CONNECTED) 671 SETCALLBACK(so, cb, connectfailed, KSOCKET_CB_CONNECTFAILED) 672 SETCALLBACK(so, cb, disconnected, KSOCKET_CB_DISCONNECTED) 673 SETCALLBACK(so, cb, newdata, KSOCKET_CB_NEWDATA) 674 SETCALLBACK(so, cb, newconn, KSOCKET_CB_NEWCONN) 675 SETCALLBACK(so, cb, cansend, KSOCKET_CB_CANSEND) 676 SETCALLBACK(so, cb, oobdata, KSOCKET_CB_OOBDATA) 677 SETCALLBACK(so, cb, cantsendmore, KSOCKET_CB_CANTSENDMORE) 678 SETCALLBACK(so, cb, cantrecvmore, KSOCKET_CB_CANTRECVMORE) 679 so->so_ksock_cb_arg = arg; 680 mutex_exit(&so->so_lock); 681 } 682 return (0); 683 } 684 685 int 686 ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvalp, struct cred *cr) 687 { 688 struct sonode *so; 689 int rval; 690 691 /* All Solaris components should pass a cred for this operation. */ 692 ASSERT(cr != NULL); 693 694 if (!KSOCKET_VALID(ks)) 695 return (ENOTSOCK); 696 697 so = KSTOSO(ks); 698 699 switch (cmd) { 700 default: 701 /* STREAM iotcls are not supported */ 702 if ((cmd & 0xffffff00U) == STR) { 703 rval = EOPNOTSUPP; 704 } else { 705 rval = socket_ioctl(so, cmd, arg, 706 KSOCKET_FMODE(ks) | FKIOCTL, cr, rvalp); 707 } 708 break; 709 case FIOASYNC: 710 case SIOCSPGRP: 711 case FIOSETOWN: 712 case SIOCGPGRP: 713 case FIOGETOWN: 714 rval = EOPNOTSUPP; 715 break; 716 } 717 718 return (rval); 719 } 720 721 /* 722 * Wait for an input event, similar to t_kspoll(). 723 * Ideas and code borrowed from ../devpoll.c 724 * Basically, setup just enough poll data structures so 725 * we can block on a CV until timeout or pollwakeup(). 726 */ 727 int 728 ksocket_spoll(ksocket_t ks, int timo, short events, short *revents, 729 struct cred *cr) 730 { 731 struct sonode *so; 732 pollhead_t *php, *php2; 733 polldat_t *pdp; 734 pollcache_t *pcp; 735 int error; 736 clock_t expires = 0; 737 clock_t rval; 738 739 /* All Solaris components should pass a cred for this operation. */ 740 ASSERT(cr != NULL); 741 ASSERT(curthread->t_pollcache == NULL); 742 743 if (revents == NULL) 744 return (EINVAL); 745 if (!KSOCKET_VALID(ks)) 746 return (ENOTSOCK); 747 so = KSTOSO(ks); 748 749 /* 750 * Check if there are any events already pending. 751 * If we're not willing to block, (timo == 0) then 752 * pass "anyyet">0 to socket_poll so it can skip 753 * some work. Othewise pass "anyyet"=0 and if 754 * there are no events pending, it will fill in 755 * the pollhead pointer we need for pollwakeup(). 756 * 757 * XXX - pollrelock() logic needs to know which 758 * which pollcache lock to grab. It'd be a 759 * cleaner solution if we could pass pcp as 760 * an arguement in VOP_POLL interface instead 761 * of implicitly passing it using thread_t 762 * struct. On the other hand, changing VOP_POLL 763 * interface will require all driver/file system 764 * poll routine to change. May want to revisit 765 * the tradeoff later. 766 */ 767 php = NULL; 768 *revents = 0; 769 pcp = pcache_alloc(); 770 pcache_create(pcp, 1); 771 772 mutex_enter(&pcp->pc_lock); 773 curthread->t_pollcache = pcp; 774 error = socket_poll(so, (short)events, (timo == 0), 775 revents, &php); 776 curthread->t_pollcache = NULL; 777 mutex_exit(&pcp->pc_lock); 778 779 if (error != 0 || *revents != 0 || timo == 0) 780 goto out; 781 782 /* 783 * Need to block. Did not get *revents, so the 784 * php should be non-NULL, but let's verify. 785 * Also compute when our sleep expires. 786 */ 787 if (php == NULL) { 788 error = EIO; 789 goto out; 790 } 791 if (timo > 0) 792 expires = ddi_get_lbolt() + 793 MSEC_TO_TICK_ROUNDUP(timo); 794 795 /* 796 * Setup: pollhead -> polldat -> pollcache 797 * needed for pollwakeup() 798 * pdp should be freed by pcache_destroy 799 */ 800 pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP); 801 pdp->pd_fd = 0; 802 pdp->pd_events = events; 803 pdp->pd_pcache = pcp; 804 pcache_insert_fd(pcp, pdp, 1); 805 pollhead_insert(php, pdp); 806 pdp->pd_php = php; 807 808 mutex_enter(&pcp->pc_lock); 809 while (!(so->so_state & SS_CLOSING)) { 810 pcp->pc_flag = 0; 811 812 /* Ditto pcp comment above. */ 813 curthread->t_pollcache = pcp; 814 error = socket_poll(so, (short)events, 0, 815 revents, &php2); 816 curthread->t_pollcache = NULL; 817 ASSERT(php2 == php); 818 819 if (error != 0 || *revents != 0) 820 break; 821 822 if (pcp->pc_flag & PC_POLLWAKE) 823 continue; 824 825 if (timo == -1) { 826 rval = cv_wait_sig(&pcp->pc_cv, &pcp->pc_lock); 827 } else { 828 rval = cv_timedwait_sig(&pcp->pc_cv, &pcp->pc_lock, 829 expires); 830 } 831 if (rval <= 0) { 832 if (rval == 0) 833 error = EINTR; 834 break; 835 } 836 } 837 mutex_exit(&pcp->pc_lock); 838 839 if (pdp->pd_php != NULL) { 840 pollhead_delete(pdp->pd_php, pdp); 841 pdp->pd_php = NULL; 842 pdp->pd_fd = 0; 843 } 844 845 /* 846 * pollwakeup() may still interact with this pollcache. Wait until 847 * it is done. 848 */ 849 mutex_enter(&pcp->pc_no_exit); 850 ASSERT(pcp->pc_busy >= 0); 851 while (pcp->pc_busy > 0) 852 cv_wait(&pcp->pc_busy_cv, &pcp->pc_no_exit); 853 mutex_exit(&pcp->pc_no_exit); 854 out: 855 pcache_destroy(pcp); 856 return (error); 857 } 858 859 int 860 ksocket_sendmblk(ksocket_t ks, struct nmsghdr *msg, int flags, 861 mblk_t **mpp, cred_t *cr) 862 { 863 struct sonode *so; 864 int i_val; 865 socklen_t val_len; 866 mblk_t *mp = *mpp; 867 int error; 868 869 /* All Solaris components should pass a cred for this operation. */ 870 ASSERT(cr != NULL); 871 872 if (!KSOCKET_VALID(ks)) 873 return (ENOTSOCK); 874 875 so = KSTOSO(ks); 876 877 if (flags & MSG_MBLK_QUICKRELE) { 878 error = socket_getsockopt(so, SOL_SOCKET, SO_SND_COPYAVOID, 879 &i_val, &val_len, 0, cr); 880 if (error != 0) 881 return (error); 882 883 /* Zero copy is not enable */ 884 if (i_val == 0) 885 return (ECANCELED); 886 887 for (; mp != NULL; mp = mp->b_cont) 888 mp->b_datap->db_struioflag |= STRUIO_ZC; 889 } 890 891 error = socket_sendmblk(so, msg, flags, cr, mpp); 892 893 return (error); 894 } 895 896 897 void 898 ksocket_hold(ksocket_t ks) 899 { 900 struct sonode *so; 901 so = KSTOSO(ks); 902 903 if (!mutex_owned(&so->so_lock)) { 904 mutex_enter(&so->so_lock); 905 so->so_count++; 906 mutex_exit(&so->so_lock); 907 } else 908 so->so_count++; 909 } 910 911 void 912 ksocket_rele(ksocket_t ks) 913 { 914 struct sonode *so; 915 916 so = KSTOSO(ks); 917 /* 918 * When so_count equals 1 means no thread working on this ksocket 919 */ 920 if (so->so_count < 2) 921 cmn_err(CE_PANIC, "ksocket_rele: sonode ref count 0 or 1"); 922 923 if (!mutex_owned(&so->so_lock)) { 924 mutex_enter(&so->so_lock); 925 if (--so->so_count == 1) 926 cv_signal(&so->so_closing_cv); 927 mutex_exit(&so->so_lock); 928 } else { 929 if (--so->so_count == 1) 930 cv_signal(&so->so_closing_cv); 931 } 932 } 933 934 int 935 ksocket_krecv_set(ksocket_t ks, ksocket_krecv_f cb, void *arg) 936 { 937 return (so_krecv_set(KSTOSO(ks), (so_krecv_f)cb, arg)); 938 } 939 940 void 941 ksocket_krecv_unblock(ksocket_t ks) 942 { 943 return (so_krecv_unblock(KSTOSO(ks))); 944 } 945