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