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 * Copyright 2017 Joyent, Inc.
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 *, 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
sosdp_init(struct sonode * so,struct sonode * pso,struct cred * cr,int flags)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
sosdp_accept(struct sonode * lso,int fflag,struct cred * cr,struct sonode ** nsop)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
sosdp_bind(struct sonode * so,struct sockaddr * name,socklen_t namelen,int flags,struct cred * cr)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
sosdp_listen(struct sonode * so,int backlog,struct cred * cr)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
sosdp_connect(struct sonode * so,struct sockaddr * name,socklen_t namelen,int fflag,int flags,struct cred * cr)328 sosdp_connect(struct sonode *so, 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
sosdp_recvmsg(struct sonode * so,struct nmsghdr * msg,struct uio * uiop,struct cred * cr)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
sosdp_sendmsg(struct sonode * so,struct nmsghdr * msg,struct uio * uiop,struct cred * cr)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
sosdp_getpeername(struct sonode * so,struct sockaddr * addr,socklen_t * addrlen,boolean_t accept,struct cred * cr)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
sosdp_getsockname(struct sonode * so,struct sockaddr * addr,socklen_t * addrlen,struct cred * cr)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
sosdp_shutdown(struct sonode * so,int how,struct cred * cr)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
sosdp_getsockopt(struct sonode * so,int level,int option_name,void * optval,socklen_t * optlenp,int flags,struct cred * cr)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
sosdp_setsockopt(struct sonode * so,int level,int option_name,const void * optval,t_uscalar_t optlen,struct cred * cr)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
sosdp_ioctl(struct sonode * so,int cmd,intptr_t arg,int mode,struct cred * cr,int32_t * rvalp)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
sosdp_poll(struct sonode * so,short events,int anyyet,short * reventsp,struct pollhead ** phpp)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 goto done;
1099 }
1100
1101 *reventsp = 0;
1102 if (so->so_type != SOCK_STREAM) {
1103 goto done;
1104 }
1105
1106 /*
1107 * Don't mark socket writable until TX queued data is below watermark.
1108 */
1109 if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
1110 SDP_XMIT)) {
1111 *reventsp |= POLLOUT & events;
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_len > 0)) {
1120 *reventsp |= (POLLIN|POLLRDNORM) & events;
1121 }
1122
1123 done:
1124 if ((*reventsp == 0 && !anyyet) || (events & POLLET)) {
1125 *phpp = &so->so_poll_list;
1126 }
1127
1128 return (0);
1129 }
1130
1131 /* ARGSUSED */
1132 static int
sosdp_close(struct sonode * so,int flag,struct cred * cr)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, B_FALSE, error);
1158
1159 return (error);
1160 }
1161
1162 /* ARGSUSED */
1163 void
sosdp_fini(struct sonode * so,struct cred * cr)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 *
sdp_sock_newconn(void * parenthandle,void * connind)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
sdp_sock_connected(void * handle)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
sdp_sock_disconnected(void * handle,int error)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, B_FALSE, error);
1266 }
1267
1268 /*
1269 * Incoming data.
1270 */
1271 /*ARGSUSED*/
1272 static int
sdp_sock_recv(void * handle,mblk_t * mp,int flags)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
sdp_sock_xmitted(void * handle,int writeable)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
sdp_sock_urgdata(void * handle)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
sdp_sock_ordrel(void * handle)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
sdp_sock_connfail(void * handle,int error)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