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 */ 25 26 #include <sys/file.h> 27 #include <sys/stropts.h> 28 #include <sys/socket.h> 29 #include <sys/socketvar.h> 30 #include <sys/sysmacros.h> 31 #include <sys/filio.h> /* FIO* ioctls */ 32 #include <sys/sockio.h> /* SIOC* ioctls */ 33 #include <sys/cmn_err.h> 34 #include <sys/ksocket.h> 35 #include <io/ksocket/ksocket_impl.h> 36 #include <fs/sockfs/sockcommon.h> 37 38 #define SOCKETMOD_TCP "tcp" 39 #define SOCKETMOD_UDP "udp" 40 /* 41 * Kernel Sockets 42 * 43 * Mostly a wrapper around the private socket_* functions. 44 */ 45 int 46 ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags, 47 struct cred *cr) 48 { 49 static const int version = SOV_DEFAULT; 50 int error = 0; 51 struct sonode *so; 52 *ksp = NULL; 53 54 /* All Solaris components should pass a cred for this operation. */ 55 ASSERT(cr != NULL); 56 57 if (domain == AF_NCA || domain == AF_UNIX) 58 return (EAFNOSUPPORT); 59 60 ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP); 61 so = socket_create(domain, type, protocol, NULL, NULL, version, flags, 62 cr, &error); 63 if (so == NULL) { 64 if (error == EAFNOSUPPORT) { 65 char *mod = NULL; 66 67 /* 68 * Could be that root file sytem is not loaded or 69 * soconfig has not run yet. 70 */ 71 if (type == SOCK_STREAM && (domain == AF_INET || 72 domain == AF_INET6) && (protocol == 0 || 73 protocol == IPPROTO_TCP)) { 74 mod = SOCKETMOD_TCP; 75 } else if (type == SOCK_DGRAM && (domain == AF_INET || 76 domain == AF_INET6) && (protocol == 0 || 77 protocol == IPPROTO_UDP)) { 78 mod = SOCKETMOD_UDP; 79 } else { 80 return (EAFNOSUPPORT); 81 } 82 83 so = socket_create(domain, type, protocol, NULL, 84 mod, version, flags, cr, &error); 85 if (so == NULL) 86 return (error); 87 } else { 88 return (error); 89 } 90 } 91 92 so->so_mode |= SM_KERNEL; 93 94 *ksp = SOTOKS(so); 95 96 return (0); 97 } 98 int 99 ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen, 100 struct cred *cr) 101 { 102 int error; 103 104 /* All Solaris components should pass a cred for this operation. */ 105 ASSERT(cr != NULL); 106 107 if (!KSOCKET_VALID(ks)) 108 return (ENOTSOCK); 109 110 error = socket_bind(KSTOSO(ks), addr, addrlen, _SOBIND_SOCKBSD, cr); 111 112 return (error); 113 } 114 115 int 116 ksocket_listen(ksocket_t ks, int backlog, struct cred *cr) 117 { 118 /* All Solaris components should pass a cred for this operation. */ 119 ASSERT(cr != NULL); 120 121 if (!KSOCKET_VALID(ks)) 122 return (ENOTSOCK); 123 124 return (socket_listen(KSTOSO(ks), backlog, cr)); 125 } 126 127 int 128 ksocket_accept(ksocket_t ks, struct sockaddr *addr, 129 socklen_t *addrlenp, ksocket_t *nks, struct cred *cr) 130 { 131 int error; 132 struct sonode *nso = NULL; 133 134 /* All Solaris components should pass a cred for this operation. */ 135 ASSERT(cr != NULL); 136 137 *nks = NULL; 138 139 if (!KSOCKET_VALID(ks)) 140 return (ENOTSOCK); 141 142 if (addr != NULL && addrlenp == NULL) 143 return (EFAULT); 144 145 error = socket_accept(KSTOSO(ks), KSOCKET_FMODE(ks), cr, &nso); 146 if (error != 0) 147 return (error); 148 149 ASSERT(nso != NULL); 150 151 nso->so_mode |= SM_KERNEL; 152 153 if (addr != NULL && addrlenp != NULL) { 154 error = socket_getpeername(nso, addr, addrlenp, B_TRUE, cr); 155 if (error != 0) { 156 (void) socket_close(nso, 0, cr); 157 socket_destroy(nso); 158 return ((error == ENOTCONN) ? ECONNABORTED : error); 159 } 160 } 161 162 *nks = SOTOKS(nso); 163 164 return (error); 165 } 166 167 int 168 ksocket_connect(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen, 169 struct cred *cr) 170 { 171 /* All Solaris components should pass a cred for this operation. */ 172 ASSERT(cr != NULL); 173 174 if (!KSOCKET_VALID(ks)) 175 return (ENOTSOCK); 176 177 return (socket_connect(KSTOSO(ks), addr, addrlen, 178 KSOCKET_FMODE(ks), 0, cr)); 179 } 180 181 int 182 ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags, 183 size_t *sent, struct cred *cr) 184 { 185 int error; 186 struct nmsghdr msghdr; 187 struct uio auio; 188 struct iovec iov; 189 190 /* All Solaris components should pass a cred for this operation. */ 191 ASSERT(cr != NULL); 192 193 if (!KSOCKET_VALID(ks)) { 194 if (sent != NULL) 195 *sent = 0; 196 return (ENOTSOCK); 197 } 198 199 iov.iov_base = msg; 200 iov.iov_len = msglen; 201 202 bzero(&auio, sizeof (struct uio)); 203 auio.uio_loffset = 0; 204 auio.uio_iov = &iov; 205 auio.uio_iovcnt = 1; 206 auio.uio_resid = msglen; 207 if (flags & MSG_USERSPACE) 208 auio.uio_segflg = UIO_USERSPACE; 209 else 210 auio.uio_segflg = UIO_SYSSPACE; 211 auio.uio_extflg = UIO_COPY_DEFAULT; 212 auio.uio_limit = 0; 213 auio.uio_fmode = KSOCKET_FMODE(ks); 214 215 msghdr.msg_name = NULL; 216 msghdr.msg_namelen = 0; 217 msghdr.msg_control = NULL; 218 msghdr.msg_controllen = 0; 219 msghdr.msg_flags = flags | MSG_EOR; 220 221 error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr); 222 if (error != 0) { 223 if (sent != NULL) 224 *sent = 0; 225 return (error); 226 } 227 228 if (sent != NULL) 229 *sent = msglen - auio.uio_resid; 230 return (0); 231 } 232 233 int 234 ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags, 235 struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr) 236 { 237 int error; 238 struct nmsghdr msghdr; 239 struct uio auio; 240 struct iovec iov; 241 242 /* All Solaris components should pass a cred for this operation. */ 243 ASSERT(cr != NULL); 244 245 if (!KSOCKET_VALID(ks)) { 246 if (sent != NULL) 247 *sent = 0; 248 return (ENOTSOCK); 249 } 250 251 iov.iov_base = msg; 252 iov.iov_len = msglen; 253 254 bzero(&auio, sizeof (struct uio)); 255 auio.uio_loffset = 0; 256 auio.uio_iov = &iov; 257 auio.uio_iovcnt = 1; 258 auio.uio_resid = msglen; 259 if (flags & MSG_USERSPACE) 260 auio.uio_segflg = UIO_USERSPACE; 261 else 262 auio.uio_segflg = UIO_SYSSPACE; 263 auio.uio_extflg = UIO_COPY_DEFAULT; 264 auio.uio_limit = 0; 265 auio.uio_fmode = KSOCKET_FMODE(ks); 266 267 msghdr.msg_iov = &iov; 268 msghdr.msg_iovlen = 1; 269 msghdr.msg_name = (char *)name; 270 msghdr.msg_namelen = namelen; 271 msghdr.msg_control = NULL; 272 msghdr.msg_controllen = 0; 273 msghdr.msg_flags = flags | MSG_EOR; 274 275 error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr); 276 if (error != 0) { 277 if (sent != NULL) 278 *sent = 0; 279 return (error); 280 } 281 if (sent != NULL) 282 *sent = msglen - auio.uio_resid; 283 return (0); 284 } 285 286 int 287 ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags, 288 size_t *sent, struct cred *cr) 289 { 290 int error; 291 ssize_t len; 292 int i; 293 struct uio auio; 294 295 /* All Solaris components should pass a cred for this operation. */ 296 ASSERT(cr != NULL); 297 298 if (!KSOCKET_VALID(ks)) { 299 if (sent != NULL) 300 *sent = 0; 301 return (ENOTSOCK); 302 } 303 304 bzero(&auio, sizeof (struct uio)); 305 auio.uio_loffset = 0; 306 auio.uio_iov = msg->msg_iov; 307 auio.uio_iovcnt = msg->msg_iovlen; 308 if (flags & MSG_USERSPACE) 309 auio.uio_segflg = UIO_USERSPACE; 310 else 311 auio.uio_segflg = UIO_SYSSPACE; 312 auio.uio_extflg = UIO_COPY_DEFAULT; 313 auio.uio_limit = 0; 314 auio.uio_fmode = KSOCKET_FMODE(ks); 315 len = 0; 316 for (i = 0; i < msg->msg_iovlen; i++) { 317 ssize_t iovlen; 318 iovlen = (msg->msg_iov)[i].iov_len; 319 len += iovlen; 320 if (len < 0 || iovlen < 0) 321 return (EINVAL); 322 } 323 auio.uio_resid = len; 324 325 msg->msg_flags = flags | MSG_EOR; 326 327 error = socket_sendmsg(KSTOSO(ks), msg, &auio, cr); 328 if (error != 0) { 329 if (sent != NULL) 330 *sent = 0; 331 return (error); 332 } 333 334 if (sent != NULL) 335 *sent = len - auio.uio_resid; 336 return (0); 337 } 338 339 340 int 341 ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags, 342 size_t *recv, struct cred *cr) 343 { 344 int error; 345 struct nmsghdr msghdr; 346 struct uio auio; 347 struct iovec iov; 348 349 /* All Solaris components should pass a cred for this operation. */ 350 ASSERT(cr != NULL); 351 352 if (!KSOCKET_VALID(ks)) { 353 if (recv != NULL) 354 *recv = 0; 355 return (ENOTSOCK); 356 } 357 358 iov.iov_base = msg; 359 iov.iov_len = msglen; 360 361 bzero(&auio, sizeof (struct uio)); 362 auio.uio_loffset = 0; 363 auio.uio_iov = &iov; 364 auio.uio_iovcnt = 1; 365 auio.uio_resid = msglen; 366 if (flags & MSG_USERSPACE) 367 auio.uio_segflg = UIO_USERSPACE; 368 else 369 auio.uio_segflg = UIO_SYSSPACE; 370 auio.uio_extflg = UIO_COPY_DEFAULT; 371 auio.uio_limit = 0; 372 auio.uio_fmode = KSOCKET_FMODE(ks); 373 374 msghdr.msg_name = NULL; 375 msghdr.msg_namelen = 0; 376 msghdr.msg_control = NULL; 377 msghdr.msg_controllen = 0; 378 msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 379 MSG_DONTWAIT | MSG_USERSPACE); 380 381 error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr); 382 if (error != 0) { 383 if (recv != NULL) 384 *recv = 0; 385 return (error); 386 } 387 388 if (recv != NULL) 389 *recv = msglen - auio.uio_resid; 390 return (0); 391 } 392 393 int 394 ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags, 395 struct sockaddr *name, socklen_t *namelen, size_t *recv, struct cred *cr) 396 { 397 int error; 398 struct nmsghdr msghdr; 399 struct uio auio; 400 struct iovec iov; 401 402 /* All Solaris components should pass a cred for this operation. */ 403 ASSERT(cr != NULL); 404 405 if (!KSOCKET_VALID(ks)) { 406 if (recv != NULL) 407 *recv = 0; 408 return (ENOTSOCK); 409 } 410 411 iov.iov_base = msg; 412 iov.iov_len = msglen; 413 414 bzero(&auio, sizeof (struct uio)); 415 auio.uio_loffset = 0; 416 auio.uio_iov = &iov; 417 auio.uio_iovcnt = 1; 418 auio.uio_resid = msglen; 419 if (flags & MSG_USERSPACE) 420 auio.uio_segflg = UIO_USERSPACE; 421 else 422 auio.uio_segflg = UIO_SYSSPACE; 423 auio.uio_extflg = UIO_COPY_DEFAULT; 424 auio.uio_limit = 0; 425 auio.uio_fmode = KSOCKET_FMODE(ks); 426 427 msghdr.msg_name = (char *)name; 428 msghdr.msg_namelen = *namelen; 429 msghdr.msg_control = NULL; 430 msghdr.msg_controllen = 0; 431 msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 432 MSG_DONTWAIT | MSG_USERSPACE); 433 434 error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr); 435 if (error != 0) { 436 if (recv != NULL) 437 *recv = 0; 438 return (error); 439 } 440 if (recv != NULL) 441 *recv = msglen - auio.uio_resid; 442 443 bcopy(msghdr.msg_name, name, msghdr.msg_namelen); 444 bcopy(&msghdr.msg_namelen, namelen, sizeof (msghdr.msg_namelen)); 445 return (0); 446 } 447 448 int 449 ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recv, 450 struct cred *cr) 451 { 452 int error; 453 ssize_t len; 454 int i; 455 struct uio auio; 456 457 /* All Solaris components should pass a cred for this operation. */ 458 ASSERT(cr != NULL); 459 460 if (!KSOCKET_VALID(ks)) { 461 if (recv != NULL) 462 *recv = 0; 463 return (ENOTSOCK); 464 } 465 466 bzero(&auio, sizeof (struct uio)); 467 auio.uio_loffset = 0; 468 auio.uio_iov = msg->msg_iov; 469 auio.uio_iovcnt = msg->msg_iovlen; 470 if (msg->msg_flags & MSG_USERSPACE) 471 auio.uio_segflg = UIO_USERSPACE; 472 else 473 auio.uio_segflg = UIO_SYSSPACE; 474 auio.uio_extflg = UIO_COPY_DEFAULT; 475 auio.uio_limit = 0; 476 auio.uio_fmode = KSOCKET_FMODE(ks); 477 len = 0; 478 479 for (i = 0; i < msg->msg_iovlen; i++) { 480 ssize_t iovlen; 481 iovlen = (msg->msg_iov)[i].iov_len; 482 len += iovlen; 483 if (len < 0 || iovlen < 0) 484 return (EINVAL); 485 } 486 auio.uio_resid = len; 487 488 msg->msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 489 MSG_DONTWAIT | MSG_USERSPACE); 490 491 error = socket_recvmsg(KSTOSO(ks), msg, &auio, cr); 492 if (error != 0) { 493 if (recv != NULL) 494 *recv = 0; 495 return (error); 496 } 497 if (recv != NULL) 498 *recv = len - auio.uio_resid; 499 return (0); 500 501 } 502 503 int 504 ksocket_shutdown(ksocket_t ks, int how, struct cred *cr) 505 { 506 struct sonode *so; 507 508 /* All Solaris components should pass a cred for this operation. */ 509 ASSERT(cr != NULL); 510 511 if (!KSOCKET_VALID(ks)) 512 return (ENOTSOCK); 513 514 so = KSTOSO(ks); 515 516 return (socket_shutdown(so, how, cr)); 517 } 518 519 int 520 ksocket_close(ksocket_t ks, struct cred *cr) 521 { 522 struct sonode *so; 523 so = KSTOSO(ks); 524 525 /* All Solaris components should pass a cred for this operation. */ 526 ASSERT(cr != NULL); 527 528 mutex_enter(&so->so_lock); 529 530 if (!KSOCKET_VALID(ks)) { 531 mutex_exit(&so->so_lock); 532 return (ENOTSOCK); 533 } 534 535 so->so_state |= SS_CLOSING; 536 537 if (so->so_count > 1) { 538 mutex_enter(&so->so_acceptq_lock); 539 cv_broadcast(&so->so_acceptq_cv); 540 mutex_exit(&so->so_acceptq_lock); 541 cv_broadcast(&so->so_rcv_cv); 542 cv_broadcast(&so->so_state_cv); 543 cv_broadcast(&so->so_single_cv); 544 cv_broadcast(&so->so_read_cv); 545 cv_broadcast(&so->so_snd_cv); 546 cv_broadcast(&so->so_copy_cv); 547 } 548 while (so->so_count > 1) 549 cv_wait(&so->so_closing_cv, &so->so_lock); 550 551 mutex_exit(&so->so_lock); 552 /* Remove callbacks, if any */ 553 (void) ksocket_setcallbacks(ks, NULL, NULL, cr); 554 555 (void) socket_close(so, 0, cr); 556 socket_destroy(so); 557 558 return (0); 559 } 560 561 int 562 ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 563 struct cred *cr) 564 { 565 struct sonode *so; 566 567 /* All Solaris components should pass a cred for this operation. */ 568 ASSERT(cr != NULL); 569 570 if (!KSOCKET_VALID(ks)) 571 return (ENOTSOCK); 572 573 so = KSTOSO(ks); 574 575 if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 576 return (EFAULT); 577 578 return (socket_getsockname(so, addr, addrlen, cr)); 579 } 580 581 int 582 ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 583 struct cred *cr) 584 { 585 struct sonode *so; 586 587 /* All Solaris components should pass a cred for this operation. */ 588 ASSERT(cr != NULL); 589 590 if (!KSOCKET_VALID(ks)) 591 return (ENOTSOCK); 592 593 so = KSTOSO(ks); 594 595 if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 596 return (EFAULT); 597 598 return (socket_getpeername(so, addr, addrlen, B_FALSE, cr)); 599 } 600 601 int 602 ksocket_getsockopt(ksocket_t ks, int level, int optname, void *optval, 603 int *optlen, struct cred *cr) 604 { 605 struct sonode *so; 606 607 /* All Solaris components should pass a cred for this operation. */ 608 ASSERT(cr != NULL); 609 610 if (!KSOCKET_VALID(ks)) 611 return (ENOTSOCK); 612 613 so = KSTOSO(ks); 614 615 if (optlen == NULL) 616 return (EFAULT); 617 if (*optlen > SO_MAXARGSIZE) 618 return (EINVAL); 619 620 return (socket_getsockopt(so, level, optname, optval, 621 (socklen_t *)optlen, 0, cr)); 622 } 623 624 int 625 ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval, 626 int optlen, struct cred *cr) 627 { 628 struct sonode *so; 629 630 /* All Solaris components should pass a cred for this operation. */ 631 ASSERT(cr != NULL); 632 633 if (!KSOCKET_VALID(ks)) 634 return (ENOTSOCK); 635 636 so = KSTOSO(ks); 637 638 if (optval == NULL) 639 optlen = 0; 640 641 return (socket_setsockopt(so, level, optname, optval, 642 (t_uscalar_t)optlen, cr)); 643 } 644 645 /* ARGSUSED */ 646 int 647 ksocket_setcallbacks(ksocket_t ks, ksocket_callbacks_t *cb, void *arg, 648 struct cred *cr) 649 { 650 struct sonode *so; 651 652 /* All Solaris components should pass a cred for this operation. */ 653 ASSERT(cr != NULL); 654 655 if (!KSOCKET_VALID(ks)) 656 return (ENOTSOCK); 657 658 so = KSTOSO(ks); 659 660 if (cb == NULL && arg != NULL) 661 return (EFAULT); 662 if (cb == NULL) { 663 mutex_enter(&so->so_lock); 664 bzero(&(so->so_ksock_callbacks), sizeof (ksocket_callbacks_t)); 665 so->so_ksock_cb_arg = NULL; 666 mutex_exit(&so->so_lock); 667 } else { 668 mutex_enter(&so->so_lock); 669 SETCALLBACK(so, cb, connected, KSOCKET_CB_CONNECTED) 670 SETCALLBACK(so, cb, connectfailed, KSOCKET_CB_CONNECTFAILED) 671 SETCALLBACK(so, cb, disconnected, KSOCKET_CB_DISCONNECTED) 672 SETCALLBACK(so, cb, newdata, KSOCKET_CB_NEWDATA) 673 SETCALLBACK(so, cb, newconn, KSOCKET_CB_NEWCONN) 674 SETCALLBACK(so, cb, cansend, KSOCKET_CB_CANSEND) 675 SETCALLBACK(so, cb, oobdata, KSOCKET_CB_OOBDATA) 676 SETCALLBACK(so, cb, cantsendmore, KSOCKET_CB_CANTSENDMORE) 677 SETCALLBACK(so, cb, cantrecvmore, KSOCKET_CB_CANTRECVMORE) 678 so->so_ksock_cb_arg = arg; 679 mutex_exit(&so->so_lock); 680 } 681 return (0); 682 } 683 684 int 685 ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvalp, struct cred *cr) 686 { 687 struct sonode *so; 688 int rval; 689 690 /* All Solaris components should pass a cred for this operation. */ 691 ASSERT(cr != NULL); 692 693 if (!KSOCKET_VALID(ks)) 694 return (ENOTSOCK); 695 696 so = KSTOSO(ks); 697 698 switch (cmd) { 699 default: 700 /* STREAM iotcls are not supported */ 701 if ((cmd & 0xffffff00U) == STR) { 702 rval = EOPNOTSUPP; 703 } else { 704 rval = socket_ioctl(so, cmd, arg, 705 KSOCKET_FMODE(ks) | FKIOCTL, cr, rvalp); 706 } 707 break; 708 case FIOASYNC: 709 case SIOCSPGRP: 710 case FIOSETOWN: 711 case SIOCGPGRP: 712 case FIOGETOWN: 713 rval = EOPNOTSUPP; 714 break; 715 } 716 717 return (rval); 718 } 719 720 int 721 ksocket_sendmblk(ksocket_t ks, struct nmsghdr *msg, int flags, 722 mblk_t **mpp, cred_t *cr) 723 { 724 struct sonode *so; 725 int i_val; 726 socklen_t val_len; 727 mblk_t *mp = *mpp; 728 int error; 729 730 /* All Solaris components should pass a cred for this operation. */ 731 ASSERT(cr != NULL); 732 733 if (!KSOCKET_VALID(ks)) 734 return (ENOTSOCK); 735 736 so = KSTOSO(ks); 737 738 if (flags & MSG_MBLK_QUICKRELE) { 739 error = socket_getsockopt(so, SOL_SOCKET, SO_SND_COPYAVOID, 740 &i_val, &val_len, 0, cr); 741 if (error != 0) 742 return (error); 743 744 /* Zero copy is not enable */ 745 if (i_val == 0) 746 return (ECANCELED); 747 748 for (; mp != NULL; mp = mp->b_cont) 749 mp->b_datap->db_struioflag |= STRUIO_ZC; 750 } 751 752 error = socket_sendmblk(so, msg, flags, cr, mpp); 753 754 return (error); 755 } 756 757 758 void 759 ksocket_hold(ksocket_t ks) 760 { 761 struct sonode *so; 762 so = KSTOSO(ks); 763 764 if (!mutex_owned(&so->so_lock)) { 765 mutex_enter(&so->so_lock); 766 so->so_count++; 767 mutex_exit(&so->so_lock); 768 } else 769 so->so_count++; 770 } 771 772 void 773 ksocket_rele(ksocket_t ks) 774 { 775 struct sonode *so; 776 777 so = KSTOSO(ks); 778 /* 779 * When so_count equals 1 means no thread working on this ksocket 780 */ 781 if (so->so_count < 2) 782 cmn_err(CE_PANIC, "ksocket_rele: sonode ref count 0 or 1"); 783 784 if (!mutex_owned(&so->so_lock)) { 785 mutex_enter(&so->so_lock); 786 if (--so->so_count == 1) 787 cv_signal(&so->so_closing_cv); 788 mutex_exit(&so->so_lock); 789 } else { 790 if (--so->so_count == 1) 791 cv_signal(&so->so_closing_cv); 792 } 793 } 794