Merge commit '80d5689f5d4588adc071138e25e9d0d5252d9b55'
[unleashed.git] / kernel / net / sockmods / sdp / socksdp.c
blob64dac6fcf875c532e36238e521e6995d7dad648b
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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Joyent, Inc.
27 #include <sys/types.h>
28 #include <sys/t_lock.h>
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/buf.h>
32 #include <sys/vfs.h>
33 #include <sys/vnode.h>
34 #include <sys/debug.h>
35 #include <sys/errno.h>
36 #include <sys/stropts.h>
37 #include <sys/cmn_err.h>
38 #include <sys/sysmacros.h>
39 #include <sys/policy.h>
41 #include <sys/filio.h>
42 #include <sys/sockio.h>
44 #include <sys/project.h>
45 #include <sys/tihdr.h>
46 #include <sys/strsubr.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
50 #include <sys/strsun.h>
52 #include <inet/sdp_itf.h>
53 #include "socksdp.h"
54 #include <../../../../kernel/fs/sockfs/sockcommon.h>
57 * SDP sockfs sonode operations
59 static int sosdp_init(struct sonode *, struct sonode *, struct cred *, int);
60 static int sosdp_accept(struct sonode *, int, struct cred *, struct sonode **);
61 static int sosdp_bind(struct sonode *, struct sockaddr *, socklen_t, int,
62 struct cred *);
63 static int sosdp_listen(struct sonode *, int, struct cred *);
64 static int sosdp_connect(struct sonode *, struct sockaddr *, socklen_t,
65 int, int, struct cred *);
66 static int sosdp_recvmsg(struct sonode *, struct msghdr *, struct uio *,
67 struct cred *);
68 static int sosdp_sendmsg(struct sonode *, struct msghdr *, struct uio *,
69 struct cred *);
70 static int sosdp_getpeername(struct sonode *, struct sockaddr *, socklen_t *,
71 boolean_t, struct cred *);
72 static int sosdp_getsockname(struct sonode *, struct sockaddr *, socklen_t *,
73 struct cred *);
74 static int sosdp_shutdown(struct sonode *, int, struct cred *);
75 static int sosdp_getsockopt(struct sonode *, int, int, void *, socklen_t *,
76 int, struct cred *);
77 static int sosdp_setsockopt(struct sonode *, int, int, const void *,
78 socklen_t, struct cred *);
79 static int sosdp_ioctl(struct sonode *, int, intptr_t, int, struct cred *,
80 int32_t *);
81 static int sosdp_poll(struct sonode *, short, int, short *,
82 struct pollhead **);
83 static int sosdp_close(struct sonode *, int, struct cred *);
84 void sosdp_fini(struct sonode *, struct cred *);
88 * Socket upcalls
90 static void *sdp_sock_newconn(void *parenthandle, void *connind);
91 static void sdp_sock_connected(void *handle);
92 static void sdp_sock_disconnected(void *handle, int error);
93 static void sdp_sock_connfail(void *handle, int error);
94 static int sdp_sock_recv(void *handle, mblk_t *mp, int flags);
95 static void sdp_sock_xmitted(void *handle, int txqueued);
96 static void sdp_sock_urgdata(void *handle);
97 static void sdp_sock_ordrel(void *handle);
99 sonodeops_t sosdp_sonodeops = {
100 sosdp_init, /* sop_init */
101 sosdp_accept, /* sop_accept */
102 sosdp_bind, /* sop_bind */
103 sosdp_listen, /* sop_listen */
104 sosdp_connect, /* sop_connect */
105 sosdp_recvmsg, /* sop_recvmsg */
106 sosdp_sendmsg, /* sop_sendmsg */
107 so_sendmblk_notsupp, /* sop_sendmblk */
108 sosdp_getpeername, /* sop_getpeername */
109 sosdp_getsockname, /* sop_getsockname */
110 sosdp_shutdown, /* sop_shutdown */
111 sosdp_getsockopt, /* sop_getsockopt */
112 sosdp_setsockopt, /* sop_setsockopt */
113 sosdp_ioctl, /* sop_ioctl */
114 sosdp_poll, /* sop_poll */
115 sosdp_close, /* sop_close */
118 sdp_upcalls_t sosdp_sock_upcalls = {
119 sdp_sock_newconn,
120 sdp_sock_connected,
121 sdp_sock_disconnected,
122 sdp_sock_connfail,
123 sdp_sock_recv,
124 sdp_sock_xmitted,
125 sdp_sock_urgdata,
126 sdp_sock_ordrel,
129 /* ARGSUSED */
130 static int
131 sosdp_init(struct sonode *so, struct sonode *pso, struct cred *cr, int flags)
133 int error = 0;
134 sdp_sockbuf_limits_t sbl;
135 sdp_upcalls_t *upcalls;
137 if (pso != NULL) {
138 /* passive open, just inherit settings from parent */
140 mutex_enter(&so->so_lock);
142 so->so_state |= (SS_ISBOUND | SS_ISCONNECTED |
143 (pso->so_state & SS_ASYNC));
144 sosdp_so_inherit(pso, so);
145 so->so_proto_props = pso->so_proto_props;
147 mutex_exit(&so->so_lock);
149 return (0);
152 if ((error = secpolicy_basic_net_access(cr)) != 0)
153 return (error);
155 upcalls = &sosdp_sock_upcalls;
157 so->so_proto_handle = (sock_lower_handle_t)sdp_create(so, NULL,
158 so->so_family, SDP_CAN_BLOCK, upcalls, &sbl, cr, &error);
159 if (so->so_proto_handle == NULL)
160 return (ENOMEM);
162 so->so_rcvbuf = sbl.sbl_rxbuf;
163 so->so_rcvlowat = sbl.sbl_rxlowat;
164 so->so_sndbuf = sbl.sbl_txbuf;
165 so->so_sndlowat = sbl.sbl_txlowat;
167 return (error);
171 * Accept incoming connection.
173 /* ARGSUSED */
174 static int
175 sosdp_accept(struct sonode *lso, int fflag, struct cred *cr,
176 struct sonode **nsop)
178 int error = 0;
179 struct sonode *nso;
181 dprint(3, ("sosdp_accept: so:%p so_proto_handle:%p", (void *)lso,
182 (void *)lso->so_proto_handle));
184 if (!(lso->so_state & SS_ACCEPTCONN)) {
186 * Not a listen socket.
188 eprintsoline(lso, EINVAL);
189 return (EINVAL);
192 * Returns right away if socket is nonblocking.
194 error = so_acceptq_dequeue(lso, (fflag & (FNONBLOCK|FNDELAY)), &nso);
195 if (error != 0) {
196 eprintsoline(lso, error);
197 dprint(4, ("sosdp_accept: failed %d:lso:%p so_proto_handle:%p",
198 error, (void *)lso, (void *)lso->so_proto_handle));
199 return (error);
202 dprint(2, ("sosdp_accept: new %p\n", (void *)nso));
203 *nsop = nso;
205 return (0);
209 * Bind local endpoint.
211 /* ARGSUSED */
213 sosdp_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
214 int flags, struct cred *cr)
216 int error = 0;
218 if (!(flags & _SOBIND_LOCK_HELD)) {
219 mutex_enter(&so->so_lock);
220 so_lock_single(so); /* Set SOLOCKED */
221 } else {
222 ASSERT(MUTEX_HELD(&so->so_lock));
223 ASSERT(so->so_flag & SOLOCKED);
226 if ((so->so_state & SS_ISBOUND) || name == NULL || namelen == 0) {
228 * Multiple binds not allowed for any SDP socket.
229 * Also binding with null address is not supported.
231 error = EINVAL;
232 eprintsoline(so, error);
233 goto done;
237 * X/Open requires this check
239 if (so->so_state & SS_CANTSENDMORE) {
240 error = EINVAL;
241 goto done;
245 * Protocol module does address family checks
247 mutex_exit(&so->so_lock);
249 error = sdp_bind((struct sdp_conn_struct_t *)so->so_proto_handle,
250 name, namelen);
252 mutex_enter(&so->so_lock);
254 if (error == 0) {
255 so->so_state |= SS_ISBOUND;
256 } else {
257 eprintsoline(so, error);
259 done:
260 if (!(flags & _SOBIND_LOCK_HELD)) {
261 so_unlock_single(so, SOLOCKED);
262 mutex_exit(&so->so_lock);
263 } else {
264 /* If the caller held the lock don't release it here */
265 ASSERT(MUTEX_HELD(&so->so_lock));
266 ASSERT(so->so_flag & SOLOCKED);
268 return (error);
272 * Turn socket into a listen socket.
274 /* ARGSUSED */
275 static int
276 sosdp_listen(struct sonode *so, int backlog, struct cred *cr)
278 int error = 0;
280 mutex_enter(&so->so_lock);
281 so_lock_single(so);
284 * If this socket is trying to do connect, or if it has
285 * been connected, disallow.
287 if (so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED |
288 SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE)) {
289 error = EINVAL;
290 eprintsoline(so, EINVAL);
291 goto done;
294 * If listen() is only called to change backlog, we don't
295 * need to notify protocol module.
297 if (so->so_state & SS_ACCEPTCONN) {
298 so->so_backlog = backlog;
299 goto done;
302 mutex_exit(&so->so_lock);
304 error = sdp_listen((struct sdp_conn_struct_t *)so->so_proto_handle,
305 backlog);
307 mutex_enter(&so->so_lock);
308 if (error == 0) {
309 so->so_state |= (SS_ACCEPTCONN | SS_ISBOUND);
310 so->so_backlog = backlog;
311 } else {
312 eprintsoline(so, error);
314 done:
315 so_unlock_single(so, SOLOCKED);
316 mutex_exit(&so->so_lock);
318 return (error);
322 * Active open.
324 /*ARGSUSED*/
325 static int
326 sosdp_connect(struct sonode *so, struct sockaddr *name,
327 socklen_t namelen, int fflag, int flags, struct cred *cr)
329 int error = 0;
331 mutex_enter(&so->so_lock);
332 so_lock_single(so);
335 * Can't connect() after listen(), or if the socket is already
336 * connected.
338 if (so->so_state & (SS_ACCEPTCONN|SS_ISCONNECTED|SS_ISCONNECTING)) {
339 if (so->so_state & SS_ISCONNECTED) {
340 error = EISCONN;
341 } else if (so->so_state & SS_ISCONNECTING) {
342 error = EALREADY;
343 } else {
344 error = EOPNOTSUPP;
346 eprintsoline(so, error);
347 goto done;
351 * check for failure of an earlier call
353 if (so->so_error != 0) {
354 error = sogeterr(so, B_TRUE);
355 eprintsoline(so, error);
356 goto done;
360 * Connection is closing, or closed, don't allow reconnect.
361 * TCP allows this to proceed, but the socket remains unwriteable.
362 * BSD returns EINVAL.
364 if (so->so_state & (SS_ISDISCONNECTING|SS_CANTRCVMORE|
365 SS_CANTSENDMORE)) {
366 error = EINVAL;
367 eprintsoline(so, error);
368 goto done;
370 if (name == NULL || namelen == 0) {
371 eprintsoline(so, EINVAL);
372 goto done;
374 soisconnecting(so);
375 mutex_exit(&so->so_lock);
377 error = sdp_connect((struct sdp_conn_struct_t *)so->so_proto_handle,
378 name, namelen);
380 mutex_enter(&so->so_lock);
381 if (error == 0) {
383 * Allow other threads to access the socket
385 error = sowaitconnected(so, fflag, 0);
386 dprint(4,
387 ("sosdp_connect: wait on so:%p "
388 "so_proto_handle:%p failed:%d",
389 (void *)so, (void *)so->so_proto_handle, error));
392 switch (error) {
393 case 0:
394 case EINPROGRESS:
395 case EALREADY:
396 case EINTR:
397 /* Non-fatal errors */
398 so->so_state |= SS_ISBOUND;
399 break;
400 default:
401 /* clear SS_ISCONNECTING in case it was set */
402 so->so_state &= ~SS_ISCONNECTING;
403 break;
405 done:
406 so_unlock_single(so, SOLOCKED);
407 mutex_exit(&so->so_lock);
408 return (error);
412 * Receive data.
414 /* ARGSUSED */
416 sosdp_recvmsg(struct sonode *so, struct msghdr *msg, struct uio *uiop,
417 struct cred *cr)
419 int flags, error = 0;
420 int size;
422 flags = msg->msg_flags;
423 msg->msg_flags = 0;
426 if (!(so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|
427 SS_CANTRCVMORE))) {
428 return (ENOTCONN);
432 * flag possibilities:
434 * MSG_PEEK Don't consume data
435 * MSG_WAITALL Wait for full quantity of data (ignored if MSG_PEEK)
436 * MSG_DONTWAIT Non-blocking (same as FNDELAY | FNONBLOCK)
438 * MSG_WAITALL can return less than the full buffer if either
440 * 1. we would block and we are non-blocking
441 * 2. a full message cannot be delivered
445 mutex_enter(&so->so_lock);
448 * Allow just one reader at a time.
450 error = so_lock_read_intr(so,
451 uiop->uio_fmode | ((flags & MSG_DONTWAIT) ? FNONBLOCK : 0));
452 if (error != 0) {
453 mutex_exit(&so->so_lock);
454 return (error);
456 size = uiop->uio_resid;
457 mutex_exit(&so->so_lock);
459 if (!(so->so_state & SS_CANTRCVMORE)) {
460 if (uiop->uio_fmode & (FNDELAY|FNONBLOCK)) {
461 flags |= MSG_DONTWAIT;
463 error = sdp_recv(
464 (struct sdp_conn_struct_t *)so->so_proto_handle, msg,
465 size, flags, uiop);
466 } else {
467 msg->msg_controllen = 0;
468 msg->msg_namelen = 0;
471 mutex_enter(&so->so_lock);
472 so_unlock_read(so);
473 mutex_exit(&so->so_lock);
474 return (error);
478 * Send message.
480 /* ARGSUSED */
481 static int
482 sosdp_sendmsg(struct sonode *so, struct msghdr *msg, struct uio *uiop,
483 struct cred *cr)
485 int flags;
486 ssize_t count;
487 int error;
489 ASSERT(so->so_type == SOCK_STREAM);
491 dprint(4, ("sosdp_sendmsg: so:%p so_proto_handle:%p",
492 (void *)so, (void *)so->so_proto_handle));
494 flags = msg->msg_flags;
496 if (msg->msg_controllen != 0) {
497 return (EOPNOTSUPP);
500 mutex_enter(&so->so_lock);
501 if (so->so_state & SS_CANTSENDMORE) {
502 mutex_exit(&so->so_lock);
503 return (EPIPE);
506 if (so->so_error != 0) {
507 error = sogeterr(so, B_TRUE);
508 mutex_exit(&so->so_lock);
509 return (error);
512 if (uiop->uio_fmode & (FNDELAY|FNONBLOCK))
513 flags |= MSG_DONTWAIT;
515 count = uiop->uio_resid;
517 if (!(so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED))) {
518 dprint(4, ("sosdp_sendmsg: invalid state: <%x>",
519 so->so_state));
520 mutex_exit(&so->so_lock);
521 return (ENOTCONN);
524 mutex_exit(&so->so_lock);
525 error = sdp_send((struct sdp_conn_struct_t *)so->so_proto_handle,
526 msg, count, flags, uiop);
528 return (error);
532 * Get address of remote node.
534 /* ARGSUSED */
535 static int
536 sosdp_getpeername(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
537 boolean_t accept, struct cred *cr)
540 if (!accept && !(so->so_state & SS_ISCONNECTED)) {
541 return (ENOTCONN);
542 } else {
543 return (sdp_getpeername(
544 (struct sdp_conn_struct_t *)so->so_proto_handle,
545 addr, addrlen));
550 * Get local address.
552 /* ARGSUSED */
553 static int
554 sosdp_getsockname(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
555 struct cred *cr)
557 mutex_enter(&so->so_lock);
559 if (!(so->so_state & SS_ISBOUND)) {
561 * Zero address, except for address family
563 if (so->so_family == AF_INET || so->so_family == AF_INET6) {
564 bzero(addr, *addrlen);
565 *addrlen = (so->so_family == AF_INET6) ?
566 sizeof (struct sockaddr_in6) :
567 sizeof (struct sockaddr_in);
568 addr->sa_family = so->so_family;
570 mutex_exit(&so->so_lock);
571 return (0);
572 } else {
573 mutex_exit(&so->so_lock);
574 return (sdp_getsockname(
575 (struct sdp_conn_struct_t *)so->so_proto_handle,
576 addr, addrlen));
581 * Called from shutdown().
583 /* ARGSUSED */
584 static int
585 sosdp_shutdown(struct sonode *so, int how, struct cred *cr)
587 uint_t state_change;
588 int error = 0;
590 mutex_enter(&so->so_lock);
591 so_lock_single(so);
593 * Record the current state and then perform any state changes.
594 * Then use the difference between the old and new states to
595 * determine which needs to be done.
597 state_change = so->so_state;
598 if (!(state_change & SS_ISCONNECTED)) {
599 error = ENOTCONN;
600 goto done;
603 switch (how) {
604 case SHUT_RD:
605 socantrcvmore(so);
606 break;
607 case SHUT_WR:
608 socantsendmore(so);
609 break;
610 case SHUT_RDWR:
611 socantsendmore(so);
612 socantrcvmore(so);
613 break;
614 default:
615 error = EINVAL;
616 goto done;
619 state_change = so->so_state & ~state_change;
621 if (state_change & SS_CANTSENDMORE) {
622 so->so_state |= SS_ISDISCONNECTING;
624 so_notify_shutdown(so);
626 if (state_change & SS_CANTSENDMORE) {
627 error = sdp_shutdown(
628 (struct sdp_conn_struct_t *)so->so_proto_handle, how);
631 mutex_enter(&so->so_lock);
632 done:
633 so_unlock_single(so, SOLOCKED);
634 mutex_exit(&so->so_lock);
637 * HACK: sdp_disconnect() may return EWOULDBLOCK. But this error is
638 * not documented in standard socket API. Catch it here.
640 if (error == EWOULDBLOCK)
641 error = 0;
642 return (error);
646 * Get socket options.
648 /*ARGSUSED*/
649 static int
650 sosdp_getsockopt(struct sonode *so, int level, int option_name,
651 void *optval, socklen_t *optlenp, int flags, struct cred *cr)
653 int error = 0;
654 void *option = NULL;
655 socklen_t maxlen = *optlenp, len, optlen;
656 uint32_t value;
657 uint8_t buffer[4];
658 void *optbuf = &buffer;
661 mutex_enter(&so->so_lock);
663 if (level == SOL_SOCKET) {
664 switch (option_name) {
665 case SO_TYPE:
666 case SO_ERROR:
667 case SO_DEBUG:
668 case SO_ACCEPTCONN:
669 case SO_REUSEADDR:
670 case SO_KEEPALIVE:
671 case SO_DONTROUTE:
672 case SO_BROADCAST:
673 case SO_USELOOPBACK:
674 case SO_OOBINLINE:
675 case SO_SNDBUF:
676 case SO_RCVBUF:
677 case SO_SNDLOWAT:
678 case SO_RCVLOWAT:
679 case SO_DGRAM_ERRIND:
680 if (maxlen < (t_uscalar_t)sizeof (int32_t)) {
681 error = EINVAL;
682 eprintsoline(so, error);
683 goto done;
685 break;
686 case SO_LINGER:
687 if (maxlen < (t_uscalar_t)sizeof (struct linger)) {
688 error = EINVAL;
689 eprintsoline(so, error);
690 goto done;
692 break;
694 len = (t_uscalar_t)sizeof (uint32_t); /* Default */
695 option = &value;
697 switch (option_name) {
698 case SO_TYPE:
699 value = so->so_type;
700 goto copyout;
702 case SO_ERROR:
703 value = sogeterr(so, B_TRUE);
704 goto copyout;
706 case SO_ACCEPTCONN:
707 value = (so->so_state & SS_ACCEPTCONN) ?
708 SO_ACCEPTCONN : 0;
709 goto copyout;
711 case SO_DEBUG:
712 case SO_REUSEADDR:
713 case SO_KEEPALIVE:
714 case SO_DONTROUTE:
715 case SO_BROADCAST:
716 case SO_USELOOPBACK:
717 case SO_OOBINLINE:
718 case SO_DGRAM_ERRIND:
719 value = (so->so_options & option_name);
720 goto copyout;
723 * The following options are only returned by sockfs
724 * when sdp_get_opt() fails.
727 case SO_LINGER:
728 option = &so->so_linger;
729 len = (t_uscalar_t)sizeof (struct linger);
730 break;
731 case SO_SNDBUF:
732 value = so->so_sndbuf;
733 len = (t_uscalar_t)sizeof (int);
734 goto copyout;
736 case SO_RCVBUF:
737 value = so->so_rcvbuf;
738 len = (t_uscalar_t)sizeof (int);
739 goto copyout;
741 case SO_SNDLOWAT:
742 value = so->so_sndlowat;
743 len = (t_uscalar_t)sizeof (int);
744 goto copyout;
746 case SO_RCVLOWAT:
747 value = so->so_rcvlowat;
748 len = (t_uscalar_t)sizeof (int);
749 goto copyout;
751 default:
752 option = NULL;
753 break;
756 if (maxlen > sizeof (buffer)) {
757 optbuf = kmem_alloc(maxlen, KM_SLEEP);
759 optlen = maxlen;
760 mutex_exit(&so->so_lock);
761 error = sdp_get_opt((struct sdp_conn_struct_t *)so->so_proto_handle,
762 level, option_name, optbuf, &optlen);
763 mutex_enter(&so->so_lock);
764 ASSERT(optlen <= maxlen);
765 if (error != 0) {
766 if (option == NULL) {
767 /* We have no fallback value */
768 eprintsoline(so, error);
769 goto free;
771 #error "What should the 'len' variable be set to?"
772 error = 0;
773 goto copyout;
776 option = optbuf;
777 len = optlen;
779 copyout:
780 len = MIN(len, maxlen);
781 bcopy(option, optval, len);
782 *optlenp = len;
784 free:
785 if (optbuf != &buffer) {
786 kmem_free(optbuf, maxlen);
788 done:
789 mutex_exit(&so->so_lock);
790 return (error);
794 * Set socket options
796 /* ARGSUSED */
797 static int
798 sosdp_setsockopt(struct sonode *so, int level, int option_name,
799 const void *optval, t_uscalar_t optlen, struct cred *cr)
801 void *conn = NULL;
802 int error = 0;
804 if (so->so_state & SS_CANTSENDMORE) {
805 return (EINVAL);
808 mutex_enter(&so->so_lock);
809 so_lock_single(so);
811 if (so->so_type == SOCK_STREAM) {
812 conn = (void *)so->so_proto_handle;
815 dprint(2, ("sosdp_setsockopt (%d) - conn %p %d %d \n",
816 so->so_type, conn, level, option_name));
818 if (conn != NULL) {
819 mutex_exit(&so->so_lock);
820 error = sdp_set_opt((struct sdp_conn_struct_t *)conn, level,
821 option_name, optval, optlen);
822 mutex_enter(&so->so_lock);
826 * Check for SOL_SOCKET options and record their values.
827 * If we know about a SOL_SOCKET parameter and the transport
828 * failed it with TBADOPT or TOUTSTATE (i.e. ENOPROTOOPT or
829 * EPROTO) we let the setsockopt succeed.
831 if (level == SOL_SOCKET) {
832 boolean_t handled = B_FALSE;
834 /* Check parameters */
835 switch (option_name) {
836 case SO_DEBUG:
837 case SO_REUSEADDR:
838 case SO_KEEPALIVE:
839 case SO_DONTROUTE:
840 case SO_BROADCAST:
841 case SO_USELOOPBACK:
842 case SO_OOBINLINE:
843 case SO_SNDBUF:
844 case SO_RCVBUF:
845 case SO_SNDLOWAT:
846 case SO_RCVLOWAT:
847 case SO_DGRAM_ERRIND:
848 if (optlen != (t_uscalar_t)sizeof (int32_t)) {
849 error = EINVAL;
850 eprintsoline(so, error);
851 goto done;
853 ASSERT(optval);
854 handled = B_TRUE;
855 break;
856 case SO_LINGER:
857 if (optlen != (t_uscalar_t)sizeof (struct linger)) {
858 error = EINVAL;
859 eprintsoline(so, error);
860 goto done;
862 ASSERT(optval);
863 handled = B_TRUE;
864 break;
867 #define intvalue (*(int32_t *)optval)
869 switch (option_name) {
870 case SO_TYPE:
871 case SO_ERROR:
872 case SO_ACCEPTCONN:
873 /* Can't be set */
874 error = ENOPROTOOPT;
875 goto done;
876 case SO_LINGER: {
877 struct linger *l = (struct linger *)optval;
879 so->so_linger.l_linger = l->l_linger;
880 if (l->l_onoff) {
881 so->so_linger.l_onoff = SO_LINGER;
882 so->so_options |= SO_LINGER;
883 } else {
884 so->so_linger.l_onoff = 0;
885 so->so_options &= ~SO_LINGER;
887 break;
890 case SO_DEBUG:
891 case SO_REUSEADDR:
892 case SO_KEEPALIVE:
893 case SO_DONTROUTE:
894 case SO_BROADCAST:
895 case SO_USELOOPBACK:
896 case SO_OOBINLINE:
897 case SO_DGRAM_ERRIND:
898 if (intvalue != 0) {
899 dprintso(so, 1,
900 ("sosdp_setsockopt: setting 0x%x\n",
901 option_name));
902 so->so_options |= option_name;
903 } else {
904 dprintso(so, 1,
905 ("sosdp_setsockopt: clearing 0x%x\n",
906 option_name));
907 so->so_options &= ~option_name;
909 break;
911 case SO_SNDBUF:
912 so->so_sndbuf = intvalue;
913 if (so->so_sndlowat > so->so_sndbuf) {
914 so->so_sndlowat = so->so_sndbuf;
916 break;
917 case SO_RCVBUF:
918 so->so_rcvbuf = intvalue;
919 if (so->so_rcvlowat > so->so_rcvbuf) {
920 so->so_rcvlowat = so->so_rcvbuf;
922 break;
923 case SO_SNDLOWAT:
924 if (so->so_sndlowat > so->so_sndbuf) {
925 so->so_sndlowat = so->so_sndbuf;
927 break;
928 case SO_RCVLOWAT:
929 if (so->so_rcvlowat > so->so_rcvbuf) {
930 so->so_rcvlowat = so->so_rcvbuf;
932 break;
934 #undef intvalue
936 if (error != 0) {
937 if ((error == ENOPROTOOPT || error == EPROTO ||
938 error == EINVAL) && handled) {
939 dprintso(so, 1,
940 ("sosdp_setsockopt: ignoring error %d "
941 "for 0x%x\n", error, option_name));
942 error = 0;
947 done:
948 so_unlock_single(so, SOLOCKED);
949 mutex_exit(&so->so_lock);
951 return (error);
954 /* ARGSUSED */
955 static int
956 sosdp_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode,
957 struct cred *cr, int32_t *rvalp)
959 int32_t value;
960 int error, intval;
961 pid_t pid;
963 /* handle socket specific ioctls */
964 switch (cmd) {
965 case FIONBIO:
966 if (so_copyin((void *)arg, &value, sizeof (int32_t),
967 (mode & (int)FKIOCTL))) {
968 return (EFAULT);
970 mutex_enter(&so->so_lock);
971 if (value != 0) {
972 so->so_state |= SS_NDELAY;
973 } else {
974 so->so_state &= ~SS_NDELAY;
976 mutex_exit(&so->so_lock);
977 return (0);
979 case FIOASYNC:
980 if (so_copyin((void *)arg, &value, sizeof (int32_t),
981 (mode & (int)FKIOCTL))) {
982 return (EFAULT);
984 mutex_enter(&so->so_lock);
986 if (value) {
987 /* Turn on SIGIO */
988 so->so_state |= SS_ASYNC;
989 } else {
990 /* Turn off SIGIO */
991 so->so_state &= ~SS_ASYNC;
993 mutex_exit(&so->so_lock);
994 return (0);
996 case SIOCSPGRP:
997 case FIOSETOWN:
998 if (so_copyin((void *)arg, &pid, sizeof (pid_t),
999 (mode & (int)FKIOCTL))) {
1000 return (EFAULT);
1002 mutex_enter(&so->so_lock);
1004 error = (pid != so->so_pgrp) ? socket_chgpgrp(so, pid) : 0;
1005 mutex_exit(&so->so_lock);
1006 return (error);
1008 case SIOCGPGRP:
1009 case FIOGETOWN:
1010 if (so_copyout(&so->so_pgrp, (void *)arg,
1011 sizeof (pid_t), (mode & (int)FKIOCTL)))
1012 return (EFAULT);
1013 return (0);
1015 case SIOCATMARK:
1016 intval = 0;
1017 error = sdp_ioctl(
1018 (struct sdp_conn_struct_t *)so->so_proto_handle, cmd,
1019 &intval, cr);
1020 if (so_copyout(&intval, (void *)arg, sizeof (int),
1021 (mode & (int)FKIOCTL)))
1022 return (EFAULT);
1023 return (0);
1026 case SIOCSENABLESDP: {
1027 int32_t enable;
1030 * System wide enable SDP
1033 if (so_copyin((void *)arg, &enable, sizeof (int32_t),
1034 mode & (int)FKIOCTL))
1035 return (EFAULT);
1037 error = sdp_ioctl(
1038 (struct sdp_conn_struct_t *)so->so_proto_handle, cmd,
1039 &enable, cr);
1040 if (so_copyout(&enable, (void *)arg,
1041 sizeof (int32_t), (mode & (int)FKIOCTL)))
1042 return (EFAULT);
1043 return (0);
1045 /* from strioctl */
1046 case FIONREAD:
1048 * Return number of bytes of data in all data messages
1049 * in queue in "arg".
1050 * For stream socket, amount of available data.
1052 if (so->so_state & SS_ACCEPTCONN) {
1053 intval = 0;
1054 } else {
1055 mutex_enter(&so->so_lock);
1056 intval = sdp_polldata(
1057 (struct sdp_conn_struct_t *)so->so_proto_handle,
1058 SDP_READ);
1059 mutex_exit(&so->so_lock);
1061 if (so_copyout(&intval, (void *)arg, sizeof (intval),
1062 (mode & (int)FKIOCTL)))
1063 return (EFAULT);
1064 return (0);
1065 default:
1066 return (EINVAL);
1071 * Check socktpi_poll() on why so_lock is not held in this function.
1073 static int
1074 sosdp_poll(struct sonode *so, short events, int anyyet, short *reventsp,
1075 struct pollhead **phpp)
1077 short origevents = events;
1078 int so_state;
1080 so_state = so->so_state;
1082 ASSERT(!so->so_is_stream);
1084 if (!(so_state & SS_ISCONNECTED) && (so->so_type == SOCK_STREAM)) {
1086 * Not connected yet - turn off write side events
1088 events &= ~(POLLOUT|POLLWRBAND);
1092 * Check for errors
1094 if (so->so_error != 0 &&
1095 ((POLLIN|POLLRDNORM|POLLOUT) & origevents) != 0) {
1096 *reventsp = (POLLIN|POLLRDNORM|POLLOUT) & origevents;
1097 goto done;
1100 *reventsp = 0;
1101 if (so->so_type != SOCK_STREAM) {
1102 goto done;
1106 * Don't mark socket writable until TX queued data is below watermark.
1108 if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
1109 SDP_XMIT)) {
1110 *reventsp |= POLLOUT & events;
1113 if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
1114 SDP_READ)) {
1115 *reventsp |= (POLLIN|POLLRDNORM) & events;
1118 if ((so_state & SS_CANTRCVMORE) || (so->so_acceptq_len > 0)) {
1119 *reventsp |= (POLLIN|POLLRDNORM) & events;
1122 done:
1123 if ((*reventsp == 0 && !anyyet) || (events & POLLET)) {
1124 *phpp = &so->so_poll_list;
1127 return (0);
1130 /* ARGSUSED */
1131 static int
1132 sosdp_close(struct sonode *so, int flag, struct cred *cr)
1134 int error = 0;
1136 mutex_enter(&so->so_lock);
1137 so_lock_single(so);
1139 * Need to set flags as there might be ops in progress on
1140 * this socket.
1142 * If socket already disconnected/disconnecting,
1143 * don't send signal (again).
1145 soisdisconnected(so, 0);
1146 mutex_exit(&so->so_lock);
1149 * Initiate connection shutdown.
1151 error = sdp_disconnect((struct sdp_conn_struct_t *)so->so_proto_handle,
1152 flag);
1154 mutex_enter(&so->so_lock);
1155 so_unlock_single(so, SOLOCKED);
1156 so_notify_disconnected(so, B_FALSE, error);
1158 return (error);
1161 /* ARGSUSED */
1162 void
1163 sosdp_fini(struct sonode *so, struct cred *cr)
1165 dprint(3, ("sosdp_fini: so:%p so_proto_handle:%p", (void *)so,
1166 (void *)so->so_proto_handle));
1168 ASSERT(so->so_ops == &sosdp_sonodeops);
1170 if (so->so_proto_handle != NULL)
1171 sdp_close((struct sdp_conn_struct_t *)so->so_proto_handle);
1172 so->so_proto_handle = NULL;
1174 mutex_enter(&so->so_lock);
1176 so_acceptq_flush(so, B_TRUE);
1178 mutex_exit(&so->so_lock);
1180 sonode_fini(so);
1184 * Upcalls from SDP
1188 * Incoming connection on listen socket.
1190 static void *
1191 sdp_sock_newconn(void *parenthandle, void *connind)
1193 struct sonode *lso = parenthandle;
1194 struct sonode *nso;
1195 int error;
1197 ASSERT(lso->so_state & SS_ACCEPTCONN);
1198 ASSERT(lso->so_proto_handle != NULL); /* closed conn */
1199 ASSERT(lso->so_type == SOCK_STREAM);
1201 dprint(3, ("sosdp_newconn A: so:%p so_proto_handle:%p", (void *)lso,
1202 (void *)lso->so_proto_handle));
1205 * Check current # of queued conns against backlog
1207 if (lso->so_rcv_queued >= lso->so_backlog) {
1208 return (NULL);
1211 nso = socket_newconn(lso, connind, NULL, SOCKET_NOSLEEP, &error);
1212 if (nso == NULL) {
1213 eprintsoline(lso, error);
1214 return (NULL);
1217 dprint(2, ("sdp_stream_newconn: new %p\n", (void *)nso));
1219 (void) so_acceptq_enqueue(lso, nso);
1221 mutex_enter(&lso->so_lock);
1222 so_notify_newconn(lso);
1223 return (nso);
1227 * For outgoing connections, the connection has been established.
1229 static void
1230 sdp_sock_connected(void *handle)
1232 struct sonode *so = handle;
1234 ASSERT(so->so_type == SOCK_STREAM);
1235 dprint(3, ("sosdp_connected C: so:%p so_proto_handle:%p", (void *)so,
1236 (void *)so->so_proto_handle));
1238 mutex_enter(&so->so_lock);
1239 ASSERT(so->so_proto_handle); /* closed conn */
1241 ASSERT(!(so->so_state & SS_ACCEPTCONN));
1242 soisconnected(so);
1244 so_notify_connected(so);
1248 * Connection got disconnected. Either with an error, or through
1249 * normal handshake.
1251 static void
1252 sdp_sock_disconnected(void *handle, int error)
1254 struct sonode *so = handle;
1256 ASSERT(so->so_type == SOCK_STREAM);
1257 dprint(2, ("sosdp_disconnected C: so:%p so_proto_handle:%p error:%d",
1258 (void *)so, (void *)so->so_proto_handle, error));
1260 mutex_enter(&so->so_lock);
1261 ASSERT(so->so_proto_handle != NULL); /* closed conn */
1263 soisdisconnected(so, error);
1264 so_notify_disconnected(so, B_FALSE, error);
1268 * Incoming data.
1270 /*ARGSUSED*/
1271 static int
1272 sdp_sock_recv(void *handle, mblk_t *mp, int flags)
1274 struct sonode *so = handle;
1276 ASSERT(so->so_type == SOCK_STREAM);
1278 mutex_enter(&so->so_lock);
1279 so_notify_data(so, 0);
1281 return (so->so_rcvbuf);
1285 * TX queued data got acknowledged.
1287 static void
1288 sdp_sock_xmitted(void *handle, int writeable)
1290 struct sonode *so = handle;
1292 dprint(4, ("sosdp_sock_xmitted: so:%p so_proto_handle:%p txq:%d",
1293 (void *)so, (void *)so->so_proto_handle, writeable));
1294 mutex_enter(&so->so_lock);
1295 ASSERT(so->so_proto_handle != NULL); /* closed conn */
1299 * Only do pollwakeup if the amount of queued data is less than
1300 * watermark.
1302 if (!writeable) {
1303 so_notify_writable(so);
1304 } else {
1305 mutex_exit(&so->so_lock);
1311 * SDP notifies socket for presence of urgent data.
1313 static void
1314 sdp_sock_urgdata(void *handle)
1316 struct sonode *so = handle;
1318 ASSERT(so->so_type == SOCK_STREAM);
1320 mutex_enter(&so->so_lock);
1322 ASSERT(so->so_proto_handle != NULL); /* closed conn */
1323 so_notify_oobsig(so);
1327 * SDP notifies socket about receiving of conn close request from peer side.
1329 static void
1330 sdp_sock_ordrel(void *handle)
1332 struct sonode *so = handle;
1334 ASSERT(so->so_type == SOCK_STREAM);
1336 dprint(4, ("sdp_sock_ordrel : so:%p, so_proto_handle:%p",
1337 (void *)so, (void *)so->so_proto_handle));
1338 mutex_enter(&so->so_lock);
1339 socantrcvmore(so);
1340 so_notify_eof(so);
1343 static void
1344 sdp_sock_connfail(void *handle, int error)
1346 struct sonode *so = handle;
1348 dprint(3, ("sosdp_conn Failed: so:%p so_proto_handle:%p", (void *)so,
1349 (void *)so->so_proto_handle));
1350 mutex_enter(&so->so_lock);
1351 ASSERT(so->so_proto_handle != NULL); /* closed conn */
1352 so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
1353 so->so_error = (ushort_t)error;
1354 mutex_exit(&so->so_lock);
1355 cv_broadcast(&so->so_state_cv);