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