1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26#include <sys/types.h>
27#include <sys/t_lock.h>
28#include <sys/param.h>
29#include <sys/systm.h>
30#include <sys/buf.h>
31#include <sys/vfs.h>
32#include <sys/vnode.h>
33#include <sys/debug.h>
34#include <sys/errno.h>
35#include <sys/stropts.h>
36#include <sys/cmn_err.h>
37#include <sys/sysmacros.h>
38#include <sys/policy.h>
39
40#include <sys/filio.h>
41#include <sys/sockio.h>
42
43#include <sys/project.h>
44#include <sys/tihdr.h>
45#include <sys/strsubr.h>
46
47#include <sys/socket.h>
48#include <sys/socketvar.h>
49#include <sys/strsun.h>
50
51#include <sys/tsol/label.h>
52
53#include <inet/sdp_itf.h>
54#include "socksdp.h"
55#include <fs/sockfs/sockcommon.h>
56
57/*
58 * SDP sockfs sonode operations
59 */
60static int sosdp_init(struct sonode *, struct sonode *, struct cred *, int);
61static int sosdp_accept(struct sonode *, int, struct cred *, struct sonode **);
62static int sosdp_bind(struct sonode *, struct sockaddr *, socklen_t, int,
63    struct cred *);
64static int sosdp_listen(struct sonode *, int, struct cred *);
65static int sosdp_connect(struct sonode *, struct sockaddr *, socklen_t,
66    int, int, struct cred *);
67static int sosdp_recvmsg(struct sonode *, struct nmsghdr *, struct uio *,
68    struct cred *);
69static int sosdp_sendmsg(struct sonode *, struct nmsghdr *, struct uio *,
70    struct cred *);
71static int sosdp_getpeername(struct sonode *, struct sockaddr *, socklen_t *,
72    boolean_t, struct cred *);
73static int sosdp_getsockname(struct sonode *, struct sockaddr *, socklen_t *,
74    struct cred *);
75static int sosdp_shutdown(struct sonode *, int, struct cred *);
76static int sosdp_getsockopt(struct sonode *, int, int, void *, socklen_t *,
77    int, struct cred *);
78static int sosdp_setsockopt(struct sonode *, int, int, const void *,
79    socklen_t, struct cred *);
80static int sosdp_ioctl(struct sonode *, int, intptr_t, int, struct cred *,
81    int32_t *);
82static int sosdp_poll(struct sonode *, short, int, short *,
83    struct pollhead **);
84static int sosdp_close(struct sonode *, int, struct cred *);
85void sosdp_fini(struct sonode *, struct cred *);
86
87
88/*
89 * Socket upcalls
90 */
91static void *sdp_sock_newconn(void *parenthandle, void *connind);
92static void sdp_sock_connected(void *handle);
93static void sdp_sock_disconnected(void *handle, int error);
94static void sdp_sock_connfail(void *handle, int error);
95static int sdp_sock_recv(void *handle, mblk_t *mp, int flags);
96static void sdp_sock_xmitted(void *handle, int txqueued);
97static void sdp_sock_urgdata(void *handle);
98static void sdp_sock_ordrel(void *handle);
99
100sonodeops_t sosdp_sonodeops = {
101	sosdp_init,			/* sop_init	*/
102	sosdp_accept,			/* sop_accept	*/
103	sosdp_bind,			/* sop_bind	*/
104	sosdp_listen,			/* sop_listen	*/
105	sosdp_connect,			/* sop_connect	*/
106	sosdp_recvmsg,			/* sop_recvmsg	*/
107	sosdp_sendmsg,			/* sop_sendmsg	*/
108	so_sendmblk_notsupp,		/* sop_sendmblk */
109	sosdp_getpeername,		/* sop_getpeername */
110	sosdp_getsockname,		/* sop_getsockname */
111	sosdp_shutdown,			/* sop_shutdown */
112	sosdp_getsockopt,		/* sop_getsockopt */
113	sosdp_setsockopt,		/* sop_setsockopt */
114	sosdp_ioctl,			/* sop_ioctl	*/
115	sosdp_poll,			/* sop_poll	*/
116	sosdp_close,			/* sop_close	*/
117};
118
119sdp_upcalls_t sosdp_sock_upcalls = {
120	sdp_sock_newconn,
121	sdp_sock_connected,
122	sdp_sock_disconnected,
123	sdp_sock_connfail,
124	sdp_sock_recv,
125	sdp_sock_xmitted,
126	sdp_sock_urgdata,
127	sdp_sock_ordrel,
128};
129
130/* ARGSUSED */
131static int
132sosdp_init(struct sonode *so, struct sonode *pso, struct cred *cr, int flags)
133{
134	int error = 0;
135	sdp_sockbuf_limits_t sbl;
136	sdp_upcalls_t *upcalls;
137
138	if (pso != NULL) {
139		/* passive open, just inherit settings from parent */
140
141		mutex_enter(&so->so_lock);
142
143		so->so_state |= (SS_ISBOUND | SS_ISCONNECTED |
144		    (pso->so_state & SS_ASYNC));
145		sosdp_so_inherit(pso, so);
146		so->so_proto_props = pso->so_proto_props;
147
148		mutex_exit(&so->so_lock);
149
150		return (0);
151	}
152
153	if ((error = secpolicy_basic_net_access(cr)) != 0)
154		return (error);
155
156	upcalls = &sosdp_sock_upcalls;
157
158	so->so_proto_handle = (sock_lower_handle_t)sdp_create(so, NULL,
159	    so->so_family, SDP_CAN_BLOCK, upcalls, &sbl, cr, &error);
160	if (so->so_proto_handle == NULL)
161		return (ENOMEM);
162
163	so->so_rcvbuf = sbl.sbl_rxbuf;
164	so->so_rcvlowat = sbl.sbl_rxlowat;
165	so->so_sndbuf = sbl.sbl_txbuf;
166	so->so_sndlowat = sbl.sbl_txlowat;
167
168	return (error);
169}
170
171/*
172 * Accept incoming connection.
173 */
174/* ARGSUSED */
175static int
176sosdp_accept(struct sonode *lso, int fflag, struct cred *cr,
177    struct sonode **nsop)
178{
179	int error = 0;
180	struct sonode *nso;
181
182	dprint(3, ("sosdp_accept: so:%p so_proto_handle:%p", (void *)lso,
183	    (void *)lso->so_proto_handle));
184
185	if (!(lso->so_state & SS_ACCEPTCONN)) {
186		/*
187		 * Not a listen socket.
188		 */
189		eprintsoline(lso, EINVAL);
190		return (EINVAL);
191	}
192	/*
193	 * Returns right away if socket is nonblocking.
194	 */
195	error = so_acceptq_dequeue(lso, (fflag & (FNONBLOCK|FNDELAY)), &nso);
196	if (error != 0) {
197		eprintsoline(lso, error);
198		dprint(4, ("sosdp_accept: failed %d:lso:%p so_proto_handle:%p",
199		    error, (void *)lso, (void *)lso->so_proto_handle));
200		return (error);
201	}
202
203	dprint(2, ("sosdp_accept: new %p\n", (void *)nso));
204	*nsop = nso;
205
206	return (0);
207}
208
209/*
210 * Bind local endpoint.
211 */
212/* ARGSUSED */
213int
214sosdp_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
215    int flags, struct cred *cr)
216{
217	int	error = 0;
218
219	if (!(flags & _SOBIND_LOCK_HELD)) {
220		mutex_enter(&so->so_lock);
221		so_lock_single(so);	/* Set SOLOCKED */
222	} else {
223		ASSERT(MUTEX_HELD(&so->so_lock));
224		ASSERT(so->so_flag & SOLOCKED);
225	}
226
227	if ((so->so_state & SS_ISBOUND) || name == NULL || namelen == 0) {
228		/*
229		 * Multiple binds not allowed for any SDP socket.
230		 * Also binding with null address is not supported.
231		 */
232		error = EINVAL;
233		eprintsoline(so, error);
234		goto done;
235	}
236
237	/*
238	 * X/Open requires this check
239	 */
240	if (so->so_state & SS_CANTSENDMORE) {
241		error = EINVAL;
242		goto done;
243	}
244
245	/*
246	 * Protocol module does address family checks
247	 */
248	mutex_exit(&so->so_lock);
249
250	error = sdp_bind((struct sdp_conn_struct_t *)so->so_proto_handle,
251	    name, namelen);
252
253	mutex_enter(&so->so_lock);
254
255	if (error == 0) {
256		so->so_state |= SS_ISBOUND;
257	} else {
258		eprintsoline(so, error);
259	}
260done:
261	if (!(flags & _SOBIND_LOCK_HELD)) {
262		so_unlock_single(so, SOLOCKED);
263		mutex_exit(&so->so_lock);
264	} else {
265		/* If the caller held the lock don't release it here */
266		ASSERT(MUTEX_HELD(&so->so_lock));
267		ASSERT(so->so_flag & SOLOCKED);
268	}
269	return (error);
270}
271
272/*
273 * Turn socket into a listen socket.
274 */
275/* ARGSUSED */
276static int
277sosdp_listen(struct sonode *so, int backlog, struct cred *cr)
278{
279	int error = 0;
280
281	mutex_enter(&so->so_lock);
282	so_lock_single(so);
283
284	/*
285	 * If this socket is trying to do connect, or if it has
286	 * been connected, disallow.
287	 */
288	if (so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED |
289	    SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE)) {
290		error = EINVAL;
291		eprintsoline(so, EINVAL);
292		goto done;
293	}
294	/*
295	 * If listen() is only called to change backlog, we don't
296	 * need to notify protocol module.
297	 */
298	if (so->so_state & SS_ACCEPTCONN) {
299		so->so_backlog = backlog;
300		goto done;
301	}
302
303	mutex_exit(&so->so_lock);
304
305	error = sdp_listen((struct sdp_conn_struct_t *)so->so_proto_handle,
306	    backlog);
307
308	mutex_enter(&so->so_lock);
309	if (error == 0) {
310		so->so_state |= (SS_ACCEPTCONN | SS_ISBOUND);
311		so->so_backlog = backlog;
312	} else {
313		eprintsoline(so, error);
314	}
315done:
316	so_unlock_single(so, SOLOCKED);
317	mutex_exit(&so->so_lock);
318
319	return (error);
320}
321
322/*
323 * Active open.
324 */
325/*ARGSUSED*/
326static int
327sosdp_connect(struct sonode *so, struct sockaddr *name,
328    socklen_t namelen, int fflag, int flags, struct cred *cr)
329{
330	int error = 0;
331
332	mutex_enter(&so->so_lock);
333	so_lock_single(so);
334
335	/*
336	 * Can't connect() after listen(), or if the socket is already
337	 * connected.
338	 */
339	if (so->so_state & (SS_ACCEPTCONN|SS_ISCONNECTED|SS_ISCONNECTING)) {
340		if (so->so_state & SS_ISCONNECTED) {
341			error = EISCONN;
342		} else if (so->so_state & SS_ISCONNECTING) {
343			error = EALREADY;
344		} else {
345			error = EOPNOTSUPP;
346		}
347		eprintsoline(so, error);
348		goto done;
349	}
350
351	/*
352	 * check for failure of an earlier call
353	 */
354	if (so->so_error != 0) {
355		error = sogeterr(so, B_TRUE);
356		eprintsoline(so, error);
357		goto done;
358	}
359
360	/*
361	 * Connection is closing, or closed, don't allow reconnect.
362	 * TCP allows this to proceed, but the socket remains unwriteable.
363	 * BSD returns EINVAL.
364	 */
365	if (so->so_state & (SS_ISDISCONNECTING|SS_CANTRCVMORE|
366	    SS_CANTSENDMORE)) {
367		error = EINVAL;
368		eprintsoline(so, error);
369		goto done;
370	}
371	if (name == NULL || namelen == 0) {
372		eprintsoline(so, EINVAL);
373		goto done;
374	}
375	soisconnecting(so);
376	mutex_exit(&so->so_lock);
377
378	error = sdp_connect((struct sdp_conn_struct_t *)so->so_proto_handle,
379	    name, namelen);
380
381	mutex_enter(&so->so_lock);
382	if (error == 0) {
383		/*
384		 * Allow other threads to access the socket
385		 */
386		error = sowaitconnected(so, fflag, 0);
387		dprint(4,
388		    ("sosdp_connect: wait on so:%p "
389		    "so_proto_handle:%p failed:%d",
390		    (void *)so,	(void *)so->so_proto_handle, error));
391	}
392
393	switch (error) {
394	case 0:
395	case EINPROGRESS:
396	case EALREADY:
397	case EINTR:
398		/* Non-fatal errors */
399		so->so_state |= SS_ISBOUND;
400		break;
401	default:
402		/* clear SS_ISCONNECTING in case it was set */
403		so->so_state &= ~SS_ISCONNECTING;
404		break;
405	}
406done:
407	so_unlock_single(so, SOLOCKED);
408	mutex_exit(&so->so_lock);
409	return (error);
410}
411
412/*
413 * Receive data.
414 */
415/* ARGSUSED */
416int
417sosdp_recvmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
418    struct cred *cr)
419{
420	int flags, error = 0;
421	int size;
422
423	flags = msg->msg_flags;
424	msg->msg_flags = 0;
425
426
427	if (!(so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|
428	    SS_CANTRCVMORE))) {
429		return (ENOTCONN);
430	}
431
432	/*
433	 * flag possibilities:
434	 *
435	 * MSG_PEEK	Don't consume data
436	 * MSG_WAITALL	Wait for full quantity of data (ignored if MSG_PEEK)
437	 * MSG_DONTWAIT Non-blocking (same as FNDELAY | FNONBLOCK)
438	 *
439	 * MSG_WAITALL can return less than the full buffer if either
440	 *
441	 * 1. we would block and we are non-blocking
442	 * 2. a full message cannot be delivered
443	 *
444	 */
445
446	mutex_enter(&so->so_lock);
447
448	/*
449	 * Allow just one reader at a time.
450	 */
451	error = so_lock_read_intr(so,
452	    uiop->uio_fmode | ((flags & MSG_DONTWAIT) ? FNONBLOCK : 0));
453	if (error != 0) {
454		mutex_exit(&so->so_lock);
455		return (error);
456	}
457	size = uiop->uio_resid;
458	mutex_exit(&so->so_lock);
459
460	if (!(so->so_state & SS_CANTRCVMORE)) {
461		if (uiop->uio_fmode & (FNDELAY|FNONBLOCK)) {
462			flags |= MSG_DONTWAIT;
463		}
464		error = sdp_recv(
465		    (struct sdp_conn_struct_t *)so->so_proto_handle, msg,
466		    size, flags, uiop);
467	} else {
468		msg->msg_controllen = 0;
469		msg->msg_namelen = 0;
470	}
471done:
472	mutex_enter(&so->so_lock);
473	so_unlock_read(so);
474	mutex_exit(&so->so_lock);
475	return (error);
476}
477
478/*
479 * Send message.
480 */
481/* ARGSUSED */
482static int
483sosdp_sendmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
484    struct cred *cr)
485{
486	int flags;
487	ssize_t count;
488	int error;
489
490	ASSERT(so->so_type == SOCK_STREAM);
491
492	dprint(4, ("sosdp_sendmsg: so:%p so_proto_handle:%p",
493	    (void *)so, (void *)so->so_proto_handle));
494
495	flags = msg->msg_flags;
496
497	if (msg->msg_controllen != 0) {
498		return (EOPNOTSUPP);
499	}
500
501	mutex_enter(&so->so_lock);
502	if (so->so_state & SS_CANTSENDMORE) {
503		mutex_exit(&so->so_lock);
504		return (EPIPE);
505	}
506
507	if (so->so_error != 0) {
508		error = sogeterr(so, B_TRUE);
509		mutex_exit(&so->so_lock);
510		return (error);
511	}
512
513	if (uiop->uio_fmode & (FNDELAY|FNONBLOCK))
514		flags |= MSG_DONTWAIT;
515
516	count = uiop->uio_resid;
517
518	if (!(so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED))) {
519		dprint(4, ("sosdp_sendmsg: invalid state: <%x>",
520		    so->so_state));
521		mutex_exit(&so->so_lock);
522		return (ENOTCONN);
523	}
524
525	mutex_exit(&so->so_lock);
526	error = sdp_send((struct sdp_conn_struct_t *)so->so_proto_handle,
527	    msg, count, flags, uiop);
528
529	return (error);
530}
531
532/*
533 * Get address of remote node.
534 */
535/* ARGSUSED */
536static int
537sosdp_getpeername(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
538    boolean_t accept, struct cred *cr)
539{
540
541	if (!accept && !(so->so_state & SS_ISCONNECTED)) {
542		return (ENOTCONN);
543	} else {
544		return (sdp_getpeername(
545		    (struct sdp_conn_struct_t *)so->so_proto_handle,
546		    addr, addrlen));
547	}
548}
549
550/*
551 * Get local address.
552 */
553/* ARGSUSED */
554static int
555sosdp_getsockname(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
556    struct cred *cr)
557{
558	mutex_enter(&so->so_lock);
559
560	if (!(so->so_state & SS_ISBOUND)) {
561		/*
562		 * Zero address, except for address family
563		 */
564		if (so->so_family == AF_INET || so->so_family == AF_INET6) {
565			bzero(addr, *addrlen);
566			*addrlen = (so->so_family == AF_INET6) ?
567			    sizeof (struct sockaddr_in6) :
568			    sizeof (struct sockaddr_in);
569			addr->sa_family = so->so_family;
570		}
571		mutex_exit(&so->so_lock);
572		return (0);
573	} else {
574		mutex_exit(&so->so_lock);
575		return (sdp_getsockname(
576		    (struct sdp_conn_struct_t *)so->so_proto_handle,
577		    addr, addrlen));
578	}
579}
580
581/*
582 * Called from shutdown().
583 */
584/* ARGSUSED */
585static int
586sosdp_shutdown(struct sonode *so, int how, struct cred *cr)
587{
588	uint_t state_change;
589	int error = 0;
590
591	mutex_enter(&so->so_lock);
592	so_lock_single(so);
593	/*
594	 * Record the current state and then perform any state changes.
595	 * Then use the difference between the old and new states to
596	 * determine which needs to be done.
597	 */
598	state_change = so->so_state;
599	if (!(state_change & SS_ISCONNECTED)) {
600		error = ENOTCONN;
601		goto done;
602	}
603
604	switch (how) {
605	case SHUT_RD:
606		socantrcvmore(so);
607		break;
608	case SHUT_WR:
609		socantsendmore(so);
610		break;
611	case SHUT_RDWR:
612		socantsendmore(so);
613		socantrcvmore(so);
614		break;
615	default:
616		error = EINVAL;
617		goto done;
618	}
619
620	state_change = so->so_state & ~state_change;
621
622	if (state_change & SS_CANTSENDMORE) {
623		so->so_state |= SS_ISDISCONNECTING;
624	}
625	so_notify_shutdown(so);
626
627	if (state_change & SS_CANTSENDMORE) {
628		error = sdp_shutdown(
629		    (struct sdp_conn_struct_t *)so->so_proto_handle, how);
630	}
631
632	mutex_enter(&so->so_lock);
633done:
634	so_unlock_single(so, SOLOCKED);
635	mutex_exit(&so->so_lock);
636
637	/*
638	 * HACK: sdp_disconnect() may return EWOULDBLOCK.  But this error is
639	 * not documented in standard socket API.  Catch it here.
640	 */
641	if (error == EWOULDBLOCK)
642		error = 0;
643	return (error);
644}
645
646/*
647 * Get socket options.
648 */
649/*ARGSUSED*/
650static int
651sosdp_getsockopt(struct sonode *so, int level, int option_name,
652    void *optval, socklen_t *optlenp, int flags, struct cred *cr)
653{
654	int error = 0;
655	void *option = NULL;
656	socklen_t maxlen = *optlenp, len, optlen;
657	uint32_t value;
658	uint8_t buffer[4];
659	void *optbuf = &buffer;
660
661
662	mutex_enter(&so->so_lock);
663
664	if (level == SOL_SOCKET) {
665		switch (option_name) {
666		case SO_TYPE:
667		case SO_ERROR:
668		case SO_DEBUG:
669		case SO_ACCEPTCONN:
670		case SO_REUSEADDR:
671		case SO_KEEPALIVE:
672		case SO_DONTROUTE:
673		case SO_BROADCAST:
674		case SO_USELOOPBACK:
675		case SO_OOBINLINE:
676		case SO_SNDBUF:
677		case SO_RCVBUF:
678		case SO_SNDLOWAT:
679		case SO_RCVLOWAT:
680		case SO_DGRAM_ERRIND:
681			if (maxlen < (t_uscalar_t)sizeof (int32_t)) {
682				error = EINVAL;
683				eprintsoline(so, error);
684				goto done;
685			}
686			break;
687		case SO_LINGER:
688			if (maxlen < (t_uscalar_t)sizeof (struct linger)) {
689				error = EINVAL;
690				eprintsoline(so, error);
691				goto done;
692			}
693			break;
694		}
695		len = (t_uscalar_t)sizeof (uint32_t);   /* Default */
696		option = &value;
697
698		switch (option_name) {
699		case SO_TYPE:
700			value = so->so_type;
701			goto copyout;
702
703		case SO_ERROR:
704			value = sogeterr(so, B_TRUE);
705			goto copyout;
706
707		case SO_ACCEPTCONN:
708			value = (so->so_state & SS_ACCEPTCONN) ?
709			    SO_ACCEPTCONN : 0;
710			goto copyout;
711
712		case SO_DEBUG:
713		case SO_REUSEADDR:
714		case SO_KEEPALIVE:
715		case SO_DONTROUTE:
716		case SO_BROADCAST:
717		case SO_USELOOPBACK:
718		case SO_OOBINLINE:
719		case SO_DGRAM_ERRIND:
720			value = (so->so_options & option_name);
721			goto copyout;
722
723			/*
724			 * The following options are only returned by sockfs
725			 * when sdp_get_opt() fails.
726			 */
727
728		case SO_LINGER:
729			option = &so->so_linger;
730			len = (t_uscalar_t)sizeof (struct linger);
731			break;
732		case SO_SNDBUF:
733			value = so->so_sndbuf;
734			len = (t_uscalar_t)sizeof (int);
735			goto copyout;
736
737		case SO_RCVBUF:
738			value = so->so_rcvbuf;
739			len = (t_uscalar_t)sizeof (int);
740			goto copyout;
741
742		case SO_SNDLOWAT:
743			value = so->so_sndlowat;
744			len = (t_uscalar_t)sizeof (int);
745			goto copyout;
746
747		case SO_RCVLOWAT:
748			value = so->so_rcvlowat;
749			len = (t_uscalar_t)sizeof (int);
750			goto copyout;
751
752		default:
753			option = NULL;
754			break;
755		}
756	}
757	if (maxlen > sizeof (buffer)) {
758		optbuf = kmem_alloc(maxlen, KM_SLEEP);
759	}
760	optlen = maxlen;
761	mutex_exit(&so->so_lock);
762	error = sdp_get_opt((struct sdp_conn_struct_t *)so->so_proto_handle,
763	    level, option_name, optbuf, &optlen);
764	mutex_enter(&so->so_lock);
765	ASSERT(optlen <= maxlen);
766	if (error != 0) {
767		if (option == NULL) {
768			/* We have no fallback value */
769			eprintsoline(so, error);
770			goto free;
771		}
772		error = 0;
773		goto copyout;
774	}
775
776	option = optbuf;
777	len = optlen;
778
779copyout:
780	len = MIN(len, maxlen);
781	bcopy(option, optval, len);
782	*optlenp = len;
783
784free:
785	if (optbuf != &buffer) {
786		kmem_free(optbuf, maxlen);
787	}
788done:
789	mutex_exit(&so->so_lock);
790	return (error);
791}
792
793/*
794 * Set socket options
795 */
796/* ARGSUSED */
797static int
798sosdp_setsockopt(struct sonode *so, int level, int option_name,
799    const void *optval, t_uscalar_t optlen, struct cred *cr)
800{
801	void *conn = NULL;
802	int error = 0;
803
804	if (so->so_state & SS_CANTSENDMORE) {
805		return (EINVAL);
806	}
807
808	mutex_enter(&so->so_lock);
809	so_lock_single(so);
810
811	if (so->so_type == SOCK_STREAM) {
812		conn = (void *)so->so_proto_handle;
813	}
814
815	dprint(2, ("sosdp_setsockopt (%d) - conn %p %d %d \n",
816	    so->so_type, conn, level, option_name));
817
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);
823	}
824
825	/*
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.
830	 */
831	if (level == SOL_SOCKET) {
832		boolean_t handled = B_FALSE;
833
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;
852			}
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;
861			}
862			ASSERT(optval);
863			handled = B_TRUE;
864			break;
865		}
866
867#define	intvalue (*(int32_t *)optval)
868
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;
878
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;
886			}
887			break;
888		}
889
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;
908			}
909			break;
910
911		case SO_SNDBUF:
912			so->so_sndbuf = intvalue;
913			if (so->so_sndlowat > so->so_sndbuf) {
914				so->so_sndlowat = so->so_sndbuf;
915			}
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;
921			}
922			break;
923		case SO_SNDLOWAT:
924			if (so->so_sndlowat > so->so_sndbuf) {
925				so->so_sndlowat = so->so_sndbuf;
926			}
927			break;
928		case SO_RCVLOWAT:
929			if (so->so_rcvlowat > so->so_rcvbuf) {
930				so->so_rcvlowat = so->so_rcvbuf;
931			}
932			break;
933		}
934#undef  intvalue
935
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;
943			}
944		}
945	}
946
947done:
948	so_unlock_single(so, SOLOCKED);
949	mutex_exit(&so->so_lock);
950
951	return (error);
952}
953
954/* ARGSUSED */
955static int
956sosdp_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode,
957    struct cred *cr, int32_t *rvalp)
958{
959	int32_t value;
960	int error, intval;
961	pid_t pid;
962
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);
969		}
970		mutex_enter(&so->so_lock);
971		if (value != 0) {
972			so->so_state |= SS_NDELAY;
973		} else {
974			so->so_state &= ~SS_NDELAY;
975		}
976		mutex_exit(&so->so_lock);
977		return (0);
978
979	case FIOASYNC:
980		if (so_copyin((void *)arg, &value, sizeof (int32_t),
981		    (mode & (int)FKIOCTL))) {
982			return (EFAULT);
983		}
984		mutex_enter(&so->so_lock);
985
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;
992		}
993		mutex_exit(&so->so_lock);
994		return (0);
995
996	case SIOCSPGRP:
997	case FIOSETOWN:
998		if (so_copyin((void *)arg, &pid, sizeof (pid_t),
999		    (mode & (int)FKIOCTL))) {
1000			return (EFAULT);
1001		}
1002		mutex_enter(&so->so_lock);
1003
1004		error = (pid != so->so_pgrp) ? socket_chgpgrp(so, pid) : 0;
1005		mutex_exit(&so->so_lock);
1006		return (error);
1007
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);
1014
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);
1024
1025
1026	case SIOCSENABLESDP: {
1027		int32_t enable;
1028
1029		/*
1030		 * System wide enable SDP
1031		 */
1032
1033		if (so_copyin((void *)arg, &enable, sizeof (int32_t),
1034		    mode & (int)FKIOCTL))
1035			return (EFAULT);
1036
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);
1044	}
1045		/* from strioctl */
1046	case FIONREAD:
1047		/*
1048		 * Return number of bytes of data in all data messages
1049		 * in queue in "arg".
1050		 * For stream socket, amount of available data.
1051		 */
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);
1060		}
1061		if (so_copyout(&intval, (void *)arg, sizeof (intval),
1062		    (mode & (int)FKIOCTL)))
1063			return (EFAULT);
1064		return (0);
1065	default:
1066		return (EINVAL);
1067	}
1068}
1069
1070/*
1071 * Check socktpi_poll() on why so_lock is not held in this function.
1072 */
1073static int
1074sosdp_poll(struct sonode *so, short events, int anyyet, short *reventsp,
1075    struct pollhead **phpp)
1076{
1077	short origevents = events;
1078	int so_state;
1079
1080	so_state = so->so_state;
1081
1082	ASSERT(so->so_version != SOV_STREAM);
1083
1084	if (!(so_state & SS_ISCONNECTED) && (so->so_type == SOCK_STREAM)) {
1085		/*
1086		 * Not connected yet - turn off write side events
1087		 */
1088		events &= ~(POLLOUT|POLLWRBAND);
1089	}
1090
1091	/*
1092	 * Check for errors
1093	 */
1094	if (so->so_error != 0 &&
1095	    ((POLLIN|POLLRDNORM|POLLOUT) & origevents)  != 0) {
1096		*reventsp = (POLLIN|POLLRDNORM|POLLOUT) & origevents;
1097		return (0);
1098	}
1099
1100	*reventsp = 0;
1101
1102	/*
1103	 * Don't mark socket as writable until TX queued data is
1104	 * below watermark.
1105	 */
1106	if (so->so_type == SOCK_STREAM) {
1107		if (sdp_polldata(
1108		    (struct sdp_conn_struct_t *)so->so_proto_handle,
1109		    SDP_XMIT)) {
1110			*reventsp |= POLLOUT & events;
1111		}
1112	} else {
1113		*reventsp = 0;
1114		goto done;
1115	}
1116
1117	if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
1118	    SDP_READ)) {
1119		*reventsp |= (POLLIN|POLLRDNORM) & events;
1120	}
1121
1122	if ((so_state & SS_CANTRCVMORE) || (so->so_acceptq_len > 0)) {
1123		*reventsp |= (POLLIN|POLLRDNORM) & events;
1124	}
1125
1126done:
1127	if (!*reventsp && !anyyet) {
1128		*phpp = &so->so_poll_list;
1129	}
1130
1131	return (0);
1132}
1133
1134/* ARGSUSED */
1135static int
1136sosdp_close(struct sonode *so, int flag, struct cred *cr)
1137{
1138	int error = 0;
1139
1140	mutex_enter(&so->so_lock);
1141	so_lock_single(so);
1142	/*
1143	 * Need to set flags as there might be ops in progress on
1144	 * this socket.
1145	 *
1146	 * If socket already disconnected/disconnecting,
1147	 * don't send signal (again).
1148	 */
1149	soisdisconnected(so, 0);
1150	mutex_exit(&so->so_lock);
1151
1152	/*
1153	 * Initiate connection shutdown.
1154	 */
1155	error = sdp_disconnect((struct sdp_conn_struct_t *)so->so_proto_handle,
1156	    flag);
1157
1158	mutex_enter(&so->so_lock);
1159	so_unlock_single(so, SOLOCKED);
1160	so_notify_disconnected(so, B_FALSE, error);
1161
1162	return (error);
1163}
1164
1165/* ARGSUSED */
1166void
1167sosdp_fini(struct sonode *so, struct cred *cr)
1168{
1169	dprint(3, ("sosdp_fini: so:%p so_proto_handle:%p", (void *)so,
1170	    (void *)so->so_proto_handle));
1171
1172	ASSERT(so->so_ops == &sosdp_sonodeops);
1173
1174	if (so->so_proto_handle != NULL)
1175		sdp_close((struct sdp_conn_struct_t *)so->so_proto_handle);
1176	so->so_proto_handle = NULL;
1177
1178	mutex_enter(&so->so_lock);
1179
1180	so_acceptq_flush(so, B_TRUE);
1181
1182	mutex_exit(&so->so_lock);
1183
1184	sonode_fini(so);
1185}
1186
1187/*
1188 * Upcalls from SDP
1189 */
1190
1191/*
1192 * Incoming connection on listen socket.
1193 */
1194static void *
1195sdp_sock_newconn(void *parenthandle, void *connind)
1196{
1197	struct sonode *lso = parenthandle;
1198	struct sonode *nso;
1199	int error;
1200
1201	ASSERT(lso->so_state & SS_ACCEPTCONN);
1202	ASSERT(lso->so_proto_handle != NULL); /* closed conn */
1203	ASSERT(lso->so_type == SOCK_STREAM);
1204
1205	dprint(3, ("sosdp_newconn A: so:%p so_proto_handle:%p", (void *)lso,
1206	    (void *)lso->so_proto_handle));
1207
1208	/*
1209	 * Check current # of queued conns against backlog
1210	 */
1211	if (lso->so_rcv_queued >= lso->so_backlog) {
1212		return (NULL);
1213	}
1214
1215	nso = socket_newconn(lso, connind, NULL, SOCKET_NOSLEEP, &error);
1216	if (nso == NULL) {
1217		eprintsoline(lso, error);
1218		return (NULL);
1219	}
1220
1221	dprint(2, ("sdp_stream_newconn: new %p\n", (void *)nso));
1222
1223	(void) so_acceptq_enqueue(lso, nso);
1224
1225	mutex_enter(&lso->so_lock);
1226	so_notify_newconn(lso);
1227	return (nso);
1228}
1229
1230/*
1231 * For outgoing connections, the connection has been established.
1232 */
1233static void
1234sdp_sock_connected(void *handle)
1235{
1236	struct sonode *so = handle;
1237
1238	ASSERT(so->so_type == SOCK_STREAM);
1239	dprint(3, ("sosdp_connected C: so:%p so_proto_handle:%p", (void *)so,
1240	    (void *)so->so_proto_handle));
1241
1242	mutex_enter(&so->so_lock);
1243	ASSERT(so->so_proto_handle); /* closed conn */
1244
1245	ASSERT(!(so->so_state & SS_ACCEPTCONN));
1246	soisconnected(so);
1247
1248	so_notify_connected(so);
1249}
1250
1251/*
1252 * Connection got disconnected. Either with an error, or through
1253 * normal handshake.
1254 */
1255static void
1256sdp_sock_disconnected(void *handle, int error)
1257{
1258	struct sonode *so = handle;
1259
1260	ASSERT(so->so_type == SOCK_STREAM);
1261	dprint(2, ("sosdp_disconnected C: so:%p so_proto_handle:%p error:%d",
1262	    (void *)so, (void *)so->so_proto_handle, error));
1263
1264	mutex_enter(&so->so_lock);
1265	ASSERT(so->so_proto_handle != NULL); /* closed conn */
1266
1267	soisdisconnected(so, error);
1268	so_notify_disconnected(so, B_FALSE, error);
1269}
1270
1271/*
1272 * Incoming data.
1273 */
1274/*ARGSUSED*/
1275static int
1276sdp_sock_recv(void *handle, mblk_t *mp, int flags)
1277{
1278	struct sonode *so = handle;
1279
1280	ASSERT(so->so_type == SOCK_STREAM);
1281
1282	mutex_enter(&so->so_lock);
1283	so_notify_data(so, 0);
1284
1285	return (so->so_rcvbuf);
1286}
1287
1288/*
1289 * TX queued data got acknowledged.
1290 */
1291static void
1292sdp_sock_xmitted(void *handle, int writeable)
1293{
1294	struct sonode *so = handle;
1295
1296	dprint(4, ("sosdp_sock_xmitted: so:%p so_proto_handle:%p txq:%d",
1297	    (void *)so, (void *)so->so_proto_handle, writeable));
1298	mutex_enter(&so->so_lock);
1299	ASSERT(so->so_proto_handle != NULL); /* closed conn */
1300
1301
1302	/*
1303	 * Only do pollwakeup if the amount of queued data is less than
1304	 * watermark.
1305	 */
1306	if (!writeable) {
1307		so_notify_writable(so);
1308	} else {
1309		mutex_exit(&so->so_lock);
1310	}
1311}
1312
1313
1314/*
1315 * SDP notifies socket for presence of urgent data.
1316 */
1317static void
1318sdp_sock_urgdata(void *handle)
1319{
1320	struct sonode *so = handle;
1321
1322	ASSERT(so->so_type == SOCK_STREAM);
1323
1324	mutex_enter(&so->so_lock);
1325
1326	ASSERT(so->so_proto_handle != NULL); /* closed conn */
1327	so_notify_oobsig(so);
1328}
1329
1330/*
1331 * SDP notifies socket about receiving of conn close request from peer side.
1332 */
1333static void
1334sdp_sock_ordrel(void *handle)
1335{
1336	struct sonode *so = handle;
1337
1338	ASSERT(so->so_type == SOCK_STREAM);
1339
1340	dprint(4, ("sdp_sock_ordrel : so:%p, so_proto_handle:%p",
1341	    (void *)so, (void *)so->so_proto_handle));
1342	mutex_enter(&so->so_lock);
1343	socantrcvmore(so);
1344	so_notify_eof(so);
1345}
1346
1347static void
1348sdp_sock_connfail(void *handle, int error)
1349{
1350	struct sonode *so = handle;
1351
1352	dprint(3, ("sosdp_conn Failed: so:%p so_proto_handle:%p", (void *)so,
1353	    (void *)so->so_proto_handle));
1354	mutex_enter(&so->so_lock);
1355	ASSERT(so->so_proto_handle != NULL); /* closed conn */
1356	so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
1357	so->so_error = (ushort_t)error;
1358	mutex_exit(&so->so_lock);
1359	cv_broadcast(&so->so_state_cv);
1360}
1361