xref: /titanic_50/usr/src/uts/common/inet/sockmods/socksdp.c (revision 3e95bd4ab92abca814bd28e854607d1975c7dc88)
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  */
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 *, 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
sosdp_init(struct sonode * so,struct sonode * pso,struct cred * cr,int flags)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 	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 */
175 static int
sosdp_accept(struct sonode * lso,int fflag,struct cred * cr,struct sonode ** nsop)176 sosdp_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 */
213 int
sosdp_bind(struct sonode * so,struct sockaddr * name,socklen_t namelen,int flags,struct cred * cr)214 sosdp_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 	}
260 done:
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 */
276 static int
sosdp_listen(struct sonode * so,int backlog,struct cred * cr)277 sosdp_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 	}
315 done:
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*/
326 static int
sosdp_connect(struct sonode * so,struct sockaddr * name,socklen_t namelen,int fflag,int flags,struct cred * cr)327 sosdp_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 	}
406 done:
407 	so_unlock_single(so, SOLOCKED);
408 	mutex_exit(&so->so_lock);
409 	return (error);
410 }
411 
412 /*
413  * Receive data.
414  */
415 /* ARGSUSED */
416 int
sosdp_recvmsg(struct sonode * so,struct nmsghdr * msg,struct uio * uiop,struct cred * cr)417 sosdp_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 	}
471 done:
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 */
482 static int
sosdp_sendmsg(struct sonode * so,struct nmsghdr * msg,struct uio * uiop,struct cred * cr)483 sosdp_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 */
536 static int
sosdp_getpeername(struct sonode * so,struct sockaddr * addr,socklen_t * addrlen,boolean_t accept,struct cred * cr)537 sosdp_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 */
554 static int
sosdp_getsockname(struct sonode * so,struct sockaddr * addr,socklen_t * addrlen,struct cred * cr)555 sosdp_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 */
585 static int
sosdp_shutdown(struct sonode * so,int how,struct cred * cr)586 sosdp_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);
633 done:
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*/
650 static int
sosdp_getsockopt(struct sonode * so,int level,int option_name,void * optval,socklen_t * optlenp,int flags,struct cred * cr)651 sosdp_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 
779 copyout:
780 	len = MIN(len, maxlen);
781 	bcopy(option, optval, len);
782 	*optlenp = len;
783 
784 free:
785 	if (optbuf != &buffer) {
786 		kmem_free(optbuf, maxlen);
787 	}
788 done:
789 	mutex_exit(&so->so_lock);
790 	return (error);
791 }
792 
793 /*
794  * Set socket options
795  */
796 /* ARGSUSED */
797 static int
sosdp_setsockopt(struct sonode * so,int level,int option_name,const void * optval,t_uscalar_t optlen,struct cred * cr)798 sosdp_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 
947 done:
948 	so_unlock_single(so, SOLOCKED);
949 	mutex_exit(&so->so_lock);
950 
951 	return (error);
952 }
953 
954 /* ARGSUSED */
955 static int
sosdp_ioctl(struct sonode * so,int cmd,intptr_t arg,int mode,struct cred * cr,int32_t * rvalp)956 sosdp_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  */
1073 static int
sosdp_poll(struct sonode * so,short events,int anyyet,short * reventsp,struct pollhead ** phpp)1074 sosdp_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 
1126 done:
1127 	if (!*reventsp && !anyyet) {
1128 		*phpp = &so->so_poll_list;
1129 	}
1130 
1131 	return (0);
1132 }
1133 
1134 /* ARGSUSED */
1135 static int
sosdp_close(struct sonode * so,int flag,struct cred * cr)1136 sosdp_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 */
1166 void
sosdp_fini(struct sonode * so,struct cred * cr)1167 sosdp_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  */
1194 static void *
sdp_sock_newconn(void * parenthandle,void * connind)1195 sdp_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  */
1233 static void
sdp_sock_connected(void * handle)1234 sdp_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  */
1255 static void
sdp_sock_disconnected(void * handle,int error)1256 sdp_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*/
1275 static int
sdp_sock_recv(void * handle,mblk_t * mp,int flags)1276 sdp_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  */
1291 static void
sdp_sock_xmitted(void * handle,int writeable)1292 sdp_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  */
1317 static void
sdp_sock_urgdata(void * handle)1318 sdp_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  */
1333 static void
sdp_sock_ordrel(void * handle)1334 sdp_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 
1347 static void
sdp_sock_connfail(void * handle,int error)1348 sdp_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