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