Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / ksocket / ksocket.c
bloba1cafbe76a34d71388d7b6d2b764212317b03082
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
28 #include <sys/file.h>
29 #include <sys/stropts.h>
30 #include <sys/socket.h>
31 #include <sys/socketvar.h>
32 #include <sys/sysmacros.h>
33 #include <sys/filio.h> /* FIO* ioctls */
34 #include <sys/sockio.h> /* SIOC* ioctls */
35 #include <sys/poll_impl.h>
36 #include <sys/cmn_err.h>
37 #include <sys/ksocket.h>
38 #include <io/ksocket/ksocket_impl.h>
39 #include <../../../../kernel/fs/sockfs/sockcommon.h>
41 #define SOCKETMOD_TCP "tcp"
42 #define SOCKETMOD_UDP "udp"
44 * Kernel Sockets
46 * Mostly a wrapper around the private socket_* functions.
48 int
49 ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags,
50 struct cred *cr)
52 int error = 0;
53 struct sonode *so;
54 *ksp = NULL;
56 /* All Solaris components should pass a cred for this operation. */
57 ASSERT(cr != NULL);
59 ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP);
60 so = socket_create(domain, type, protocol, NULL, NULL, flags,
61 cr, &error);
62 if (so == NULL) {
63 if (error == EAFNOSUPPORT) {
64 char *mod = NULL;
67 * Could be that root file system is not loaded or
68 * soconfig has not run yet.
70 if (type == SOCK_STREAM && (domain == AF_INET ||
71 domain == AF_INET6) && (protocol == 0 ||
72 protocol == IPPROTO_TCP)) {
73 mod = SOCKETMOD_TCP;
74 } else if (type == SOCK_DGRAM && (domain == AF_INET ||
75 domain == AF_INET6) && (protocol == 0 ||
76 protocol == IPPROTO_UDP)) {
77 mod = SOCKETMOD_UDP;
78 } else {
79 return (EAFNOSUPPORT);
82 so = socket_create(domain, type, protocol, NULL,
83 mod, flags, cr, &error);
84 if (so == NULL)
85 return (error);
86 } else {
87 return (error);
91 so->so_mode |= SM_KERNEL;
93 *ksp = SOTOKS(so);
95 return (0);
97 int
98 ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
99 struct cred *cr)
101 int error;
103 /* All Solaris components should pass a cred for this operation. */
104 ASSERT(cr != NULL);
106 if (!KSOCKET_VALID(ks))
107 return (ENOTSOCK);
109 error = socket_bind(KSTOSO(ks), addr, addrlen, 0, cr);
111 return (error);
115 ksocket_listen(ksocket_t ks, int backlog, struct cred *cr)
117 /* All Solaris components should pass a cred for this operation. */
118 ASSERT(cr != NULL);
120 if (!KSOCKET_VALID(ks))
121 return (ENOTSOCK);
123 return (socket_listen(KSTOSO(ks), backlog, cr));
127 ksocket_accept(ksocket_t ks, struct sockaddr *addr,
128 socklen_t *addrlenp, ksocket_t *nks, struct cred *cr)
130 int error;
131 struct sonode *nso = NULL;
133 /* All Solaris components should pass a cred for this operation. */
134 ASSERT(cr != NULL);
136 *nks = NULL;
138 if (!KSOCKET_VALID(ks))
139 return (ENOTSOCK);
141 if (addr != NULL && addrlenp == NULL)
142 return (EFAULT);
144 error = socket_accept(KSTOSO(ks), KSOCKET_FMODE(ks), cr, &nso);
145 if (error != 0)
146 return (error);
148 ASSERT(nso != NULL);
150 nso->so_mode |= SM_KERNEL;
152 if (addr != NULL && addrlenp != NULL) {
153 error = socket_getpeername(nso, addr, addrlenp, B_TRUE, cr);
154 if (error != 0) {
155 (void) socket_close(nso, 0, cr);
156 socket_destroy(nso);
157 return ((error == ENOTCONN) ? ECONNABORTED : error);
161 *nks = SOTOKS(nso);
163 return (error);
167 ksocket_connect(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
168 struct cred *cr)
170 /* All Solaris components should pass a cred for this operation. */
171 ASSERT(cr != NULL);
173 if (!KSOCKET_VALID(ks))
174 return (ENOTSOCK);
176 return (socket_connect(KSTOSO(ks), addr, addrlen,
177 KSOCKET_FMODE(ks), 0, cr));
181 ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags,
182 size_t *sent, struct cred *cr)
184 int error;
185 struct msghdr msghdr;
186 struct uio auio;
187 struct iovec iov;
189 /* All Solaris components should pass a cred for this operation. */
190 ASSERT(cr != NULL);
192 if (!KSOCKET_VALID(ks)) {
193 if (sent != NULL)
194 *sent = 0;
195 return (ENOTSOCK);
198 iov.iov_base = msg;
199 iov.iov_len = msglen;
201 bzero(&auio, sizeof (struct uio));
202 auio.uio_loffset = 0;
203 auio.uio_iov = &iov;
204 auio.uio_iovcnt = 1;
205 auio.uio_resid = msglen;
206 if (flags & MSG_USERSPACE)
207 auio.uio_segflg = UIO_USERSPACE;
208 else
209 auio.uio_segflg = UIO_SYSSPACE;
210 auio.uio_extflg = UIO_COPY_DEFAULT;
211 auio.uio_limit = 0;
212 auio.uio_fmode = KSOCKET_FMODE(ks);
214 msghdr.msg_name = NULL;
215 msghdr.msg_namelen = 0;
216 msghdr.msg_control = NULL;
217 msghdr.msg_controllen = 0;
218 msghdr.msg_flags = flags | MSG_EOR;
220 error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr);
221 if (error != 0) {
222 if (sent != NULL)
223 *sent = 0;
224 return (error);
227 if (sent != NULL)
228 *sent = msglen - auio.uio_resid;
229 return (0);
233 ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags,
234 struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr)
236 int error;
237 struct msghdr msghdr;
238 struct uio auio;
239 struct iovec iov;
241 /* All Solaris components should pass a cred for this operation. */
242 ASSERT(cr != NULL);
244 if (!KSOCKET_VALID(ks)) {
245 if (sent != NULL)
246 *sent = 0;
247 return (ENOTSOCK);
250 iov.iov_base = msg;
251 iov.iov_len = msglen;
253 bzero(&auio, sizeof (struct uio));
254 auio.uio_loffset = 0;
255 auio.uio_iov = &iov;
256 auio.uio_iovcnt = 1;
257 auio.uio_resid = msglen;
258 if (flags & MSG_USERSPACE)
259 auio.uio_segflg = UIO_USERSPACE;
260 else
261 auio.uio_segflg = UIO_SYSSPACE;
262 auio.uio_extflg = UIO_COPY_DEFAULT;
263 auio.uio_limit = 0;
264 auio.uio_fmode = KSOCKET_FMODE(ks);
266 msghdr.msg_iov = &iov;
267 msghdr.msg_iovlen = 1;
268 msghdr.msg_name = (char *)name;
269 msghdr.msg_namelen = namelen;
270 msghdr.msg_control = NULL;
271 msghdr.msg_controllen = 0;
272 msghdr.msg_flags = flags | MSG_EOR;
274 error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr);
275 if (error != 0) {
276 if (sent != NULL)
277 *sent = 0;
278 return (error);
280 if (sent != NULL)
281 *sent = msglen - auio.uio_resid;
282 return (0);
286 ksocket_sendmsg(ksocket_t ks, struct msghdr *msg, int flags,
287 size_t *sent, struct cred *cr)
289 int error;
290 ssize_t len;
291 int i;
292 struct uio auio;
294 /* All Solaris components should pass a cred for this operation. */
295 ASSERT(cr != NULL);
297 if (!KSOCKET_VALID(ks)) {
298 if (sent != NULL)
299 *sent = 0;
300 return (ENOTSOCK);
303 bzero(&auio, sizeof (struct uio));
304 auio.uio_loffset = 0;
305 auio.uio_iov = msg->msg_iov;
306 auio.uio_iovcnt = msg->msg_iovlen;
307 if (flags & MSG_USERSPACE)
308 auio.uio_segflg = UIO_USERSPACE;
309 else
310 auio.uio_segflg = UIO_SYSSPACE;
311 auio.uio_extflg = UIO_COPY_DEFAULT;
312 auio.uio_limit = 0;
313 auio.uio_fmode = KSOCKET_FMODE(ks);
314 len = 0;
315 for (i = 0; i < msg->msg_iovlen; i++) {
316 ssize_t iovlen;
317 iovlen = (msg->msg_iov)[i].iov_len;
318 len += iovlen;
319 if (len < 0 || iovlen < 0)
320 return (EINVAL);
322 auio.uio_resid = len;
324 msg->msg_flags = flags | MSG_EOR;
326 error = socket_sendmsg(KSTOSO(ks), msg, &auio, cr);
327 if (error != 0) {
328 if (sent != NULL)
329 *sent = 0;
330 return (error);
333 if (sent != NULL)
334 *sent = len - auio.uio_resid;
335 return (0);
340 ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags,
341 size_t *recv, struct cred *cr)
343 int error;
344 struct msghdr msghdr;
345 struct uio auio;
346 struct iovec iov;
348 /* All Solaris components should pass a cred for this operation. */
349 ASSERT(cr != NULL);
351 if (!KSOCKET_VALID(ks)) {
352 if (recv != NULL)
353 *recv = 0;
354 return (ENOTSOCK);
357 iov.iov_base = msg;
358 iov.iov_len = msglen;
360 bzero(&auio, sizeof (struct uio));
361 auio.uio_loffset = 0;
362 auio.uio_iov = &iov;
363 auio.uio_iovcnt = 1;
364 auio.uio_resid = msglen;
365 if (flags & MSG_USERSPACE)
366 auio.uio_segflg = UIO_USERSPACE;
367 else
368 auio.uio_segflg = UIO_SYSSPACE;
369 auio.uio_extflg = UIO_COPY_DEFAULT;
370 auio.uio_limit = 0;
371 auio.uio_fmode = KSOCKET_FMODE(ks);
373 msghdr.msg_name = NULL;
374 msghdr.msg_namelen = 0;
375 msghdr.msg_control = NULL;
376 msghdr.msg_controllen = 0;
377 msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
378 MSG_DONTWAIT | MSG_USERSPACE);
380 error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr);
381 if (error != 0) {
382 if (recv != NULL)
383 *recv = 0;
384 return (error);
387 if (recv != NULL)
388 *recv = msglen - auio.uio_resid;
389 return (0);
393 ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags,
394 struct sockaddr *name, socklen_t *namelen, size_t *recv, struct cred *cr)
396 int error;
397 struct msghdr msghdr;
398 struct uio auio;
399 struct iovec iov;
401 /* All Solaris components should pass a cred for this operation. */
402 ASSERT(cr != NULL);
404 if (!KSOCKET_VALID(ks)) {
405 if (recv != NULL)
406 *recv = 0;
407 return (ENOTSOCK);
410 iov.iov_base = msg;
411 iov.iov_len = msglen;
413 bzero(&auio, sizeof (struct uio));
414 auio.uio_loffset = 0;
415 auio.uio_iov = &iov;
416 auio.uio_iovcnt = 1;
417 auio.uio_resid = msglen;
418 if (flags & MSG_USERSPACE)
419 auio.uio_segflg = UIO_USERSPACE;
420 else
421 auio.uio_segflg = UIO_SYSSPACE;
422 auio.uio_extflg = UIO_COPY_DEFAULT;
423 auio.uio_limit = 0;
424 auio.uio_fmode = KSOCKET_FMODE(ks);
426 msghdr.msg_name = (char *)name;
427 msghdr.msg_namelen = *namelen;
428 msghdr.msg_control = NULL;
429 msghdr.msg_controllen = 0;
430 msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
431 MSG_DONTWAIT | MSG_USERSPACE);
433 error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr);
434 if (error != 0) {
435 if (recv != NULL)
436 *recv = 0;
437 return (error);
439 if (recv != NULL)
440 *recv = msglen - auio.uio_resid;
442 bcopy(msghdr.msg_name, name, msghdr.msg_namelen);
443 bcopy(&msghdr.msg_namelen, namelen, sizeof (msghdr.msg_namelen));
444 return (0);
448 ksocket_recvmsg(ksocket_t ks, struct msghdr *msg, int flags, size_t *recv,
449 struct cred *cr)
451 int error;
452 ssize_t len;
453 int i;
454 struct uio auio;
456 /* All Solaris components should pass a cred for this operation. */
457 ASSERT(cr != NULL);
459 if (!KSOCKET_VALID(ks)) {
460 if (recv != NULL)
461 *recv = 0;
462 return (ENOTSOCK);
465 bzero(&auio, sizeof (struct uio));
466 auio.uio_loffset = 0;
467 auio.uio_iov = msg->msg_iov;
468 auio.uio_iovcnt = msg->msg_iovlen;
469 if (msg->msg_flags & MSG_USERSPACE)
470 auio.uio_segflg = UIO_USERSPACE;
471 else
472 auio.uio_segflg = UIO_SYSSPACE;
473 auio.uio_extflg = UIO_COPY_DEFAULT;
474 auio.uio_limit = 0;
475 auio.uio_fmode = KSOCKET_FMODE(ks);
476 len = 0;
478 for (i = 0; i < msg->msg_iovlen; i++) {
479 ssize_t iovlen;
480 iovlen = (msg->msg_iov)[i].iov_len;
481 len += iovlen;
482 if (len < 0 || iovlen < 0)
483 return (EINVAL);
485 auio.uio_resid = len;
487 msg->msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
488 MSG_DONTWAIT | MSG_USERSPACE);
490 error = socket_recvmsg(KSTOSO(ks), msg, &auio, cr);
491 if (error != 0) {
492 if (recv != NULL)
493 *recv = 0;
494 return (error);
496 if (recv != NULL)
497 *recv = len - auio.uio_resid;
498 return (0);
503 ksocket_shutdown(ksocket_t ks, int how, struct cred *cr)
505 struct sonode *so;
507 /* All Solaris components should pass a cred for this operation. */
508 ASSERT(cr != NULL);
510 if (!KSOCKET_VALID(ks))
511 return (ENOTSOCK);
513 so = KSTOSO(ks);
515 return (socket_shutdown(so, how, cr));
519 ksocket_close(ksocket_t ks, struct cred *cr)
521 struct sonode *so;
522 so = KSTOSO(ks);
524 /* All Solaris components should pass a cred for this operation. */
525 ASSERT(cr != NULL);
527 mutex_enter(&so->so_lock);
529 if (!KSOCKET_VALID(ks)) {
530 mutex_exit(&so->so_lock);
531 return (ENOTSOCK);
534 so->so_state |= SS_CLOSING;
536 if (so->so_count > 1) {
537 mutex_enter(&so->so_acceptq_lock);
538 cv_broadcast(&so->so_acceptq_cv);
539 mutex_exit(&so->so_acceptq_lock);
540 cv_broadcast(&so->so_rcv_cv);
541 cv_broadcast(&so->so_state_cv);
542 cv_broadcast(&so->so_single_cv);
543 cv_broadcast(&so->so_read_cv);
544 cv_broadcast(&so->so_snd_cv);
545 cv_broadcast(&so->so_copy_cv);
547 while (so->so_count > 1)
548 cv_wait(&so->so_closing_cv, &so->so_lock);
550 mutex_exit(&so->so_lock);
551 /* Remove callbacks, if any */
552 (void) ksocket_setcallbacks(ks, NULL, NULL, cr);
554 (void) socket_close(so, 0, cr);
555 socket_destroy(so);
557 return (0);
561 ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
562 struct cred *cr)
564 struct sonode *so;
566 /* All Solaris components should pass a cred for this operation. */
567 ASSERT(cr != NULL);
569 if (!KSOCKET_VALID(ks))
570 return (ENOTSOCK);
572 so = KSTOSO(ks);
574 if (addrlen == NULL || (addr == NULL && *addrlen != 0))
575 return (EFAULT);
577 return (socket_getsockname(so, addr, addrlen, cr));
581 ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
582 struct cred *cr)
584 struct sonode *so;
586 /* All Solaris components should pass a cred for this operation. */
587 ASSERT(cr != NULL);
589 if (!KSOCKET_VALID(ks))
590 return (ENOTSOCK);
592 so = KSTOSO(ks);
594 if (addrlen == NULL || (addr == NULL && *addrlen != 0))
595 return (EFAULT);
597 return (socket_getpeername(so, addr, addrlen, B_FALSE, cr));
601 ksocket_getsockopt(ksocket_t ks, int level, int optname, void *optval,
602 int *optlen, struct cred *cr)
604 struct sonode *so;
606 /* All Solaris components should pass a cred for this operation. */
607 ASSERT(cr != NULL);
609 if (!KSOCKET_VALID(ks))
610 return (ENOTSOCK);
612 so = KSTOSO(ks);
614 if (optlen == NULL)
615 return (EFAULT);
616 if (*optlen > SO_MAXARGSIZE)
617 return (EINVAL);
619 return (socket_getsockopt(so, level, optname, optval,
620 (socklen_t *)optlen, 0, cr));
624 ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval,
625 int optlen, struct cred *cr)
627 struct sonode *so;
629 /* All Solaris components should pass a cred for this operation. */
630 ASSERT(cr != NULL);
632 if (!KSOCKET_VALID(ks))
633 return (ENOTSOCK);
635 so = KSTOSO(ks);
637 if (optval == NULL)
638 optlen = 0;
640 return (socket_setsockopt(so, level, optname, optval,
641 (t_uscalar_t)optlen, cr));
644 /* ARGSUSED */
646 ksocket_setcallbacks(ksocket_t ks, ksocket_callbacks_t *cb, void *arg,
647 struct cred *cr)
649 struct sonode *so;
651 /* All Solaris components should pass a cred for this operation. */
652 ASSERT(cr != NULL);
654 if (!KSOCKET_VALID(ks))
655 return (ENOTSOCK);
657 so = KSTOSO(ks);
659 if (cb == NULL && arg != NULL)
660 return (EFAULT);
661 if (cb == NULL) {
662 mutex_enter(&so->so_lock);
663 bzero(&(so->so_ksock_callbacks), sizeof (ksocket_callbacks_t));
664 so->so_ksock_cb_arg = NULL;
665 mutex_exit(&so->so_lock);
666 } else {
667 mutex_enter(&so->so_lock);
668 SETCALLBACK(so, cb, connected, KSOCKET_CB_CONNECTED)
669 SETCALLBACK(so, cb, connectfailed, KSOCKET_CB_CONNECTFAILED)
670 SETCALLBACK(so, cb, disconnected, KSOCKET_CB_DISCONNECTED)
671 SETCALLBACK(so, cb, newdata, KSOCKET_CB_NEWDATA)
672 SETCALLBACK(so, cb, newconn, KSOCKET_CB_NEWCONN)
673 SETCALLBACK(so, cb, cansend, KSOCKET_CB_CANSEND)
674 SETCALLBACK(so, cb, oobdata, KSOCKET_CB_OOBDATA)
675 SETCALLBACK(so, cb, cantsendmore, KSOCKET_CB_CANTSENDMORE)
676 SETCALLBACK(so, cb, cantrecvmore, KSOCKET_CB_CANTRECVMORE)
677 so->so_ksock_cb_arg = arg;
678 mutex_exit(&so->so_lock);
680 return (0);
684 ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvalp, struct cred *cr)
686 struct sonode *so;
687 int rval;
689 /* All Solaris components should pass a cred for this operation. */
690 ASSERT(cr != NULL);
692 if (!KSOCKET_VALID(ks))
693 return (ENOTSOCK);
695 so = KSTOSO(ks);
697 switch (cmd) {
698 default:
699 /* STREAM iotcls are not supported */
700 if ((cmd & 0xffffff00U) == STR) {
701 rval = EOPNOTSUPP;
702 } else {
703 rval = socket_ioctl(so, cmd, arg,
704 KSOCKET_FMODE(ks) | FKIOCTL, cr, rvalp);
706 break;
707 case FIOASYNC:
708 case SIOCSPGRP:
709 case FIOSETOWN:
710 case SIOCGPGRP:
711 case FIOGETOWN:
712 rval = EOPNOTSUPP;
713 break;
716 return (rval);
720 * Wait for an input event, similar to t_kspoll().
721 * Ideas and code borrowed from ../devpoll.c
722 * Basically, setup just enough poll data structures so
723 * we can block on a CV until timeout or pollwakeup().
726 ksocket_spoll(ksocket_t ks, int timo, short events, short *revents,
727 struct cred *cr)
729 struct sonode *so;
730 pollhead_t *php, *php2;
731 polldat_t *pdp;
732 pollcache_t *pcp;
733 int error;
734 clock_t expires = 0;
735 clock_t rval;
737 /* All Solaris components should pass a cred for this operation. */
738 ASSERT(cr != NULL);
739 ASSERT(curthread->t_pollcache == NULL);
741 if (revents == NULL)
742 return (EINVAL);
743 if (!KSOCKET_VALID(ks))
744 return (ENOTSOCK);
745 so = KSTOSO(ks);
748 * Check if there are any events already pending.
749 * If we're not willing to block, (timo == 0) then
750 * pass "anyyet">0 to socket_poll so it can skip
751 * some work. Othewise pass "anyyet"=0 and if
752 * there are no events pending, it will fill in
753 * the pollhead pointer we need for pollwakeup().
755 * XXX - pollrelock() logic needs to know which
756 * which pollcache lock to grab. It'd be a
757 * cleaner solution if we could pass pcp as
758 * an arguement in fop_poll interface instead
759 * of implicitly passing it using thread_t
760 * struct. On the other hand, changing fop_poll
761 * interface will require all driver/file system
762 * poll routine to change. May want to revisit
763 * the tradeoff later.
765 php = NULL;
766 *revents = 0;
767 pcp = pcache_alloc();
768 pcache_create(pcp, 1);
770 mutex_enter(&pcp->pc_lock);
771 curthread->t_pollcache = pcp;
772 error = socket_poll(so, (short)events, (timo == 0),
773 revents, &php);
774 curthread->t_pollcache = NULL;
775 mutex_exit(&pcp->pc_lock);
777 if (error != 0 || *revents != 0 || timo == 0)
778 goto out;
781 * Need to block. Did not get *revents, so the
782 * php should be non-NULL, but let's verify.
783 * Also compute when our sleep expires.
785 if (php == NULL) {
786 error = EIO;
787 goto out;
789 if (timo > 0)
790 expires = ddi_get_lbolt() +
791 MSEC_TO_TICK_ROUNDUP(timo);
794 * Setup: pollhead -> polldat -> pollcache
795 * needed for pollwakeup()
796 * pdp should be freed by pcache_destroy
798 pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP);
799 pdp->pd_fd = 0;
800 pdp->pd_events = events;
801 pdp->pd_pcache = pcp;
802 pcache_insert_fd(pcp, pdp, 1);
803 pollhead_insert(php, pdp);
804 pdp->pd_php = php;
806 mutex_enter(&pcp->pc_lock);
807 while (!(so->so_state & SS_CLOSING)) {
808 pcp->pc_flag = 0;
810 /* Ditto pcp comment above. */
811 curthread->t_pollcache = pcp;
812 error = socket_poll(so, (short)events, 0,
813 revents, &php2);
814 curthread->t_pollcache = NULL;
815 ASSERT(php2 == php);
817 if (error != 0 || *revents != 0)
818 break;
820 if (pcp->pc_flag & PC_POLLWAKE)
821 continue;
823 if (timo == -1) {
824 rval = cv_wait_sig(&pcp->pc_cv, &pcp->pc_lock);
825 } else {
826 rval = cv_timedwait_sig(&pcp->pc_cv, &pcp->pc_lock,
827 expires);
829 if (rval <= 0) {
830 if (rval == 0)
831 error = EINTR;
832 break;
835 mutex_exit(&pcp->pc_lock);
837 if (pdp->pd_php != NULL) {
838 pollhead_delete(pdp->pd_php, pdp);
839 pdp->pd_php = NULL;
840 pdp->pd_fd = 0;
844 * pollwakeup() may still interact with this pollcache. Wait until
845 * it is done.
847 mutex_enter(&pcp->pc_no_exit);
848 ASSERT(pcp->pc_busy >= 0);
849 while (pcp->pc_busy > 0)
850 cv_wait(&pcp->pc_busy_cv, &pcp->pc_no_exit);
851 mutex_exit(&pcp->pc_no_exit);
852 out:
853 pcache_destroy(pcp);
854 return (error);
858 ksocket_sendmblk(ksocket_t ks, struct msghdr *msg, int flags,
859 mblk_t **mpp, cred_t *cr)
861 struct sonode *so;
862 int i_val;
863 socklen_t val_len;
864 mblk_t *mp = *mpp;
865 int error;
867 /* All Solaris components should pass a cred for this operation. */
868 ASSERT(cr != NULL);
870 if (!KSOCKET_VALID(ks))
871 return (ENOTSOCK);
873 so = KSTOSO(ks);
875 if (flags & MSG_MBLK_QUICKRELE) {
876 error = socket_getsockopt(so, SOL_SOCKET, SO_SND_COPYAVOID,
877 &i_val, &val_len, 0, cr);
878 if (error != 0)
879 return (error);
881 /* Zero copy is not enable */
882 if (i_val == 0)
883 return (ECANCELED);
885 for (; mp != NULL; mp = mp->b_cont)
886 mp->b_datap->db_struioflag |= STRUIO_ZC;
889 error = socket_sendmblk(so, msg, flags, cr, mpp);
891 return (error);
895 void
896 ksocket_hold(ksocket_t ks)
898 struct sonode *so;
899 so = KSTOSO(ks);
901 if (!mutex_owned(&so->so_lock)) {
902 mutex_enter(&so->so_lock);
903 so->so_count++;
904 mutex_exit(&so->so_lock);
905 } else
906 so->so_count++;
909 void
910 ksocket_rele(ksocket_t ks)
912 struct sonode *so;
914 so = KSTOSO(ks);
916 * When so_count equals 1 means no thread working on this ksocket
918 if (so->so_count < 2)
919 cmn_err(CE_PANIC, "ksocket_rele: sonode ref count 0 or 1");
921 if (!mutex_owned(&so->so_lock)) {
922 mutex_enter(&so->so_lock);
923 if (--so->so_count == 1)
924 cv_signal(&so->so_closing_cv);
925 mutex_exit(&so->so_lock);
926 } else {
927 if (--so->so_count == 1)
928 cv_signal(&so->so_closing_cv);