174e20cfeSnh /*
274e20cfeSnh * CDDL HEADER START
374e20cfeSnh *
474e20cfeSnh * The contents of this file are subject to the terms of the
574e20cfeSnh * Common Development and Distribution License (the "License").
674e20cfeSnh * You may not use this file except in compliance with the License.
774e20cfeSnh *
874e20cfeSnh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
974e20cfeSnh * or http://www.opensolaris.org/os/licensing.
1074e20cfeSnh * See the License for the specific language governing permissions
1174e20cfeSnh * and limitations under the License.
1274e20cfeSnh *
1374e20cfeSnh * When distributing Covered Code, include this CDDL HEADER in each
1474e20cfeSnh * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1574e20cfeSnh * If applicable, add the following below this CDDL HEADER, with the
1674e20cfeSnh * fields enclosed by brackets "[]" replaced with your own identifying
1774e20cfeSnh * information: Portions Copyright [yyyy] [name of copyright owner]
1874e20cfeSnh *
1974e20cfeSnh * CDDL HEADER END
2074e20cfeSnh */
2174e20cfeSnh
2274e20cfeSnh /*
233e95bd4aSAnders Persson * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24*80d5689fSPatrick Mooney * Copyright 2017 Joyent, Inc.
2574e20cfeSnh */
2674e20cfeSnh
2774e20cfeSnh #include <sys/types.h>
2874e20cfeSnh #include <sys/t_lock.h>
2974e20cfeSnh #include <sys/param.h>
3074e20cfeSnh #include <sys/systm.h>
3174e20cfeSnh #include <sys/buf.h>
3274e20cfeSnh #include <sys/vfs.h>
3374e20cfeSnh #include <sys/vnode.h>
3474e20cfeSnh #include <sys/debug.h>
3574e20cfeSnh #include <sys/errno.h>
3674e20cfeSnh #include <sys/stropts.h>
3774e20cfeSnh #include <sys/cmn_err.h>
3874e20cfeSnh #include <sys/sysmacros.h>
39634e26ecSCasper H.S. Dik #include <sys/policy.h>
4074e20cfeSnh
410f1702c5SYu Xiangning #include <sys/filio.h>
420f1702c5SYu Xiangning #include <sys/sockio.h>
430f1702c5SYu Xiangning
4474e20cfeSnh #include <sys/project.h>
4574e20cfeSnh #include <sys/tihdr.h>
4674e20cfeSnh #include <sys/strsubr.h>
4774e20cfeSnh
4874e20cfeSnh #include <sys/socket.h>
4974e20cfeSnh #include <sys/socketvar.h>
5074e20cfeSnh #include <sys/strsun.h>
5174e20cfeSnh
5274e20cfeSnh #include <sys/tsol/label.h>
5374e20cfeSnh
5474e20cfeSnh #include <inet/sdp_itf.h>
5574e20cfeSnh #include "socksdp.h"
560f1702c5SYu Xiangning #include <fs/sockfs/sockcommon.h>
5774e20cfeSnh
5874e20cfeSnh /*
5974e20cfeSnh * SDP sockfs sonode operations
6074e20cfeSnh */
610f1702c5SYu Xiangning static int sosdp_init(struct sonode *, struct sonode *, struct cred *, int);
620f1702c5SYu Xiangning static int sosdp_accept(struct sonode *, int, struct cred *, struct sonode **);
630f1702c5SYu Xiangning static int sosdp_bind(struct sonode *, struct sockaddr *, socklen_t, int,
640f1702c5SYu Xiangning struct cred *);
650f1702c5SYu Xiangning static int sosdp_listen(struct sonode *, int, struct cred *);
663e95bd4aSAnders Persson static int sosdp_connect(struct sonode *, struct sockaddr *, socklen_t,
670f1702c5SYu Xiangning int, int, struct cred *);
680f1702c5SYu Xiangning static int sosdp_recvmsg(struct sonode *, struct nmsghdr *, struct uio *,
690f1702c5SYu Xiangning struct cred *);
700f1702c5SYu Xiangning static int sosdp_sendmsg(struct sonode *, struct nmsghdr *, struct uio *,
710f1702c5SYu Xiangning struct cred *);
720f1702c5SYu Xiangning static int sosdp_getpeername(struct sonode *, struct sockaddr *, socklen_t *,
730f1702c5SYu Xiangning boolean_t, struct cred *);
740f1702c5SYu Xiangning static int sosdp_getsockname(struct sonode *, struct sockaddr *, socklen_t *,
750f1702c5SYu Xiangning struct cred *);
760f1702c5SYu Xiangning static int sosdp_shutdown(struct sonode *, int, struct cred *);
7774e20cfeSnh static int sosdp_getsockopt(struct sonode *, int, int, void *, socklen_t *,
780f1702c5SYu Xiangning int, struct cred *);
7974e20cfeSnh static int sosdp_setsockopt(struct sonode *, int, int, const void *,
800f1702c5SYu Xiangning socklen_t, struct cred *);
810f1702c5SYu Xiangning static int sosdp_ioctl(struct sonode *, int, intptr_t, int, struct cred *,
820f1702c5SYu Xiangning int32_t *);
830f1702c5SYu Xiangning static int sosdp_poll(struct sonode *, short, int, short *,
840f1702c5SYu Xiangning struct pollhead **);
850f1702c5SYu Xiangning static int sosdp_close(struct sonode *, int, struct cred *);
860f1702c5SYu Xiangning void sosdp_fini(struct sonode *, struct cred *);
8774e20cfeSnh
8874e20cfeSnh
8974e20cfeSnh /*
9074e20cfeSnh * Socket upcalls
9174e20cfeSnh */
9274e20cfeSnh static void *sdp_sock_newconn(void *parenthandle, void *connind);
9374e20cfeSnh static void sdp_sock_connected(void *handle);
9474e20cfeSnh static void sdp_sock_disconnected(void *handle, int error);
9574e20cfeSnh static void sdp_sock_connfail(void *handle, int error);
9674e20cfeSnh static int sdp_sock_recv(void *handle, mblk_t *mp, int flags);
9774e20cfeSnh static void sdp_sock_xmitted(void *handle, int txqueued);
9874e20cfeSnh static void sdp_sock_urgdata(void *handle);
9974e20cfeSnh static void sdp_sock_ordrel(void *handle);
10074e20cfeSnh
10174e20cfeSnh sonodeops_t sosdp_sonodeops = {
1020f1702c5SYu Xiangning sosdp_init, /* sop_init */
1030f1702c5SYu Xiangning sosdp_accept, /* sop_accept */
1040f1702c5SYu Xiangning sosdp_bind, /* sop_bind */
1050f1702c5SYu Xiangning sosdp_listen, /* sop_listen */
1060f1702c5SYu Xiangning sosdp_connect, /* sop_connect */
1070f1702c5SYu Xiangning sosdp_recvmsg, /* sop_recvmsg */
1080f1702c5SYu Xiangning sosdp_sendmsg, /* sop_sendmsg */
1090f1702c5SYu Xiangning so_sendmblk_notsupp, /* sop_sendmblk */
1100f1702c5SYu Xiangning sosdp_getpeername, /* sop_getpeername */
1110f1702c5SYu Xiangning sosdp_getsockname, /* sop_getsockname */
1120f1702c5SYu Xiangning sosdp_shutdown, /* sop_shutdown */
1130f1702c5SYu Xiangning sosdp_getsockopt, /* sop_getsockopt */
1140f1702c5SYu Xiangning sosdp_setsockopt, /* sop_setsockopt */
1150f1702c5SYu Xiangning sosdp_ioctl, /* sop_ioctl */
1160f1702c5SYu Xiangning sosdp_poll, /* sop_poll */
1170f1702c5SYu Xiangning sosdp_close, /* sop_close */
11874e20cfeSnh };
11974e20cfeSnh
12074e20cfeSnh sdp_upcalls_t sosdp_sock_upcalls = {
12174e20cfeSnh sdp_sock_newconn,
12274e20cfeSnh sdp_sock_connected,
12374e20cfeSnh sdp_sock_disconnected,
12474e20cfeSnh sdp_sock_connfail,
12574e20cfeSnh sdp_sock_recv,
12674e20cfeSnh sdp_sock_xmitted,
12774e20cfeSnh sdp_sock_urgdata,
12874e20cfeSnh sdp_sock_ordrel,
12974e20cfeSnh };
13074e20cfeSnh
1310f1702c5SYu Xiangning /* ARGSUSED */
13274e20cfeSnh static int
sosdp_init(struct sonode * so,struct sonode * pso,struct cred * cr,int flags)1330f1702c5SYu Xiangning sosdp_init(struct sonode *so, struct sonode *pso, struct cred *cr, int flags)
13474e20cfeSnh {
1350f1702c5SYu Xiangning int error = 0;
1360f1702c5SYu Xiangning sdp_sockbuf_limits_t sbl;
1370f1702c5SYu Xiangning sdp_upcalls_t *upcalls;
13874e20cfeSnh
1390f1702c5SYu Xiangning if (pso != NULL) {
1400f1702c5SYu Xiangning /* passive open, just inherit settings from parent */
14174e20cfeSnh
1420f1702c5SYu Xiangning mutex_enter(&so->so_lock);
14374e20cfeSnh
1440f1702c5SYu Xiangning so->so_state |= (SS_ISBOUND | SS_ISCONNECTED |
1450f1702c5SYu Xiangning (pso->so_state & SS_ASYNC));
1460f1702c5SYu Xiangning sosdp_so_inherit(pso, so);
1470f1702c5SYu Xiangning so->so_proto_props = pso->so_proto_props;
14874e20cfeSnh
1490f1702c5SYu Xiangning mutex_exit(&so->so_lock);
15074e20cfeSnh
1510f1702c5SYu Xiangning return (0);
15274e20cfeSnh }
15374e20cfeSnh
154634e26ecSCasper H.S. Dik if ((error = secpolicy_basic_net_access(cr)) != 0)
155634e26ecSCasper H.S. Dik return (error);
156634e26ecSCasper H.S. Dik
1570f1702c5SYu Xiangning upcalls = &sosdp_sock_upcalls;
15874e20cfeSnh
1590f1702c5SYu Xiangning so->so_proto_handle = (sock_lower_handle_t)sdp_create(so, NULL,
1600f1702c5SYu Xiangning so->so_family, SDP_CAN_BLOCK, upcalls, &sbl, cr, &error);
1610f1702c5SYu Xiangning if (so->so_proto_handle == NULL)
1620f1702c5SYu Xiangning return (ENOMEM);
16374e20cfeSnh
1640f1702c5SYu Xiangning so->so_rcvbuf = sbl.sbl_rxbuf;
1650f1702c5SYu Xiangning so->so_rcvlowat = sbl.sbl_rxlowat;
1660f1702c5SYu Xiangning so->so_sndbuf = sbl.sbl_txbuf;
1670f1702c5SYu Xiangning so->so_sndlowat = sbl.sbl_txlowat;
16874e20cfeSnh
1690f1702c5SYu Xiangning return (error);
17074e20cfeSnh }
17174e20cfeSnh
17274e20cfeSnh /*
17374e20cfeSnh * Accept incoming connection.
17474e20cfeSnh */
1750f1702c5SYu Xiangning /* ARGSUSED */
17674e20cfeSnh static int
sosdp_accept(struct sonode * lso,int fflag,struct cred * cr,struct sonode ** nsop)1770f1702c5SYu Xiangning sosdp_accept(struct sonode *lso, int fflag, struct cred *cr,
1780f1702c5SYu Xiangning struct sonode **nsop)
17974e20cfeSnh {
18074e20cfeSnh int error = 0;
18174e20cfeSnh struct sonode *nso;
18274e20cfeSnh
1830f1702c5SYu Xiangning dprint(3, ("sosdp_accept: so:%p so_proto_handle:%p", (void *)lso,
1840f1702c5SYu Xiangning (void *)lso->so_proto_handle));
18574e20cfeSnh
18674e20cfeSnh if (!(lso->so_state & SS_ACCEPTCONN)) {
18774e20cfeSnh /*
18874e20cfeSnh * Not a listen socket.
18974e20cfeSnh */
19074e20cfeSnh eprintsoline(lso, EINVAL);
19174e20cfeSnh return (EINVAL);
19274e20cfeSnh }
19374e20cfeSnh /*
19474e20cfeSnh * Returns right away if socket is nonblocking.
19574e20cfeSnh */
1960f1702c5SYu Xiangning error = so_acceptq_dequeue(lso, (fflag & (FNONBLOCK|FNDELAY)), &nso);
19774e20cfeSnh if (error != 0) {
19874e20cfeSnh eprintsoline(lso, error);
1990f1702c5SYu Xiangning dprint(4, ("sosdp_accept: failed %d:lso:%p so_proto_handle:%p",
2000f1702c5SYu Xiangning error, (void *)lso, (void *)lso->so_proto_handle));
20174e20cfeSnh return (error);
20274e20cfeSnh }
20374e20cfeSnh
2048793b36bSNick Todd dprint(2, ("sosdp_accept: new %p\n", (void *)nso));
20574e20cfeSnh *nsop = nso;
2060f1702c5SYu Xiangning
20774e20cfeSnh return (0);
20874e20cfeSnh }
20974e20cfeSnh
21074e20cfeSnh /*
21174e20cfeSnh * Bind local endpoint.
21274e20cfeSnh */
2130f1702c5SYu Xiangning /* ARGSUSED */
21474e20cfeSnh int
sosdp_bind(struct sonode * so,struct sockaddr * name,socklen_t namelen,int flags,struct cred * cr)21574e20cfeSnh sosdp_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
2160f1702c5SYu Xiangning int flags, struct cred *cr)
21774e20cfeSnh {
2180f1702c5SYu Xiangning int error = 0;
21974e20cfeSnh
22074e20cfeSnh if (!(flags & _SOBIND_LOCK_HELD)) {
22174e20cfeSnh mutex_enter(&so->so_lock);
22274e20cfeSnh so_lock_single(so); /* Set SOLOCKED */
22374e20cfeSnh } else {
22474e20cfeSnh ASSERT(MUTEX_HELD(&so->so_lock));
22574e20cfeSnh ASSERT(so->so_flag & SOLOCKED);
22674e20cfeSnh }
22774e20cfeSnh
22874e20cfeSnh if ((so->so_state & SS_ISBOUND) || name == NULL || namelen == 0) {
22974e20cfeSnh /*
23074e20cfeSnh * Multiple binds not allowed for any SDP socket.
23174e20cfeSnh * Also binding with null address is not supported.
23274e20cfeSnh */
23374e20cfeSnh error = EINVAL;
23474e20cfeSnh eprintsoline(so, error);
23574e20cfeSnh goto done;
23674e20cfeSnh }
2370f1702c5SYu Xiangning
23874e20cfeSnh /*
23974e20cfeSnh * X/Open requires this check
24074e20cfeSnh */
24174e20cfeSnh if (so->so_state & SS_CANTSENDMORE) {
24274e20cfeSnh error = EINVAL;
24374e20cfeSnh goto done;
24474e20cfeSnh }
24574e20cfeSnh
24674e20cfeSnh /*
2470f1702c5SYu Xiangning * Protocol module does address family checks
24874e20cfeSnh */
24974e20cfeSnh mutex_exit(&so->so_lock);
25074e20cfeSnh
2510f1702c5SYu Xiangning error = sdp_bind((struct sdp_conn_struct_t *)so->so_proto_handle,
2520f1702c5SYu Xiangning name, namelen);
25374e20cfeSnh
25474e20cfeSnh mutex_enter(&so->so_lock);
2550f1702c5SYu Xiangning
25674e20cfeSnh if (error == 0) {
25774e20cfeSnh so->so_state |= SS_ISBOUND;
25874e20cfeSnh } else {
25974e20cfeSnh eprintsoline(so, error);
26074e20cfeSnh }
26174e20cfeSnh done:
26274e20cfeSnh if (!(flags & _SOBIND_LOCK_HELD)) {
26374e20cfeSnh so_unlock_single(so, SOLOCKED);
26474e20cfeSnh mutex_exit(&so->so_lock);
26574e20cfeSnh } else {
26674e20cfeSnh /* If the caller held the lock don't release it here */
26774e20cfeSnh ASSERT(MUTEX_HELD(&so->so_lock));
26874e20cfeSnh ASSERT(so->so_flag & SOLOCKED);
26974e20cfeSnh }
27074e20cfeSnh return (error);
27174e20cfeSnh }
27274e20cfeSnh
27374e20cfeSnh /*
27474e20cfeSnh * Turn socket into a listen socket.
27574e20cfeSnh */
2760f1702c5SYu Xiangning /* ARGSUSED */
27774e20cfeSnh static int
sosdp_listen(struct sonode * so,int backlog,struct cred * cr)2780f1702c5SYu Xiangning sosdp_listen(struct sonode *so, int backlog, struct cred *cr)
27974e20cfeSnh {
28074e20cfeSnh int error = 0;
28174e20cfeSnh
28274e20cfeSnh mutex_enter(&so->so_lock);
28374e20cfeSnh so_lock_single(so);
28474e20cfeSnh
28574e20cfeSnh /*
28674e20cfeSnh * If this socket is trying to do connect, or if it has
28774e20cfeSnh * been connected, disallow.
28874e20cfeSnh */
28974e20cfeSnh if (so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED |
29074e20cfeSnh SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE)) {
29174e20cfeSnh error = EINVAL;
2920f1702c5SYu Xiangning eprintsoline(so, EINVAL);
29374e20cfeSnh goto done;
29474e20cfeSnh }
29574e20cfeSnh /*
29674e20cfeSnh * If listen() is only called to change backlog, we don't
29774e20cfeSnh * need to notify protocol module.
29874e20cfeSnh */
29974e20cfeSnh if (so->so_state & SS_ACCEPTCONN) {
30074e20cfeSnh so->so_backlog = backlog;
30174e20cfeSnh goto done;
30274e20cfeSnh }
30374e20cfeSnh
30474e20cfeSnh mutex_exit(&so->so_lock);
30574e20cfeSnh
3060f1702c5SYu Xiangning error = sdp_listen((struct sdp_conn_struct_t *)so->so_proto_handle,
3070f1702c5SYu Xiangning backlog);
30874e20cfeSnh
30974e20cfeSnh mutex_enter(&so->so_lock);
31074e20cfeSnh if (error == 0) {
3110f1702c5SYu Xiangning so->so_state |= (SS_ACCEPTCONN | SS_ISBOUND);
31274e20cfeSnh so->so_backlog = backlog;
31374e20cfeSnh } else {
31474e20cfeSnh eprintsoline(so, error);
31574e20cfeSnh }
31674e20cfeSnh done:
31774e20cfeSnh so_unlock_single(so, SOLOCKED);
31874e20cfeSnh mutex_exit(&so->so_lock);
31974e20cfeSnh
32074e20cfeSnh return (error);
32174e20cfeSnh }
32274e20cfeSnh
32374e20cfeSnh /*
32474e20cfeSnh * Active open.
32574e20cfeSnh */
32674e20cfeSnh /*ARGSUSED*/
32774e20cfeSnh static int
sosdp_connect(struct sonode * so,struct sockaddr * name,socklen_t namelen,int fflag,int flags,struct cred * cr)3283e95bd4aSAnders Persson sosdp_connect(struct sonode *so, struct sockaddr *name,
3290f1702c5SYu Xiangning socklen_t namelen, int fflag, int flags, struct cred *cr)
33074e20cfeSnh {
3310f1702c5SYu Xiangning int error = 0;
33274e20cfeSnh
33374e20cfeSnh mutex_enter(&so->so_lock);
33474e20cfeSnh so_lock_single(so);
33574e20cfeSnh
33674e20cfeSnh /*
33774e20cfeSnh * Can't connect() after listen(), or if the socket is already
33874e20cfeSnh * connected.
33974e20cfeSnh */
34074e20cfeSnh if (so->so_state & (SS_ACCEPTCONN|SS_ISCONNECTED|SS_ISCONNECTING)) {
34174e20cfeSnh if (so->so_state & SS_ISCONNECTED) {
34274e20cfeSnh error = EISCONN;
34374e20cfeSnh } else if (so->so_state & SS_ISCONNECTING) {
34474e20cfeSnh error = EALREADY;
34574e20cfeSnh } else {
34674e20cfeSnh error = EOPNOTSUPP;
34774e20cfeSnh }
34874e20cfeSnh eprintsoline(so, error);
34974e20cfeSnh goto done;
35074e20cfeSnh }
35174e20cfeSnh
35274e20cfeSnh /*
3530f1702c5SYu Xiangning * check for failure of an earlier call
35474e20cfeSnh */
35574e20cfeSnh if (so->so_error != 0) {
3560f1702c5SYu Xiangning error = sogeterr(so, B_TRUE);
35774e20cfeSnh eprintsoline(so, error);
35874e20cfeSnh goto done;
35974e20cfeSnh }
36074e20cfeSnh
36174e20cfeSnh /*
36274e20cfeSnh * Connection is closing, or closed, don't allow reconnect.
36374e20cfeSnh * TCP allows this to proceed, but the socket remains unwriteable.
36474e20cfeSnh * BSD returns EINVAL.
36574e20cfeSnh */
36674e20cfeSnh if (so->so_state & (SS_ISDISCONNECTING|SS_CANTRCVMORE|
36774e20cfeSnh SS_CANTSENDMORE)) {
36874e20cfeSnh error = EINVAL;
36974e20cfeSnh eprintsoline(so, error);
37074e20cfeSnh goto done;
37174e20cfeSnh }
37274e20cfeSnh if (name == NULL || namelen == 0) {
3730f1702c5SYu Xiangning eprintsoline(so, EINVAL);
37474e20cfeSnh goto done;
37574e20cfeSnh }
37674e20cfeSnh soisconnecting(so);
37774e20cfeSnh mutex_exit(&so->so_lock);
37874e20cfeSnh
3790f1702c5SYu Xiangning error = sdp_connect((struct sdp_conn_struct_t *)so->so_proto_handle,
3800f1702c5SYu Xiangning name, namelen);
3810f1702c5SYu Xiangning
38274e20cfeSnh mutex_enter(&so->so_lock);
38374e20cfeSnh if (error == 0) {
38474e20cfeSnh /*
38574e20cfeSnh * Allow other threads to access the socket
38674e20cfeSnh */
3870f1702c5SYu Xiangning error = sowaitconnected(so, fflag, 0);
3880f1702c5SYu Xiangning dprint(4,
3890f1702c5SYu Xiangning ("sosdp_connect: wait on so:%p "
3900f1702c5SYu Xiangning "so_proto_handle:%p failed:%d",
3910f1702c5SYu Xiangning (void *)so, (void *)so->so_proto_handle, error));
39274e20cfeSnh }
3930f1702c5SYu Xiangning
39474e20cfeSnh switch (error) {
39574e20cfeSnh case 0:
39674e20cfeSnh case EINPROGRESS:
39774e20cfeSnh case EALREADY:
39874e20cfeSnh case EINTR:
39974e20cfeSnh /* Non-fatal errors */
40074e20cfeSnh so->so_state |= SS_ISBOUND;
40174e20cfeSnh break;
40274e20cfeSnh default:
40374e20cfeSnh /* clear SS_ISCONNECTING in case it was set */
40474e20cfeSnh so->so_state &= ~SS_ISCONNECTING;
40574e20cfeSnh break;
40674e20cfeSnh }
40774e20cfeSnh done:
40874e20cfeSnh so_unlock_single(so, SOLOCKED);
40974e20cfeSnh mutex_exit(&so->so_lock);
41074e20cfeSnh return (error);
41174e20cfeSnh }
41274e20cfeSnh
41374e20cfeSnh /*
41474e20cfeSnh * Receive data.
41574e20cfeSnh */
4160f1702c5SYu Xiangning /* ARGSUSED */
41774e20cfeSnh int
sosdp_recvmsg(struct sonode * so,struct nmsghdr * msg,struct uio * uiop,struct cred * cr)4180f1702c5SYu Xiangning sosdp_recvmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
4190f1702c5SYu Xiangning struct cred *cr)
42074e20cfeSnh {
42174e20cfeSnh int flags, error = 0;
42274e20cfeSnh int size;
42374e20cfeSnh
42474e20cfeSnh flags = msg->msg_flags;
42574e20cfeSnh msg->msg_flags = 0;
42674e20cfeSnh
42774e20cfeSnh
42874e20cfeSnh if (!(so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|
42974e20cfeSnh SS_CANTRCVMORE))) {
43074e20cfeSnh return (ENOTCONN);
43174e20cfeSnh }
43274e20cfeSnh
43374e20cfeSnh /*
43474e20cfeSnh * flag possibilities:
43574e20cfeSnh *
43674e20cfeSnh * MSG_PEEK Don't consume data
43774e20cfeSnh * MSG_WAITALL Wait for full quantity of data (ignored if MSG_PEEK)
43874e20cfeSnh * MSG_DONTWAIT Non-blocking (same as FNDELAY | FNONBLOCK)
43974e20cfeSnh *
44074e20cfeSnh * MSG_WAITALL can return less than the full buffer if either
44174e20cfeSnh *
44274e20cfeSnh * 1. we would block and we are non-blocking
44374e20cfeSnh * 2. a full message cannot be delivered
44474e20cfeSnh *
44574e20cfeSnh */
44674e20cfeSnh
44774e20cfeSnh mutex_enter(&so->so_lock);
44874e20cfeSnh
44974e20cfeSnh /*
45074e20cfeSnh * Allow just one reader at a time.
45174e20cfeSnh */
452255daac4Sethindra error = so_lock_read_intr(so,
453255daac4Sethindra uiop->uio_fmode | ((flags & MSG_DONTWAIT) ? FNONBLOCK : 0));
45474e20cfeSnh if (error != 0) {
45574e20cfeSnh mutex_exit(&so->so_lock);
45674e20cfeSnh return (error);
45774e20cfeSnh }
45874e20cfeSnh size = uiop->uio_resid;
45974e20cfeSnh mutex_exit(&so->so_lock);
46074e20cfeSnh
46174e20cfeSnh if (!(so->so_state & SS_CANTRCVMORE)) {
46274e20cfeSnh if (uiop->uio_fmode & (FNDELAY|FNONBLOCK)) {
46374e20cfeSnh flags |= MSG_DONTWAIT;
46474e20cfeSnh }
4650f1702c5SYu Xiangning error = sdp_recv(
4660f1702c5SYu Xiangning (struct sdp_conn_struct_t *)so->so_proto_handle, msg,
4670f1702c5SYu Xiangning size, flags, uiop);
46874e20cfeSnh } else {
46974e20cfeSnh msg->msg_controllen = 0;
47074e20cfeSnh msg->msg_namelen = 0;
47174e20cfeSnh }
47274e20cfeSnh done:
47374e20cfeSnh mutex_enter(&so->so_lock);
47474e20cfeSnh so_unlock_read(so);
47574e20cfeSnh mutex_exit(&so->so_lock);
47674e20cfeSnh return (error);
47774e20cfeSnh }
47874e20cfeSnh
47974e20cfeSnh /*
48074e20cfeSnh * Send message.
48174e20cfeSnh */
4820f1702c5SYu Xiangning /* ARGSUSED */
48374e20cfeSnh static int
sosdp_sendmsg(struct sonode * so,struct nmsghdr * msg,struct uio * uiop,struct cred * cr)4840f1702c5SYu Xiangning sosdp_sendmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
4850f1702c5SYu Xiangning struct cred *cr)
48674e20cfeSnh {
48774e20cfeSnh int flags;
48874e20cfeSnh ssize_t count;
48974e20cfeSnh int error;
49074e20cfeSnh
49174e20cfeSnh ASSERT(so->so_type == SOCK_STREAM);
49274e20cfeSnh
4930f1702c5SYu Xiangning dprint(4, ("sosdp_sendmsg: so:%p so_proto_handle:%p",
4940f1702c5SYu Xiangning (void *)so, (void *)so->so_proto_handle));
49574e20cfeSnh
49674e20cfeSnh flags = msg->msg_flags;
49774e20cfeSnh
49874e20cfeSnh if (msg->msg_controllen != 0) {
49974e20cfeSnh return (EOPNOTSUPP);
50074e20cfeSnh }
50174e20cfeSnh
50274e20cfeSnh mutex_enter(&so->so_lock);
50374e20cfeSnh if (so->so_state & SS_CANTSENDMORE) {
50474e20cfeSnh mutex_exit(&so->so_lock);
50574e20cfeSnh return (EPIPE);
50674e20cfeSnh }
50774e20cfeSnh
50874e20cfeSnh if (so->so_error != 0) {
5090f1702c5SYu Xiangning error = sogeterr(so, B_TRUE);
51074e20cfeSnh mutex_exit(&so->so_lock);
51174e20cfeSnh return (error);
51274e20cfeSnh }
51374e20cfeSnh
51474e20cfeSnh if (uiop->uio_fmode & (FNDELAY|FNONBLOCK))
515b5fca8f8Stomee flags |= MSG_DONTWAIT;
51674e20cfeSnh
51774e20cfeSnh count = uiop->uio_resid;
51874e20cfeSnh
51974e20cfeSnh if (!(so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED))) {
52074e20cfeSnh dprint(4, ("sosdp_sendmsg: invalid state: <%x>",
52174e20cfeSnh so->so_state));
52274e20cfeSnh mutex_exit(&so->so_lock);
52374e20cfeSnh return (ENOTCONN);
52474e20cfeSnh }
52574e20cfeSnh
52674e20cfeSnh mutex_exit(&so->so_lock);
5270f1702c5SYu Xiangning error = sdp_send((struct sdp_conn_struct_t *)so->so_proto_handle,
5280f1702c5SYu Xiangning msg, count, flags, uiop);
52974e20cfeSnh
53074e20cfeSnh return (error);
53174e20cfeSnh }
53274e20cfeSnh
53374e20cfeSnh /*
53474e20cfeSnh * Get address of remote node.
53574e20cfeSnh */
5360f1702c5SYu Xiangning /* ARGSUSED */
53774e20cfeSnh static int
sosdp_getpeername(struct sonode * so,struct sockaddr * addr,socklen_t * addrlen,boolean_t accept,struct cred * cr)5380f1702c5SYu Xiangning sosdp_getpeername(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
5390f1702c5SYu Xiangning boolean_t accept, struct cred *cr)
54074e20cfeSnh {
54174e20cfeSnh
5420f1702c5SYu Xiangning if (!accept && !(so->so_state & SS_ISCONNECTED)) {
5430f1702c5SYu Xiangning return (ENOTCONN);
54474e20cfeSnh } else {
5450f1702c5SYu Xiangning return (sdp_getpeername(
5460f1702c5SYu Xiangning (struct sdp_conn_struct_t *)so->so_proto_handle,
5470f1702c5SYu Xiangning addr, addrlen));
54874e20cfeSnh }
54974e20cfeSnh }
55074e20cfeSnh
55174e20cfeSnh /*
55274e20cfeSnh * Get local address.
55374e20cfeSnh */
5540f1702c5SYu Xiangning /* ARGSUSED */
55574e20cfeSnh static int
sosdp_getsockname(struct sonode * so,struct sockaddr * addr,socklen_t * addrlen,struct cred * cr)5560f1702c5SYu Xiangning sosdp_getsockname(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
5570f1702c5SYu Xiangning struct cred *cr)
55874e20cfeSnh {
55974e20cfeSnh mutex_enter(&so->so_lock);
5600f1702c5SYu Xiangning
56174e20cfeSnh if (!(so->so_state & SS_ISBOUND)) {
56274e20cfeSnh /*
56374e20cfeSnh * Zero address, except for address family
56474e20cfeSnh */
5650f1702c5SYu Xiangning if (so->so_family == AF_INET || so->so_family == AF_INET6) {
5660f1702c5SYu Xiangning bzero(addr, *addrlen);
5670f1702c5SYu Xiangning *addrlen = (so->so_family == AF_INET6) ?
5680f1702c5SYu Xiangning sizeof (struct sockaddr_in6) :
5690f1702c5SYu Xiangning sizeof (struct sockaddr_in);
5700f1702c5SYu Xiangning addr->sa_family = so->so_family;
5710f1702c5SYu Xiangning }
57274e20cfeSnh mutex_exit(&so->so_lock);
5730f1702c5SYu Xiangning return (0);
57474e20cfeSnh } else {
57574e20cfeSnh mutex_exit(&so->so_lock);
5760f1702c5SYu Xiangning return (sdp_getsockname(
5770f1702c5SYu Xiangning (struct sdp_conn_struct_t *)so->so_proto_handle,
5780f1702c5SYu Xiangning addr, addrlen));
57974e20cfeSnh }
58074e20cfeSnh }
58174e20cfeSnh
58274e20cfeSnh /*
58374e20cfeSnh * Called from shutdown().
58474e20cfeSnh */
5850f1702c5SYu Xiangning /* ARGSUSED */
58674e20cfeSnh static int
sosdp_shutdown(struct sonode * so,int how,struct cred * cr)5870f1702c5SYu Xiangning sosdp_shutdown(struct sonode *so, int how, struct cred *cr)
58874e20cfeSnh {
58974e20cfeSnh uint_t state_change;
59074e20cfeSnh int error = 0;
59174e20cfeSnh
59274e20cfeSnh mutex_enter(&so->so_lock);
59374e20cfeSnh so_lock_single(so);
59474e20cfeSnh /*
59574e20cfeSnh * Record the current state and then perform any state changes.
59674e20cfeSnh * Then use the difference between the old and new states to
59774e20cfeSnh * determine which needs to be done.
59874e20cfeSnh */
59974e20cfeSnh state_change = so->so_state;
6000f1702c5SYu Xiangning if (!(state_change & SS_ISCONNECTED)) {
6010f1702c5SYu Xiangning error = ENOTCONN;
6020f1702c5SYu Xiangning goto done;
6030f1702c5SYu Xiangning }
60474e20cfeSnh
60574e20cfeSnh switch (how) {
60674e20cfeSnh case SHUT_RD:
60774e20cfeSnh socantrcvmore(so);
60874e20cfeSnh break;
60974e20cfeSnh case SHUT_WR:
61074e20cfeSnh socantsendmore(so);
61174e20cfeSnh break;
61274e20cfeSnh case SHUT_RDWR:
61374e20cfeSnh socantsendmore(so);
61474e20cfeSnh socantrcvmore(so);
61574e20cfeSnh break;
61674e20cfeSnh default:
61774e20cfeSnh error = EINVAL;
61874e20cfeSnh goto done;
61974e20cfeSnh }
62074e20cfeSnh
62174e20cfeSnh state_change = so->so_state & ~state_change;
62274e20cfeSnh
62374e20cfeSnh if (state_change & SS_CANTSENDMORE) {
62474e20cfeSnh so->so_state |= SS_ISDISCONNECTING;
62574e20cfeSnh }
6260f1702c5SYu Xiangning so_notify_shutdown(so);
62774e20cfeSnh
62874e20cfeSnh if (state_change & SS_CANTSENDMORE) {
6290f1702c5SYu Xiangning error = sdp_shutdown(
6300f1702c5SYu Xiangning (struct sdp_conn_struct_t *)so->so_proto_handle, how);
63174e20cfeSnh }
6320f1702c5SYu Xiangning
63374e20cfeSnh mutex_enter(&so->so_lock);
63474e20cfeSnh done:
63574e20cfeSnh so_unlock_single(so, SOLOCKED);
63674e20cfeSnh mutex_exit(&so->so_lock);
63774e20cfeSnh
63874e20cfeSnh /*
63974e20cfeSnh * HACK: sdp_disconnect() may return EWOULDBLOCK. But this error is
64074e20cfeSnh * not documented in standard socket API. Catch it here.
64174e20cfeSnh */
64274e20cfeSnh if (error == EWOULDBLOCK)
64374e20cfeSnh error = 0;
64474e20cfeSnh return (error);
64574e20cfeSnh }
64674e20cfeSnh
64774e20cfeSnh /*
64874e20cfeSnh * Get socket options.
64974e20cfeSnh */
65074e20cfeSnh /*ARGSUSED*/
65174e20cfeSnh static int
sosdp_getsockopt(struct sonode * so,int level,int option_name,void * optval,socklen_t * optlenp,int flags,struct cred * cr)65274e20cfeSnh sosdp_getsockopt(struct sonode *so, int level, int option_name,
6530f1702c5SYu Xiangning void *optval, socklen_t *optlenp, int flags, struct cred *cr)
65474e20cfeSnh {
65574e20cfeSnh int error = 0;
65674e20cfeSnh void *option = NULL;
65774e20cfeSnh socklen_t maxlen = *optlenp, len, optlen;
65874e20cfeSnh uint32_t value;
65974e20cfeSnh uint8_t buffer[4];
66074e20cfeSnh void *optbuf = &buffer;
66174e20cfeSnh
66274e20cfeSnh
66374e20cfeSnh mutex_enter(&so->so_lock);
66474e20cfeSnh
66574e20cfeSnh if (level == SOL_SOCKET) {
66674e20cfeSnh switch (option_name) {
66774e20cfeSnh case SO_TYPE:
66874e20cfeSnh case SO_ERROR:
66974e20cfeSnh case SO_DEBUG:
67074e20cfeSnh case SO_ACCEPTCONN:
67174e20cfeSnh case SO_REUSEADDR:
67274e20cfeSnh case SO_KEEPALIVE:
67374e20cfeSnh case SO_DONTROUTE:
67474e20cfeSnh case SO_BROADCAST:
67574e20cfeSnh case SO_USELOOPBACK:
67674e20cfeSnh case SO_OOBINLINE:
67774e20cfeSnh case SO_SNDBUF:
67874e20cfeSnh case SO_RCVBUF:
67974e20cfeSnh case SO_SNDLOWAT:
68074e20cfeSnh case SO_RCVLOWAT:
68174e20cfeSnh case SO_DGRAM_ERRIND:
68274e20cfeSnh if (maxlen < (t_uscalar_t)sizeof (int32_t)) {
68374e20cfeSnh error = EINVAL;
68474e20cfeSnh eprintsoline(so, error);
68574e20cfeSnh goto done;
68674e20cfeSnh }
68774e20cfeSnh break;
68874e20cfeSnh case SO_LINGER:
68974e20cfeSnh if (maxlen < (t_uscalar_t)sizeof (struct linger)) {
69074e20cfeSnh error = EINVAL;
69174e20cfeSnh eprintsoline(so, error);
69274e20cfeSnh goto done;
69374e20cfeSnh }
69474e20cfeSnh break;
69574e20cfeSnh }
69674e20cfeSnh len = (t_uscalar_t)sizeof (uint32_t); /* Default */
69774e20cfeSnh option = &value;
69874e20cfeSnh
69974e20cfeSnh switch (option_name) {
70074e20cfeSnh case SO_TYPE:
70174e20cfeSnh value = so->so_type;
70274e20cfeSnh goto copyout;
70374e20cfeSnh
70474e20cfeSnh case SO_ERROR:
7050f1702c5SYu Xiangning value = sogeterr(so, B_TRUE);
70674e20cfeSnh goto copyout;
70774e20cfeSnh
70874e20cfeSnh case SO_ACCEPTCONN:
70974e20cfeSnh value = (so->so_state & SS_ACCEPTCONN) ?
71074e20cfeSnh SO_ACCEPTCONN : 0;
71174e20cfeSnh goto copyout;
71274e20cfeSnh
71374e20cfeSnh case SO_DEBUG:
71474e20cfeSnh case SO_REUSEADDR:
71574e20cfeSnh case SO_KEEPALIVE:
71674e20cfeSnh case SO_DONTROUTE:
71774e20cfeSnh case SO_BROADCAST:
71874e20cfeSnh case SO_USELOOPBACK:
71974e20cfeSnh case SO_OOBINLINE:
72074e20cfeSnh case SO_DGRAM_ERRIND:
72174e20cfeSnh value = (so->so_options & option_name);
72274e20cfeSnh goto copyout;
72374e20cfeSnh
72474e20cfeSnh /*
72574e20cfeSnh * The following options are only returned by sockfs
72674e20cfeSnh * when sdp_get_opt() fails.
72774e20cfeSnh */
72874e20cfeSnh
72974e20cfeSnh case SO_LINGER:
73074e20cfeSnh option = &so->so_linger;
73174e20cfeSnh len = (t_uscalar_t)sizeof (struct linger);
73274e20cfeSnh break;
73374e20cfeSnh case SO_SNDBUF:
73474e20cfeSnh value = so->so_sndbuf;
73574e20cfeSnh len = (t_uscalar_t)sizeof (int);
73674e20cfeSnh goto copyout;
73774e20cfeSnh
73874e20cfeSnh case SO_RCVBUF:
73974e20cfeSnh value = so->so_rcvbuf;
74074e20cfeSnh len = (t_uscalar_t)sizeof (int);
74174e20cfeSnh goto copyout;
74274e20cfeSnh
74374e20cfeSnh case SO_SNDLOWAT:
74474e20cfeSnh value = so->so_sndlowat;
74574e20cfeSnh len = (t_uscalar_t)sizeof (int);
74674e20cfeSnh goto copyout;
74774e20cfeSnh
74874e20cfeSnh case SO_RCVLOWAT:
74974e20cfeSnh value = so->so_rcvlowat;
75074e20cfeSnh len = (t_uscalar_t)sizeof (int);
75174e20cfeSnh goto copyout;
75274e20cfeSnh
75374e20cfeSnh default:
75474e20cfeSnh option = NULL;
75574e20cfeSnh break;
75674e20cfeSnh }
75774e20cfeSnh }
75874e20cfeSnh if (maxlen > sizeof (buffer)) {
75974e20cfeSnh optbuf = kmem_alloc(maxlen, KM_SLEEP);
76074e20cfeSnh }
76174e20cfeSnh optlen = maxlen;
76274e20cfeSnh mutex_exit(&so->so_lock);
7630f1702c5SYu Xiangning error = sdp_get_opt((struct sdp_conn_struct_t *)so->so_proto_handle,
7640f1702c5SYu Xiangning level, option_name, optbuf, &optlen);
76574e20cfeSnh mutex_enter(&so->so_lock);
76674e20cfeSnh ASSERT(optlen <= maxlen);
76774e20cfeSnh if (error != 0) {
76874e20cfeSnh if (option == NULL) {
76974e20cfeSnh /* We have no fallback value */
77074e20cfeSnh eprintsoline(so, error);
77174e20cfeSnh goto free;
77274e20cfeSnh }
77374e20cfeSnh error = 0;
77474e20cfeSnh goto copyout;
77574e20cfeSnh }
77674e20cfeSnh
77774e20cfeSnh option = optbuf;
77874e20cfeSnh len = optlen;
77974e20cfeSnh
78074e20cfeSnh copyout:
78174e20cfeSnh len = MIN(len, maxlen);
78274e20cfeSnh bcopy(option, optval, len);
78374e20cfeSnh *optlenp = len;
78474e20cfeSnh
78574e20cfeSnh free:
78674e20cfeSnh if (optbuf != &buffer) {
78774e20cfeSnh kmem_free(optbuf, maxlen);
78874e20cfeSnh }
78974e20cfeSnh done:
79074e20cfeSnh mutex_exit(&so->so_lock);
79174e20cfeSnh return (error);
79274e20cfeSnh }
79374e20cfeSnh
79474e20cfeSnh /*
79574e20cfeSnh * Set socket options
79674e20cfeSnh */
7970f1702c5SYu Xiangning /* ARGSUSED */
79874e20cfeSnh static int
sosdp_setsockopt(struct sonode * so,int level,int option_name,const void * optval,t_uscalar_t optlen,struct cred * cr)79974e20cfeSnh sosdp_setsockopt(struct sonode *so, int level, int option_name,
8000f1702c5SYu Xiangning const void *optval, t_uscalar_t optlen, struct cred *cr)
80174e20cfeSnh {
80274e20cfeSnh void *conn = NULL;
8030f1702c5SYu Xiangning int error = 0;
80474e20cfeSnh
80574e20cfeSnh if (so->so_state & SS_CANTSENDMORE) {
80674e20cfeSnh return (EINVAL);
80774e20cfeSnh }
80874e20cfeSnh
80974e20cfeSnh mutex_enter(&so->so_lock);
81074e20cfeSnh so_lock_single(so);
81174e20cfeSnh
81274e20cfeSnh if (so->so_type == SOCK_STREAM) {
8130f1702c5SYu Xiangning conn = (void *)so->so_proto_handle;
81474e20cfeSnh }
81574e20cfeSnh
81674e20cfeSnh dprint(2, ("sosdp_setsockopt (%d) - conn %p %d %d \n",
817b5fca8f8Stomee so->so_type, conn, level, option_name));
8180f1702c5SYu Xiangning
81974e20cfeSnh if (conn != NULL) {
82074e20cfeSnh mutex_exit(&so->so_lock);
8210f1702c5SYu Xiangning error = sdp_set_opt((struct sdp_conn_struct_t *)conn, level,
8220f1702c5SYu Xiangning option_name, optval, optlen);
82374e20cfeSnh mutex_enter(&so->so_lock);
82474e20cfeSnh }
8250f1702c5SYu Xiangning
82674e20cfeSnh /*
82774e20cfeSnh * Check for SOL_SOCKET options and record their values.
82874e20cfeSnh * If we know about a SOL_SOCKET parameter and the transport
82974e20cfeSnh * failed it with TBADOPT or TOUTSTATE (i.e. ENOPROTOOPT or
83074e20cfeSnh * EPROTO) we let the setsockopt succeed.
83174e20cfeSnh */
83274e20cfeSnh if (level == SOL_SOCKET) {
83374e20cfeSnh boolean_t handled = B_FALSE;
83474e20cfeSnh
83574e20cfeSnh /* Check parameters */
83674e20cfeSnh switch (option_name) {
83774e20cfeSnh case SO_DEBUG:
83874e20cfeSnh case SO_REUSEADDR:
83974e20cfeSnh case SO_KEEPALIVE:
84074e20cfeSnh case SO_DONTROUTE:
84174e20cfeSnh case SO_BROADCAST:
84274e20cfeSnh case SO_USELOOPBACK:
84374e20cfeSnh case SO_OOBINLINE:
84474e20cfeSnh case SO_SNDBUF:
84574e20cfeSnh case SO_RCVBUF:
84674e20cfeSnh case SO_SNDLOWAT:
84774e20cfeSnh case SO_RCVLOWAT:
84874e20cfeSnh case SO_DGRAM_ERRIND:
84974e20cfeSnh if (optlen != (t_uscalar_t)sizeof (int32_t)) {
85074e20cfeSnh error = EINVAL;
85174e20cfeSnh eprintsoline(so, error);
85274e20cfeSnh goto done;
85374e20cfeSnh }
85474e20cfeSnh ASSERT(optval);
85574e20cfeSnh handled = B_TRUE;
85674e20cfeSnh break;
85774e20cfeSnh case SO_LINGER:
85874e20cfeSnh if (optlen != (t_uscalar_t)sizeof (struct linger)) {
85974e20cfeSnh error = EINVAL;
86074e20cfeSnh eprintsoline(so, error);
86174e20cfeSnh goto done;
86274e20cfeSnh }
86374e20cfeSnh ASSERT(optval);
86474e20cfeSnh handled = B_TRUE;
86574e20cfeSnh break;
86674e20cfeSnh }
86774e20cfeSnh
86874e20cfeSnh #define intvalue (*(int32_t *)optval)
86974e20cfeSnh
87074e20cfeSnh switch (option_name) {
87174e20cfeSnh case SO_TYPE:
87274e20cfeSnh case SO_ERROR:
87374e20cfeSnh case SO_ACCEPTCONN:
87474e20cfeSnh /* Can't be set */
87574e20cfeSnh error = ENOPROTOOPT;
87674e20cfeSnh goto done;
87774e20cfeSnh case SO_LINGER: {
87874e20cfeSnh struct linger *l = (struct linger *)optval;
87974e20cfeSnh
88074e20cfeSnh so->so_linger.l_linger = l->l_linger;
88174e20cfeSnh if (l->l_onoff) {
88274e20cfeSnh so->so_linger.l_onoff = SO_LINGER;
88374e20cfeSnh so->so_options |= SO_LINGER;
88474e20cfeSnh } else {
88574e20cfeSnh so->so_linger.l_onoff = 0;
88674e20cfeSnh so->so_options &= ~SO_LINGER;
88774e20cfeSnh }
88874e20cfeSnh break;
88974e20cfeSnh }
89074e20cfeSnh
89174e20cfeSnh case SO_DEBUG:
89274e20cfeSnh case SO_REUSEADDR:
89374e20cfeSnh case SO_KEEPALIVE:
89474e20cfeSnh case SO_DONTROUTE:
89574e20cfeSnh case SO_BROADCAST:
89674e20cfeSnh case SO_USELOOPBACK:
89774e20cfeSnh case SO_OOBINLINE:
89874e20cfeSnh case SO_DGRAM_ERRIND:
89974e20cfeSnh if (intvalue != 0) {
90074e20cfeSnh dprintso(so, 1,
90174e20cfeSnh ("sosdp_setsockopt: setting 0x%x\n",
902b5fca8f8Stomee option_name));
90374e20cfeSnh so->so_options |= option_name;
90474e20cfeSnh } else {
90574e20cfeSnh dprintso(so, 1,
90674e20cfeSnh ("sosdp_setsockopt: clearing 0x%x\n",
907b5fca8f8Stomee option_name));
90874e20cfeSnh so->so_options &= ~option_name;
90974e20cfeSnh }
91074e20cfeSnh break;
91174e20cfeSnh
91274e20cfeSnh case SO_SNDBUF:
91374e20cfeSnh so->so_sndbuf = intvalue;
91474e20cfeSnh if (so->so_sndlowat > so->so_sndbuf) {
91574e20cfeSnh so->so_sndlowat = so->so_sndbuf;
91674e20cfeSnh }
91774e20cfeSnh break;
91874e20cfeSnh case SO_RCVBUF:
91974e20cfeSnh so->so_rcvbuf = intvalue;
92074e20cfeSnh if (so->so_rcvlowat > so->so_rcvbuf) {
92174e20cfeSnh so->so_rcvlowat = so->so_rcvbuf;
92274e20cfeSnh }
92374e20cfeSnh break;
92474e20cfeSnh case SO_SNDLOWAT:
92574e20cfeSnh if (so->so_sndlowat > so->so_sndbuf) {
92674e20cfeSnh so->so_sndlowat = so->so_sndbuf;
92774e20cfeSnh }
92874e20cfeSnh break;
92974e20cfeSnh case SO_RCVLOWAT:
93074e20cfeSnh if (so->so_rcvlowat > so->so_rcvbuf) {
93174e20cfeSnh so->so_rcvlowat = so->so_rcvbuf;
93274e20cfeSnh }
93374e20cfeSnh break;
93474e20cfeSnh }
93574e20cfeSnh #undef intvalue
93674e20cfeSnh
93774e20cfeSnh if (error != 0) {
93874e20cfeSnh if ((error == ENOPROTOOPT || error == EPROTO ||
93974e20cfeSnh error == EINVAL) && handled) {
94074e20cfeSnh dprintso(so, 1,
94174e20cfeSnh ("sosdp_setsockopt: ignoring error %d "
942b5fca8f8Stomee "for 0x%x\n", error, option_name));
94374e20cfeSnh error = 0;
94474e20cfeSnh }
94574e20cfeSnh }
94674e20cfeSnh }
94774e20cfeSnh
94874e20cfeSnh done:
94974e20cfeSnh so_unlock_single(so, SOLOCKED);
95074e20cfeSnh mutex_exit(&so->so_lock);
95174e20cfeSnh
95274e20cfeSnh return (error);
95374e20cfeSnh }
95474e20cfeSnh
9550f1702c5SYu Xiangning /* ARGSUSED */
9560f1702c5SYu Xiangning static int
sosdp_ioctl(struct sonode * so,int cmd,intptr_t arg,int mode,struct cred * cr,int32_t * rvalp)9570f1702c5SYu Xiangning sosdp_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode,
9580f1702c5SYu Xiangning struct cred *cr, int32_t *rvalp)
9590f1702c5SYu Xiangning {
9600f1702c5SYu Xiangning int32_t value;
9610f1702c5SYu Xiangning int error, intval;
9620f1702c5SYu Xiangning pid_t pid;
9630f1702c5SYu Xiangning
9640f1702c5SYu Xiangning /* handle socket specific ioctls */
9650f1702c5SYu Xiangning switch (cmd) {
9660f1702c5SYu Xiangning case FIONBIO:
9670f1702c5SYu Xiangning if (so_copyin((void *)arg, &value, sizeof (int32_t),
9680f1702c5SYu Xiangning (mode & (int)FKIOCTL))) {
9690f1702c5SYu Xiangning return (EFAULT);
9700f1702c5SYu Xiangning }
9710f1702c5SYu Xiangning mutex_enter(&so->so_lock);
9720f1702c5SYu Xiangning if (value != 0) {
9730f1702c5SYu Xiangning so->so_state |= SS_NDELAY;
9740f1702c5SYu Xiangning } else {
9750f1702c5SYu Xiangning so->so_state &= ~SS_NDELAY;
9760f1702c5SYu Xiangning }
9770f1702c5SYu Xiangning mutex_exit(&so->so_lock);
9780f1702c5SYu Xiangning return (0);
9790f1702c5SYu Xiangning
9800f1702c5SYu Xiangning case FIOASYNC:
9810f1702c5SYu Xiangning if (so_copyin((void *)arg, &value, sizeof (int32_t),
9820f1702c5SYu Xiangning (mode & (int)FKIOCTL))) {
9830f1702c5SYu Xiangning return (EFAULT);
9840f1702c5SYu Xiangning }
9850f1702c5SYu Xiangning mutex_enter(&so->so_lock);
9860f1702c5SYu Xiangning
9870f1702c5SYu Xiangning if (value) {
9880f1702c5SYu Xiangning /* Turn on SIGIO */
9890f1702c5SYu Xiangning so->so_state |= SS_ASYNC;
9900f1702c5SYu Xiangning } else {
9910f1702c5SYu Xiangning /* Turn off SIGIO */
9920f1702c5SYu Xiangning so->so_state &= ~SS_ASYNC;
9930f1702c5SYu Xiangning }
9940f1702c5SYu Xiangning mutex_exit(&so->so_lock);
9950f1702c5SYu Xiangning return (0);
9960f1702c5SYu Xiangning
9970f1702c5SYu Xiangning case SIOCSPGRP:
9980f1702c5SYu Xiangning case FIOSETOWN:
9990f1702c5SYu Xiangning if (so_copyin((void *)arg, &pid, sizeof (pid_t),
10000f1702c5SYu Xiangning (mode & (int)FKIOCTL))) {
10010f1702c5SYu Xiangning return (EFAULT);
10020f1702c5SYu Xiangning }
10030f1702c5SYu Xiangning mutex_enter(&so->so_lock);
10040f1702c5SYu Xiangning
10050f1702c5SYu Xiangning error = (pid != so->so_pgrp) ? socket_chgpgrp(so, pid) : 0;
10060f1702c5SYu Xiangning mutex_exit(&so->so_lock);
10070f1702c5SYu Xiangning return (error);
10080f1702c5SYu Xiangning
10090f1702c5SYu Xiangning case SIOCGPGRP:
10100f1702c5SYu Xiangning case FIOGETOWN:
10110f1702c5SYu Xiangning if (so_copyout(&so->so_pgrp, (void *)arg,
10120f1702c5SYu Xiangning sizeof (pid_t), (mode & (int)FKIOCTL)))
10130f1702c5SYu Xiangning return (EFAULT);
10140f1702c5SYu Xiangning return (0);
10150f1702c5SYu Xiangning
10160f1702c5SYu Xiangning case SIOCATMARK:
10170f1702c5SYu Xiangning intval = 0;
10180f1702c5SYu Xiangning error = sdp_ioctl(
10190f1702c5SYu Xiangning (struct sdp_conn_struct_t *)so->so_proto_handle, cmd,
10200f1702c5SYu Xiangning &intval, cr);
10210f1702c5SYu Xiangning if (so_copyout(&intval, (void *)arg, sizeof (int),
10220f1702c5SYu Xiangning (mode & (int)FKIOCTL)))
10230f1702c5SYu Xiangning return (EFAULT);
10240f1702c5SYu Xiangning return (0);
10250f1702c5SYu Xiangning
10260f1702c5SYu Xiangning
10270f1702c5SYu Xiangning case SIOCSENABLESDP: {
10280f1702c5SYu Xiangning int32_t enable;
10290f1702c5SYu Xiangning
10300f1702c5SYu Xiangning /*
10310f1702c5SYu Xiangning * System wide enable SDP
10320f1702c5SYu Xiangning */
10330f1702c5SYu Xiangning
10340f1702c5SYu Xiangning if (so_copyin((void *)arg, &enable, sizeof (int32_t),
10350f1702c5SYu Xiangning mode & (int)FKIOCTL))
10360f1702c5SYu Xiangning return (EFAULT);
10370f1702c5SYu Xiangning
10380f1702c5SYu Xiangning error = sdp_ioctl(
10390f1702c5SYu Xiangning (struct sdp_conn_struct_t *)so->so_proto_handle, cmd,
10400f1702c5SYu Xiangning &enable, cr);
10410f1702c5SYu Xiangning if (so_copyout(&enable, (void *)arg,
10420f1702c5SYu Xiangning sizeof (int32_t), (mode & (int)FKIOCTL)))
10430f1702c5SYu Xiangning return (EFAULT);
10440f1702c5SYu Xiangning return (0);
10450f1702c5SYu Xiangning }
10460f1702c5SYu Xiangning /* from strioctl */
10470f1702c5SYu Xiangning case FIONREAD:
10480f1702c5SYu Xiangning /*
10490f1702c5SYu Xiangning * Return number of bytes of data in all data messages
10500f1702c5SYu Xiangning * in queue in "arg".
10510f1702c5SYu Xiangning * For stream socket, amount of available data.
10520f1702c5SYu Xiangning */
10530f1702c5SYu Xiangning if (so->so_state & SS_ACCEPTCONN) {
10540f1702c5SYu Xiangning intval = 0;
10550f1702c5SYu Xiangning } else {
10560f1702c5SYu Xiangning mutex_enter(&so->so_lock);
10570f1702c5SYu Xiangning intval = sdp_polldata(
10580f1702c5SYu Xiangning (struct sdp_conn_struct_t *)so->so_proto_handle,
10590f1702c5SYu Xiangning SDP_READ);
10600f1702c5SYu Xiangning mutex_exit(&so->so_lock);
10610f1702c5SYu Xiangning }
10620f1702c5SYu Xiangning if (so_copyout(&intval, (void *)arg, sizeof (intval),
10630f1702c5SYu Xiangning (mode & (int)FKIOCTL)))
10640f1702c5SYu Xiangning return (EFAULT);
10650f1702c5SYu Xiangning return (0);
10660f1702c5SYu Xiangning default:
10670f1702c5SYu Xiangning return (EINVAL);
10680f1702c5SYu Xiangning }
10690f1702c5SYu Xiangning }
10700f1702c5SYu Xiangning
10710f1702c5SYu Xiangning /*
10720f1702c5SYu Xiangning * Check socktpi_poll() on why so_lock is not held in this function.
10730f1702c5SYu Xiangning */
10740f1702c5SYu Xiangning static int
sosdp_poll(struct sonode * so,short events,int anyyet,short * reventsp,struct pollhead ** phpp)10750f1702c5SYu Xiangning sosdp_poll(struct sonode *so, short events, int anyyet, short *reventsp,
10760f1702c5SYu Xiangning struct pollhead **phpp)
10770f1702c5SYu Xiangning {
10780f1702c5SYu Xiangning short origevents = events;
10790f1702c5SYu Xiangning int so_state;
10800f1702c5SYu Xiangning
10810f1702c5SYu Xiangning so_state = so->so_state;
10820f1702c5SYu Xiangning
10830f1702c5SYu Xiangning ASSERT(so->so_version != SOV_STREAM);
10840f1702c5SYu Xiangning
10850f1702c5SYu Xiangning if (!(so_state & SS_ISCONNECTED) && (so->so_type == SOCK_STREAM)) {
10860f1702c5SYu Xiangning /*
10870f1702c5SYu Xiangning * Not connected yet - turn off write side events
10880f1702c5SYu Xiangning */
10890f1702c5SYu Xiangning events &= ~(POLLOUT|POLLWRBAND);
10900f1702c5SYu Xiangning }
10910f1702c5SYu Xiangning
10920f1702c5SYu Xiangning /*
10930f1702c5SYu Xiangning * Check for errors
10940f1702c5SYu Xiangning */
10950f1702c5SYu Xiangning if (so->so_error != 0 &&
1096*80d5689fSPatrick Mooney ((POLLIN|POLLRDNORM|POLLOUT) & origevents) != 0) {
10970f1702c5SYu Xiangning *reventsp = (POLLIN|POLLRDNORM|POLLOUT) & origevents;
1098*80d5689fSPatrick Mooney goto done;
10990f1702c5SYu Xiangning }
11000f1702c5SYu Xiangning
11010f1702c5SYu Xiangning *reventsp = 0;
1102*80d5689fSPatrick Mooney if (so->so_type != SOCK_STREAM) {
1103*80d5689fSPatrick Mooney goto done;
1104*80d5689fSPatrick Mooney }
11050f1702c5SYu Xiangning
11060f1702c5SYu Xiangning /*
1107*80d5689fSPatrick Mooney * Don't mark socket writable until TX queued data is below watermark.
11080f1702c5SYu Xiangning */
1109*80d5689fSPatrick Mooney if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
1110*80d5689fSPatrick Mooney SDP_XMIT)) {
1111*80d5689fSPatrick Mooney *reventsp |= POLLOUT & events;
11120f1702c5SYu Xiangning }
11130f1702c5SYu Xiangning
11140f1702c5SYu Xiangning if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
11150f1702c5SYu Xiangning SDP_READ)) {
11160f1702c5SYu Xiangning *reventsp |= (POLLIN|POLLRDNORM) & events;
11170f1702c5SYu Xiangning }
11180f1702c5SYu Xiangning
11193e95bd4aSAnders Persson if ((so_state & SS_CANTRCVMORE) || (so->so_acceptq_len > 0)) {
11200f1702c5SYu Xiangning *reventsp |= (POLLIN|POLLRDNORM) & events;
11210f1702c5SYu Xiangning }
11220f1702c5SYu Xiangning
11230f1702c5SYu Xiangning done:
1124*80d5689fSPatrick Mooney if ((*reventsp == 0 && !anyyet) || (events & POLLET)) {
11250f1702c5SYu Xiangning *phpp = &so->so_poll_list;
11260f1702c5SYu Xiangning }
11270f1702c5SYu Xiangning
11280f1702c5SYu Xiangning return (0);
11290f1702c5SYu Xiangning }
11300f1702c5SYu Xiangning
11310f1702c5SYu Xiangning /* ARGSUSED */
11320f1702c5SYu Xiangning static int
sosdp_close(struct sonode * so,int flag,struct cred * cr)11330f1702c5SYu Xiangning sosdp_close(struct sonode *so, int flag, struct cred *cr)
11340f1702c5SYu Xiangning {
11350f1702c5SYu Xiangning int error = 0;
11360f1702c5SYu Xiangning
11370f1702c5SYu Xiangning mutex_enter(&so->so_lock);
11380f1702c5SYu Xiangning so_lock_single(so);
11390f1702c5SYu Xiangning /*
11400f1702c5SYu Xiangning * Need to set flags as there might be ops in progress on
11410f1702c5SYu Xiangning * this socket.
11420f1702c5SYu Xiangning *
11430f1702c5SYu Xiangning * If socket already disconnected/disconnecting,
11440f1702c5SYu Xiangning * don't send signal (again).
11450f1702c5SYu Xiangning */
11460f1702c5SYu Xiangning soisdisconnected(so, 0);
11470f1702c5SYu Xiangning mutex_exit(&so->so_lock);
11480f1702c5SYu Xiangning
11490f1702c5SYu Xiangning /*
11500f1702c5SYu Xiangning * Initiate connection shutdown.
11510f1702c5SYu Xiangning */
11520f1702c5SYu Xiangning error = sdp_disconnect((struct sdp_conn_struct_t *)so->so_proto_handle,
11530f1702c5SYu Xiangning flag);
11540f1702c5SYu Xiangning
11550f1702c5SYu Xiangning mutex_enter(&so->so_lock);
11560f1702c5SYu Xiangning so_unlock_single(so, SOLOCKED);
11573e95bd4aSAnders Persson so_notify_disconnected(so, B_FALSE, error);
11580f1702c5SYu Xiangning
11590f1702c5SYu Xiangning return (error);
11600f1702c5SYu Xiangning }
11610f1702c5SYu Xiangning
11620f1702c5SYu Xiangning /* ARGSUSED */
11630f1702c5SYu Xiangning void
sosdp_fini(struct sonode * so,struct cred * cr)11640f1702c5SYu Xiangning sosdp_fini(struct sonode *so, struct cred *cr)
11650f1702c5SYu Xiangning {
11660f1702c5SYu Xiangning dprint(3, ("sosdp_fini: so:%p so_proto_handle:%p", (void *)so,
11670f1702c5SYu Xiangning (void *)so->so_proto_handle));
11680f1702c5SYu Xiangning
11690f1702c5SYu Xiangning ASSERT(so->so_ops == &sosdp_sonodeops);
11700f1702c5SYu Xiangning
11710f1702c5SYu Xiangning if (so->so_proto_handle != NULL)
11720f1702c5SYu Xiangning sdp_close((struct sdp_conn_struct_t *)so->so_proto_handle);
11730f1702c5SYu Xiangning so->so_proto_handle = NULL;
11740f1702c5SYu Xiangning
11750f1702c5SYu Xiangning mutex_enter(&so->so_lock);
11760f1702c5SYu Xiangning
11772320a8c1SAnders Persson so_acceptq_flush(so, B_TRUE);
11780f1702c5SYu Xiangning
11790f1702c5SYu Xiangning mutex_exit(&so->so_lock);
11800f1702c5SYu Xiangning
11810f1702c5SYu Xiangning sonode_fini(so);
11820f1702c5SYu Xiangning }
11830f1702c5SYu Xiangning
118474e20cfeSnh /*
118574e20cfeSnh * Upcalls from SDP
118674e20cfeSnh */
118774e20cfeSnh
118874e20cfeSnh /*
118974e20cfeSnh * Incoming connection on listen socket.
119074e20cfeSnh */
119174e20cfeSnh static void *
sdp_sock_newconn(void * parenthandle,void * connind)119274e20cfeSnh sdp_sock_newconn(void *parenthandle, void *connind)
119374e20cfeSnh {
11940f1702c5SYu Xiangning struct sonode *lso = parenthandle;
119574e20cfeSnh struct sonode *nso;
119674e20cfeSnh int error;
119774e20cfeSnh
119874e20cfeSnh ASSERT(lso->so_state & SS_ACCEPTCONN);
11990f1702c5SYu Xiangning ASSERT(lso->so_proto_handle != NULL); /* closed conn */
120074e20cfeSnh ASSERT(lso->so_type == SOCK_STREAM);
120174e20cfeSnh
12020f1702c5SYu Xiangning dprint(3, ("sosdp_newconn A: so:%p so_proto_handle:%p", (void *)lso,
12030f1702c5SYu Xiangning (void *)lso->so_proto_handle));
120474e20cfeSnh
120574e20cfeSnh /*
120674e20cfeSnh * Check current # of queued conns against backlog
120774e20cfeSnh */
12080f1702c5SYu Xiangning if (lso->so_rcv_queued >= lso->so_backlog) {
120974e20cfeSnh return (NULL);
121074e20cfeSnh }
121174e20cfeSnh
12120f1702c5SYu Xiangning nso = socket_newconn(lso, connind, NULL, SOCKET_NOSLEEP, &error);
121374e20cfeSnh if (nso == NULL) {
121474e20cfeSnh eprintsoline(lso, error);
121574e20cfeSnh return (NULL);
121674e20cfeSnh }
121774e20cfeSnh
12188793b36bSNick Todd dprint(2, ("sdp_stream_newconn: new %p\n", (void *)nso));
121974e20cfeSnh
12200f1702c5SYu Xiangning (void) so_acceptq_enqueue(lso, nso);
122174e20cfeSnh
122274e20cfeSnh mutex_enter(&lso->so_lock);
12230f1702c5SYu Xiangning so_notify_newconn(lso);
12240f1702c5SYu Xiangning return (nso);
122574e20cfeSnh }
122674e20cfeSnh
122774e20cfeSnh /*
122874e20cfeSnh * For outgoing connections, the connection has been established.
122974e20cfeSnh */
123074e20cfeSnh static void
sdp_sock_connected(void * handle)123174e20cfeSnh sdp_sock_connected(void *handle)
123274e20cfeSnh {
12330f1702c5SYu Xiangning struct sonode *so = handle;
123474e20cfeSnh
123574e20cfeSnh ASSERT(so->so_type == SOCK_STREAM);
12360f1702c5SYu Xiangning dprint(3, ("sosdp_connected C: so:%p so_proto_handle:%p", (void *)so,
12370f1702c5SYu Xiangning (void *)so->so_proto_handle));
123874e20cfeSnh
123974e20cfeSnh mutex_enter(&so->so_lock);
12400f1702c5SYu Xiangning ASSERT(so->so_proto_handle); /* closed conn */
124174e20cfeSnh
124274e20cfeSnh ASSERT(!(so->so_state & SS_ACCEPTCONN));
124374e20cfeSnh soisconnected(so);
124474e20cfeSnh
12450f1702c5SYu Xiangning so_notify_connected(so);
124674e20cfeSnh }
124774e20cfeSnh
124874e20cfeSnh /*
124974e20cfeSnh * Connection got disconnected. Either with an error, or through
125074e20cfeSnh * normal handshake.
125174e20cfeSnh */
125274e20cfeSnh static void
sdp_sock_disconnected(void * handle,int error)125374e20cfeSnh sdp_sock_disconnected(void *handle, int error)
125474e20cfeSnh {
12550f1702c5SYu Xiangning struct sonode *so = handle;
125674e20cfeSnh
125774e20cfeSnh ASSERT(so->so_type == SOCK_STREAM);
12580f1702c5SYu Xiangning dprint(2, ("sosdp_disconnected C: so:%p so_proto_handle:%p error:%d",
12590f1702c5SYu Xiangning (void *)so, (void *)so->so_proto_handle, error));
126074e20cfeSnh
126174e20cfeSnh mutex_enter(&so->so_lock);
12620f1702c5SYu Xiangning ASSERT(so->so_proto_handle != NULL); /* closed conn */
126374e20cfeSnh
126474e20cfeSnh soisdisconnected(so, error);
12653e95bd4aSAnders Persson so_notify_disconnected(so, B_FALSE, error);
126674e20cfeSnh }
126774e20cfeSnh
126874e20cfeSnh /*
126974e20cfeSnh * Incoming data.
127074e20cfeSnh */
127174e20cfeSnh /*ARGSUSED*/
127274e20cfeSnh static int
sdp_sock_recv(void * handle,mblk_t * mp,int flags)127374e20cfeSnh sdp_sock_recv(void *handle, mblk_t *mp, int flags)
127474e20cfeSnh {
12750f1702c5SYu Xiangning struct sonode *so = handle;
127674e20cfeSnh
127774e20cfeSnh ASSERT(so->so_type == SOCK_STREAM);
127874e20cfeSnh
127974e20cfeSnh mutex_enter(&so->so_lock);
12800f1702c5SYu Xiangning so_notify_data(so, 0);
128174e20cfeSnh
128274e20cfeSnh return (so->so_rcvbuf);
128374e20cfeSnh }
128474e20cfeSnh
128574e20cfeSnh /*
128674e20cfeSnh * TX queued data got acknowledged.
128774e20cfeSnh */
128874e20cfeSnh static void
sdp_sock_xmitted(void * handle,int writeable)128974e20cfeSnh sdp_sock_xmitted(void *handle, int writeable)
129074e20cfeSnh {
12910f1702c5SYu Xiangning struct sonode *so = handle;
129274e20cfeSnh
12930f1702c5SYu Xiangning dprint(4, ("sosdp_sock_xmitted: so:%p so_proto_handle:%p txq:%d",
12940f1702c5SYu Xiangning (void *)so, (void *)so->so_proto_handle, writeable));
129574e20cfeSnh mutex_enter(&so->so_lock);
12960f1702c5SYu Xiangning ASSERT(so->so_proto_handle != NULL); /* closed conn */
129774e20cfeSnh
129874e20cfeSnh
129974e20cfeSnh /*
130074e20cfeSnh * Only do pollwakeup if the amount of queued data is less than
130174e20cfeSnh * watermark.
130274e20cfeSnh */
130374e20cfeSnh if (!writeable) {
13040f1702c5SYu Xiangning so_notify_writable(so);
130574e20cfeSnh } else {
130674e20cfeSnh mutex_exit(&so->so_lock);
130774e20cfeSnh }
130874e20cfeSnh }
130974e20cfeSnh
131074e20cfeSnh
131174e20cfeSnh /*
131274e20cfeSnh * SDP notifies socket for presence of urgent data.
131374e20cfeSnh */
131474e20cfeSnh static void
sdp_sock_urgdata(void * handle)131574e20cfeSnh sdp_sock_urgdata(void *handle)
131674e20cfeSnh {
13170f1702c5SYu Xiangning struct sonode *so = handle;
131874e20cfeSnh
13190f1702c5SYu Xiangning ASSERT(so->so_type == SOCK_STREAM);
132074e20cfeSnh
13210f1702c5SYu Xiangning mutex_enter(&so->so_lock);
132274e20cfeSnh
13230f1702c5SYu Xiangning ASSERT(so->so_proto_handle != NULL); /* closed conn */
13240f1702c5SYu Xiangning so_notify_oobsig(so);
132574e20cfeSnh }
132674e20cfeSnh
132774e20cfeSnh /*
132874e20cfeSnh * SDP notifies socket about receiving of conn close request from peer side.
132974e20cfeSnh */
133074e20cfeSnh static void
sdp_sock_ordrel(void * handle)133174e20cfeSnh sdp_sock_ordrel(void *handle)
133274e20cfeSnh {
13330f1702c5SYu Xiangning struct sonode *so = handle;
13340f1702c5SYu Xiangning
13350f1702c5SYu Xiangning ASSERT(so->so_type == SOCK_STREAM);
13360f1702c5SYu Xiangning
13370f1702c5SYu Xiangning dprint(4, ("sdp_sock_ordrel : so:%p, so_proto_handle:%p",
13380f1702c5SYu Xiangning (void *)so, (void *)so->so_proto_handle));
13390f1702c5SYu Xiangning mutex_enter(&so->so_lock);
13400f1702c5SYu Xiangning socantrcvmore(so);
13410f1702c5SYu Xiangning so_notify_eof(so);
134274e20cfeSnh }
134374e20cfeSnh
134474e20cfeSnh static void
sdp_sock_connfail(void * handle,int error)134574e20cfeSnh sdp_sock_connfail(void *handle, int error)
134674e20cfeSnh {
13470f1702c5SYu Xiangning struct sonode *so = handle;
134874e20cfeSnh
13490f1702c5SYu Xiangning dprint(3, ("sosdp_conn Failed: so:%p so_proto_handle:%p", (void *)so,
13500f1702c5SYu Xiangning (void *)so->so_proto_handle));
135174e20cfeSnh mutex_enter(&so->so_lock);
13520f1702c5SYu Xiangning ASSERT(so->so_proto_handle != NULL); /* closed conn */
135374e20cfeSnh so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
135474e20cfeSnh so->so_error = (ushort_t)error;
135574e20cfeSnh mutex_exit(&so->so_lock);
135674e20cfeSnh cv_broadcast(&so->so_state_cv);
135774e20cfeSnh }
1358