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]
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>
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>
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,
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
*,
68 static int sosdp_sendmsg(struct sonode
*, struct msghdr
*, struct uio
*,
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
*,
74 static int sosdp_shutdown(struct sonode
*, int, struct cred
*);
75 static int sosdp_getsockopt(struct sonode
*, int, int, void *, socklen_t
*,
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
*,
81 static int sosdp_poll(struct sonode
*, short, int, short *,
83 static int sosdp_close(struct sonode
*, int, struct cred
*);
84 void sosdp_fini(struct sonode
*, struct cred
*);
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
= {
121 sdp_sock_disconnected
,
131 sosdp_init(struct sonode
*so
, struct sonode
*pso
, struct cred
*cr
, int flags
)
134 sdp_sockbuf_limits_t sbl
;
135 sdp_upcalls_t
*upcalls
;
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
);
152 if ((error
= secpolicy_basic_net_access(cr
)) != 0)
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
)
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
;
171 * Accept incoming connection.
175 sosdp_accept(struct sonode
*lso
, int fflag
, struct cred
*cr
,
176 struct sonode
**nsop
)
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
);
192 * Returns right away if socket is nonblocking.
194 error
= so_acceptq_dequeue(lso
, (fflag
& (FNONBLOCK
|FNDELAY
)), &nso
);
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
));
202 dprint(2, ("sosdp_accept: new %p\n", (void *)nso
));
209 * Bind local endpoint.
213 sosdp_bind(struct sonode
*so
, struct sockaddr
*name
, socklen_t namelen
,
214 int flags
, struct cred
*cr
)
218 if (!(flags
& _SOBIND_LOCK_HELD
)) {
219 mutex_enter(&so
->so_lock
);
220 so_lock_single(so
); /* Set SOLOCKED */
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.
232 eprintsoline(so
, error
);
237 * X/Open requires this check
239 if (so
->so_state
& SS_CANTSENDMORE
) {
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
,
252 mutex_enter(&so
->so_lock
);
255 so
->so_state
|= SS_ISBOUND
;
257 eprintsoline(so
, error
);
260 if (!(flags
& _SOBIND_LOCK_HELD
)) {
261 so_unlock_single(so
, SOLOCKED
);
262 mutex_exit(&so
->so_lock
);
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
);
272 * Turn socket into a listen socket.
276 sosdp_listen(struct sonode
*so
, int backlog
, struct cred
*cr
)
280 mutex_enter(&so
->so_lock
);
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
)) {
290 eprintsoline(so
, EINVAL
);
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
;
302 mutex_exit(&so
->so_lock
);
304 error
= sdp_listen((struct sdp_conn_struct_t
*)so
->so_proto_handle
,
307 mutex_enter(&so
->so_lock
);
309 so
->so_state
|= (SS_ACCEPTCONN
| SS_ISBOUND
);
310 so
->so_backlog
= backlog
;
312 eprintsoline(so
, error
);
315 so_unlock_single(so
, SOLOCKED
);
316 mutex_exit(&so
->so_lock
);
326 sosdp_connect(struct sonode
*so
, struct sockaddr
*name
,
327 socklen_t namelen
, int fflag
, int flags
, struct cred
*cr
)
331 mutex_enter(&so
->so_lock
);
335 * Can't connect() after listen(), or if the socket is already
338 if (so
->so_state
& (SS_ACCEPTCONN
|SS_ISCONNECTED
|SS_ISCONNECTING
)) {
339 if (so
->so_state
& SS_ISCONNECTED
) {
341 } else if (so
->so_state
& SS_ISCONNECTING
) {
346 eprintsoline(so
, error
);
351 * check for failure of an earlier call
353 if (so
->so_error
!= 0) {
354 error
= sogeterr(so
, B_TRUE
);
355 eprintsoline(so
, error
);
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
|
367 eprintsoline(so
, error
);
370 if (name
== NULL
|| namelen
== 0) {
371 eprintsoline(so
, EINVAL
);
375 mutex_exit(&so
->so_lock
);
377 error
= sdp_connect((struct sdp_conn_struct_t
*)so
->so_proto_handle
,
380 mutex_enter(&so
->so_lock
);
383 * Allow other threads to access the socket
385 error
= sowaitconnected(so
, fflag
, 0);
387 ("sosdp_connect: wait on so:%p "
388 "so_proto_handle:%p failed:%d",
389 (void *)so
, (void *)so
->so_proto_handle
, error
));
397 /* Non-fatal errors */
398 so
->so_state
|= SS_ISBOUND
;
401 /* clear SS_ISCONNECTING in case it was set */
402 so
->so_state
&= ~SS_ISCONNECTING
;
406 so_unlock_single(so
, SOLOCKED
);
407 mutex_exit(&so
->so_lock
);
416 sosdp_recvmsg(struct sonode
*so
, struct msghdr
*msg
, struct uio
*uiop
,
419 int flags
, error
= 0;
422 flags
= msg
->msg_flags
;
426 if (!(so
->so_state
& (SS_ISCONNECTED
|SS_ISCONNECTING
|
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));
453 mutex_exit(&so
->so_lock
);
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
;
464 (struct sdp_conn_struct_t
*)so
->so_proto_handle
, msg
,
467 msg
->msg_controllen
= 0;
468 msg
->msg_namelen
= 0;
471 mutex_enter(&so
->so_lock
);
473 mutex_exit(&so
->so_lock
);
482 sosdp_sendmsg(struct sonode
*so
, struct msghdr
*msg
, struct uio
*uiop
,
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) {
500 mutex_enter(&so
->so_lock
);
501 if (so
->so_state
& SS_CANTSENDMORE
) {
502 mutex_exit(&so
->so_lock
);
506 if (so
->so_error
!= 0) {
507 error
= sogeterr(so
, B_TRUE
);
508 mutex_exit(&so
->so_lock
);
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>",
520 mutex_exit(&so
->so_lock
);
524 mutex_exit(&so
->so_lock
);
525 error
= sdp_send((struct sdp_conn_struct_t
*)so
->so_proto_handle
,
526 msg
, count
, flags
, uiop
);
532 * Get address of remote node.
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
)) {
543 return (sdp_getpeername(
544 (struct sdp_conn_struct_t
*)so
->so_proto_handle
,
554 sosdp_getsockname(struct sonode
*so
, struct sockaddr
*addr
, socklen_t
*addrlen
,
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
);
573 mutex_exit(&so
->so_lock
);
574 return (sdp_getsockname(
575 (struct sdp_conn_struct_t
*)so
->so_proto_handle
,
581 * Called from shutdown().
585 sosdp_shutdown(struct sonode
*so
, int how
, struct cred
*cr
)
590 mutex_enter(&so
->so_lock
);
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
)) {
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
);
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
)
646 * Get socket options.
650 sosdp_getsockopt(struct sonode
*so
, int level
, int option_name
,
651 void *optval
, socklen_t
*optlenp
, int flags
, struct cred
*cr
)
655 socklen_t maxlen
= *optlenp
, len
, optlen
;
658 void *optbuf
= &buffer
;
661 mutex_enter(&so
->so_lock
);
663 if (level
== SOL_SOCKET
) {
664 switch (option_name
) {
679 case SO_DGRAM_ERRIND
:
680 if (maxlen
< (t_uscalar_t
)sizeof (int32_t)) {
682 eprintsoline(so
, error
);
687 if (maxlen
< (t_uscalar_t
)sizeof (struct linger
)) {
689 eprintsoline(so
, error
);
694 len
= (t_uscalar_t
)sizeof (uint32_t); /* Default */
697 switch (option_name
) {
703 value
= sogeterr(so
, B_TRUE
);
707 value
= (so
->so_state
& SS_ACCEPTCONN
) ?
718 case SO_DGRAM_ERRIND
:
719 value
= (so
->so_options
& option_name
);
723 * The following options are only returned by sockfs
724 * when sdp_get_opt() fails.
728 option
= &so
->so_linger
;
729 len
= (t_uscalar_t
)sizeof (struct linger
);
732 value
= so
->so_sndbuf
;
733 len
= (t_uscalar_t
)sizeof (int);
737 value
= so
->so_rcvbuf
;
738 len
= (t_uscalar_t
)sizeof (int);
742 value
= so
->so_sndlowat
;
743 len
= (t_uscalar_t
)sizeof (int);
747 value
= so
->so_rcvlowat
;
748 len
= (t_uscalar_t
)sizeof (int);
756 if (maxlen
> sizeof (buffer
)) {
757 optbuf
= kmem_alloc(maxlen
, KM_SLEEP
);
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
);
766 if (option
== NULL
) {
767 /* We have no fallback value */
768 eprintsoline(so
, error
);
771 #error "What should the 'len' variable be set to?"
780 len
= MIN(len
, maxlen
);
781 bcopy(option
, optval
, len
);
785 if (optbuf
!= &buffer
) {
786 kmem_free(optbuf
, maxlen
);
789 mutex_exit(&so
->so_lock
);
798 sosdp_setsockopt(struct sonode
*so
, int level
, int option_name
,
799 const void *optval
, t_uscalar_t optlen
, struct cred
*cr
)
804 if (so
->so_state
& SS_CANTSENDMORE
) {
808 mutex_enter(&so
->so_lock
);
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
));
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
) {
847 case SO_DGRAM_ERRIND
:
848 if (optlen
!= (t_uscalar_t
)sizeof (int32_t)) {
850 eprintsoline(so
, error
);
857 if (optlen
!= (t_uscalar_t
)sizeof (struct linger
)) {
859 eprintsoline(so
, error
);
867 #define intvalue (*(int32_t *)optval)
869 switch (option_name
) {
877 struct linger
*l
= (struct linger
*)optval
;
879 so
->so_linger
.l_linger
= l
->l_linger
;
881 so
->so_linger
.l_onoff
= SO_LINGER
;
882 so
->so_options
|= SO_LINGER
;
884 so
->so_linger
.l_onoff
= 0;
885 so
->so_options
&= ~SO_LINGER
;
897 case SO_DGRAM_ERRIND
:
900 ("sosdp_setsockopt: setting 0x%x\n",
902 so
->so_options
|= option_name
;
905 ("sosdp_setsockopt: clearing 0x%x\n",
907 so
->so_options
&= ~option_name
;
912 so
->so_sndbuf
= intvalue
;
913 if (so
->so_sndlowat
> so
->so_sndbuf
) {
914 so
->so_sndlowat
= so
->so_sndbuf
;
918 so
->so_rcvbuf
= intvalue
;
919 if (so
->so_rcvlowat
> so
->so_rcvbuf
) {
920 so
->so_rcvlowat
= so
->so_rcvbuf
;
924 if (so
->so_sndlowat
> so
->so_sndbuf
) {
925 so
->so_sndlowat
= so
->so_sndbuf
;
929 if (so
->so_rcvlowat
> so
->so_rcvbuf
) {
930 so
->so_rcvlowat
= so
->so_rcvbuf
;
937 if ((error
== ENOPROTOOPT
|| error
== EPROTO
||
938 error
== EINVAL
) && handled
) {
940 ("sosdp_setsockopt: ignoring error %d "
941 "for 0x%x\n", error
, option_name
));
948 so_unlock_single(so
, SOLOCKED
);
949 mutex_exit(&so
->so_lock
);
956 sosdp_ioctl(struct sonode
*so
, int cmd
, intptr_t arg
, int mode
,
957 struct cred
*cr
, int32_t *rvalp
)
963 /* handle socket specific ioctls */
966 if (so_copyin((void *)arg
, &value
, sizeof (int32_t),
967 (mode
& (int)FKIOCTL
))) {
970 mutex_enter(&so
->so_lock
);
972 so
->so_state
|= SS_NDELAY
;
974 so
->so_state
&= ~SS_NDELAY
;
976 mutex_exit(&so
->so_lock
);
980 if (so_copyin((void *)arg
, &value
, sizeof (int32_t),
981 (mode
& (int)FKIOCTL
))) {
984 mutex_enter(&so
->so_lock
);
988 so
->so_state
|= SS_ASYNC
;
991 so
->so_state
&= ~SS_ASYNC
;
993 mutex_exit(&so
->so_lock
);
998 if (so_copyin((void *)arg
, &pid
, sizeof (pid_t
),
999 (mode
& (int)FKIOCTL
))) {
1002 mutex_enter(&so
->so_lock
);
1004 error
= (pid
!= so
->so_pgrp
) ? socket_chgpgrp(so
, pid
) : 0;
1005 mutex_exit(&so
->so_lock
);
1010 if (so_copyout(&so
->so_pgrp
, (void *)arg
,
1011 sizeof (pid_t
), (mode
& (int)FKIOCTL
)))
1018 (struct sdp_conn_struct_t
*)so
->so_proto_handle
, cmd
,
1020 if (so_copyout(&intval
, (void *)arg
, sizeof (int),
1021 (mode
& (int)FKIOCTL
)))
1026 case SIOCSENABLESDP
: {
1030 * System wide enable SDP
1033 if (so_copyin((void *)arg
, &enable
, sizeof (int32_t),
1034 mode
& (int)FKIOCTL
))
1038 (struct sdp_conn_struct_t
*)so
->so_proto_handle
, cmd
,
1040 if (so_copyout(&enable
, (void *)arg
,
1041 sizeof (int32_t), (mode
& (int)FKIOCTL
)))
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
) {
1055 mutex_enter(&so
->so_lock
);
1056 intval
= sdp_polldata(
1057 (struct sdp_conn_struct_t
*)so
->so_proto_handle
,
1059 mutex_exit(&so
->so_lock
);
1061 if (so_copyout(&intval
, (void *)arg
, sizeof (intval
),
1062 (mode
& (int)FKIOCTL
)))
1071 * Check socktpi_poll() on why so_lock is not held in this function.
1074 sosdp_poll(struct sonode
*so
, short events
, int anyyet
, short *reventsp
,
1075 struct pollhead
**phpp
)
1077 short origevents
= events
;
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
);
1094 if (so
->so_error
!= 0 &&
1095 ((POLLIN
|POLLRDNORM
|POLLOUT
) & origevents
) != 0) {
1096 *reventsp
= (POLLIN
|POLLRDNORM
|POLLOUT
) & origevents
;
1101 if (so
->so_type
!= SOCK_STREAM
) {
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
,
1110 *reventsp
|= POLLOUT
& events
;
1113 if (sdp_polldata((struct sdp_conn_struct_t
*)so
->so_proto_handle
,
1115 *reventsp
|= (POLLIN
|POLLRDNORM
) & events
;
1118 if ((so_state
& SS_CANTRCVMORE
) || (so
->so_acceptq_len
> 0)) {
1119 *reventsp
|= (POLLIN
|POLLRDNORM
) & events
;
1123 if ((*reventsp
== 0 && !anyyet
) || (events
& POLLET
)) {
1124 *phpp
= &so
->so_poll_list
;
1132 sosdp_close(struct sonode
*so
, int flag
, struct cred
*cr
)
1136 mutex_enter(&so
->so_lock
);
1139 * Need to set flags as there might be ops in progress on
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
,
1154 mutex_enter(&so
->so_lock
);
1155 so_unlock_single(so
, SOLOCKED
);
1156 so_notify_disconnected(so
, B_FALSE
, error
);
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
);
1188 * Incoming connection on listen socket.
1191 sdp_sock_newconn(void *parenthandle
, void *connind
)
1193 struct sonode
*lso
= parenthandle
;
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
) {
1211 nso
= socket_newconn(lso
, connind
, NULL
, SOCKET_NOSLEEP
, &error
);
1213 eprintsoline(lso
, error
);
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
);
1227 * For outgoing connections, the connection has been established.
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
));
1244 so_notify_connected(so
);
1248 * Connection got disconnected. Either with an error, or through
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
);
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.
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
1303 so_notify_writable(so
);
1305 mutex_exit(&so
->so_lock
);
1311 * SDP notifies socket for presence of urgent data.
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.
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
);
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
);