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