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 2011 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 #include <sys/file.h>
28 #include <sys/stropts.h>
29 #include <sys/socket.h>
30 #include <sys/socketvar.h>
31 #include <sys/sysmacros.h>
32 #include <sys/filio.h> /* FIO* ioctls */
33 #include <sys/sockio.h> /* SIOC* ioctls */
34 #include <sys/poll_impl.h>
35 #include <sys/cmn_err.h>
36 #include <sys/ksocket.h>
37 #include <io/ksocket/ksocket_impl.h>
38 #include <fs/sockfs/sockcommon.h>
39
40 #define SOCKETMOD_TCP "tcp"
41 #define SOCKETMOD_UDP "udp"
42 /*
43 * Kernel Sockets
44 *
45 * Mostly a wrapper around the private socket_* functions.
46 */
47 int
ksocket_socket(ksocket_t * ksp,int domain,int type,int protocol,int flags,struct cred * cr)48 ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags,
49 struct cred *cr)
50 {
51 static const int version = SOV_DEFAULT;
52 int error = 0;
53 struct sonode *so;
54 *ksp = NULL;
55
56 /* All Solaris components should pass a cred for this operation. */
57 ASSERT(cr != NULL);
58
59 if (domain == AF_NCA)
60 return (EAFNOSUPPORT);
61
62 ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP);
63 so = socket_create(domain, type, protocol, NULL, NULL, version, flags,
64 cr, &error);
65 if (so == NULL) {
66 if (error == EAFNOSUPPORT) {
67 char *mod = NULL;
68
69 /*
70 * Could be that root file sytem is not loaded or
71 * soconfig has not run yet.
72 */
73 if (type == SOCK_STREAM && (domain == AF_INET ||
74 domain == AF_INET6) && (protocol == 0 ||
75 protocol == IPPROTO_TCP)) {
76 mod = SOCKETMOD_TCP;
77 } else if (type == SOCK_DGRAM && (domain == AF_INET ||
78 domain == AF_INET6) && (protocol == 0 ||
79 protocol == IPPROTO_UDP)) {
80 mod = SOCKETMOD_UDP;
81 } else {
82 return (EAFNOSUPPORT);
83 }
84
85 so = socket_create(domain, type, protocol, NULL,
86 mod, version, flags, cr, &error);
87 if (so == NULL)
88 return (error);
89 } else {
90 return (error);
91 }
92 }
93
94 so->so_mode |= SM_KERNEL;
95
96 *ksp = SOTOKS(so);
97
98 return (0);
99 }
100 int
ksocket_bind(ksocket_t ks,struct sockaddr * addr,socklen_t addrlen,struct cred * cr)101 ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
102 struct cred *cr)
103 {
104 int error;
105
106 /* All Solaris components should pass a cred for this operation. */
107 ASSERT(cr != NULL);
108
109 if (!KSOCKET_VALID(ks))
110 return (ENOTSOCK);
111
112 error = socket_bind(KSTOSO(ks), addr, addrlen, _SOBIND_SOCKBSD, cr);
113
114 return (error);
115 }
116
117 int
ksocket_listen(ksocket_t ks,int backlog,struct cred * cr)118 ksocket_listen(ksocket_t ks, int backlog, struct cred *cr)
119 {
120 /* All Solaris components should pass a cred for this operation. */
121 ASSERT(cr != NULL);
122
123 if (!KSOCKET_VALID(ks))
124 return (ENOTSOCK);
125
126 return (socket_listen(KSTOSO(ks), backlog, cr));
127 }
128
129 int
ksocket_accept(ksocket_t ks,struct sockaddr * addr,socklen_t * addrlenp,ksocket_t * nks,struct cred * cr)130 ksocket_accept(ksocket_t ks, struct sockaddr *addr,
131 socklen_t *addrlenp, ksocket_t *nks, struct cred *cr)
132 {
133 int error;
134 struct sonode *nso = NULL;
135
136 /* All Solaris components should pass a cred for this operation. */
137 ASSERT(cr != NULL);
138
139 *nks = NULL;
140
141 if (!KSOCKET_VALID(ks))
142 return (ENOTSOCK);
143
144 if (addr != NULL && addrlenp == NULL)
145 return (EFAULT);
146
147 error = socket_accept(KSTOSO(ks), KSOCKET_FMODE(ks), cr, &nso);
148 if (error != 0)
149 return (error);
150
151 ASSERT(nso != NULL);
152
153 nso->so_mode |= SM_KERNEL;
154
155 if (addr != NULL && addrlenp != NULL) {
156 error = socket_getpeername(nso, addr, addrlenp, B_TRUE, cr);
157 if (error != 0) {
158 (void) socket_close(nso, 0, cr);
159 socket_destroy(nso);
160 return ((error == ENOTCONN) ? ECONNABORTED : error);
161 }
162 }
163
164 *nks = SOTOKS(nso);
165
166 return (error);
167 }
168
169 int
ksocket_connect(ksocket_t ks,struct sockaddr * addr,socklen_t addrlen,struct cred * cr)170 ksocket_connect(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
171 struct cred *cr)
172 {
173 /* All Solaris components should pass a cred for this operation. */
174 ASSERT(cr != NULL);
175
176 if (!KSOCKET_VALID(ks))
177 return (ENOTSOCK);
178
179 return (socket_connect(KSTOSO(ks), addr, addrlen,
180 KSOCKET_FMODE(ks), 0, cr));
181 }
182
183 int
ksocket_send(ksocket_t ks,void * msg,size_t msglen,int flags,size_t * sent,struct cred * cr)184 ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags,
185 size_t *sent, struct cred *cr)
186 {
187 int error;
188 struct nmsghdr msghdr;
189 struct uio auio;
190 struct iovec iov;
191
192 /* All Solaris components should pass a cred for this operation. */
193 ASSERT(cr != NULL);
194
195 if (!KSOCKET_VALID(ks)) {
196 if (sent != NULL)
197 *sent = 0;
198 return (ENOTSOCK);
199 }
200
201 iov.iov_base = msg;
202 iov.iov_len = msglen;
203
204 bzero(&auio, sizeof (struct uio));
205 auio.uio_loffset = 0;
206 auio.uio_iov = &iov;
207 auio.uio_iovcnt = 1;
208 auio.uio_resid = msglen;
209 if (flags & MSG_USERSPACE)
210 auio.uio_segflg = UIO_USERSPACE;
211 else
212 auio.uio_segflg = UIO_SYSSPACE;
213 auio.uio_extflg = UIO_COPY_DEFAULT;
214 auio.uio_limit = 0;
215 auio.uio_fmode = KSOCKET_FMODE(ks);
216
217 msghdr.msg_name = NULL;
218 msghdr.msg_namelen = 0;
219 msghdr.msg_control = NULL;
220 msghdr.msg_controllen = 0;
221 msghdr.msg_flags = flags | MSG_EOR;
222
223 error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr);
224 if (error != 0) {
225 if (sent != NULL)
226 *sent = 0;
227 return (error);
228 }
229
230 if (sent != NULL)
231 *sent = msglen - auio.uio_resid;
232 return (0);
233 }
234
235 int
ksocket_sendto(ksocket_t ks,void * msg,size_t msglen,int flags,struct sockaddr * name,socklen_t namelen,size_t * sent,struct cred * cr)236 ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags,
237 struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr)
238 {
239 int error;
240 struct nmsghdr msghdr;
241 struct uio auio;
242 struct iovec iov;
243
244 /* All Solaris components should pass a cred for this operation. */
245 ASSERT(cr != NULL);
246
247 if (!KSOCKET_VALID(ks)) {
248 if (sent != NULL)
249 *sent = 0;
250 return (ENOTSOCK);
251 }
252
253 iov.iov_base = msg;
254 iov.iov_len = msglen;
255
256 bzero(&auio, sizeof (struct uio));
257 auio.uio_loffset = 0;
258 auio.uio_iov = &iov;
259 auio.uio_iovcnt = 1;
260 auio.uio_resid = msglen;
261 if (flags & MSG_USERSPACE)
262 auio.uio_segflg = UIO_USERSPACE;
263 else
264 auio.uio_segflg = UIO_SYSSPACE;
265 auio.uio_extflg = UIO_COPY_DEFAULT;
266 auio.uio_limit = 0;
267 auio.uio_fmode = KSOCKET_FMODE(ks);
268
269 msghdr.msg_iov = &iov;
270 msghdr.msg_iovlen = 1;
271 msghdr.msg_name = (char *)name;
272 msghdr.msg_namelen = namelen;
273 msghdr.msg_control = NULL;
274 msghdr.msg_controllen = 0;
275 msghdr.msg_flags = flags | MSG_EOR;
276
277 error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr);
278 if (error != 0) {
279 if (sent != NULL)
280 *sent = 0;
281 return (error);
282 }
283 if (sent != NULL)
284 *sent = msglen - auio.uio_resid;
285 return (0);
286 }
287
288 int
ksocket_sendmsg(ksocket_t ks,struct nmsghdr * msg,int flags,size_t * sent,struct cred * cr)289 ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags,
290 size_t *sent, struct cred *cr)
291 {
292 int error;
293 ssize_t len;
294 int i;
295 struct uio auio;
296
297 /* All Solaris components should pass a cred for this operation. */
298 ASSERT(cr != NULL);
299
300 if (!KSOCKET_VALID(ks)) {
301 if (sent != NULL)
302 *sent = 0;
303 return (ENOTSOCK);
304 }
305
306 bzero(&auio, sizeof (struct uio));
307 auio.uio_loffset = 0;
308 auio.uio_iov = msg->msg_iov;
309 auio.uio_iovcnt = msg->msg_iovlen;
310 if (flags & MSG_USERSPACE)
311 auio.uio_segflg = UIO_USERSPACE;
312 else
313 auio.uio_segflg = UIO_SYSSPACE;
314 auio.uio_extflg = UIO_COPY_DEFAULT;
315 auio.uio_limit = 0;
316 auio.uio_fmode = KSOCKET_FMODE(ks);
317 len = 0;
318 for (i = 0; i < msg->msg_iovlen; i++) {
319 ssize_t iovlen;
320 iovlen = (msg->msg_iov)[i].iov_len;
321 len += iovlen;
322 if (len < 0 || iovlen < 0)
323 return (EINVAL);
324 }
325 auio.uio_resid = len;
326
327 msg->msg_flags = flags | MSG_EOR;
328
329 error = socket_sendmsg(KSTOSO(ks), msg, &auio, cr);
330 if (error != 0) {
331 if (sent != NULL)
332 *sent = 0;
333 return (error);
334 }
335
336 if (sent != NULL)
337 *sent = len - auio.uio_resid;
338 return (0);
339 }
340
341
342 int
ksocket_recv(ksocket_t ks,void * msg,size_t msglen,int flags,size_t * recv,struct cred * cr)343 ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags,
344 size_t *recv, struct cred *cr)
345 {
346 int error;
347 struct nmsghdr msghdr;
348 struct uio auio;
349 struct iovec iov;
350
351 /* All Solaris components should pass a cred for this operation. */
352 ASSERT(cr != NULL);
353
354 if (!KSOCKET_VALID(ks)) {
355 if (recv != NULL)
356 *recv = 0;
357 return (ENOTSOCK);
358 }
359
360 iov.iov_base = msg;
361 iov.iov_len = msglen;
362
363 bzero(&auio, sizeof (struct uio));
364 auio.uio_loffset = 0;
365 auio.uio_iov = &iov;
366 auio.uio_iovcnt = 1;
367 auio.uio_resid = msglen;
368 if (flags & MSG_USERSPACE)
369 auio.uio_segflg = UIO_USERSPACE;
370 else
371 auio.uio_segflg = UIO_SYSSPACE;
372 auio.uio_extflg = UIO_COPY_DEFAULT;
373 auio.uio_limit = 0;
374 auio.uio_fmode = KSOCKET_FMODE(ks);
375
376 msghdr.msg_name = NULL;
377 msghdr.msg_namelen = 0;
378 msghdr.msg_control = NULL;
379 msghdr.msg_controllen = 0;
380 msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
381 MSG_DONTWAIT | MSG_USERSPACE);
382
383 error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr);
384 if (error != 0) {
385 if (recv != NULL)
386 *recv = 0;
387 return (error);
388 }
389
390 if (recv != NULL)
391 *recv = msglen - auio.uio_resid;
392 return (0);
393 }
394
395 int
ksocket_recvfrom(ksocket_t ks,void * msg,size_t msglen,int flags,struct sockaddr * name,socklen_t * namelen,size_t * recv,struct cred * cr)396 ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags,
397 struct sockaddr *name, socklen_t *namelen, size_t *recv, struct cred *cr)
398 {
399 int error;
400 struct nmsghdr msghdr;
401 struct uio auio;
402 struct iovec iov;
403
404 /* All Solaris components should pass a cred for this operation. */
405 ASSERT(cr != NULL);
406
407 if (!KSOCKET_VALID(ks)) {
408 if (recv != NULL)
409 *recv = 0;
410 return (ENOTSOCK);
411 }
412
413 iov.iov_base = msg;
414 iov.iov_len = msglen;
415
416 bzero(&auio, sizeof (struct uio));
417 auio.uio_loffset = 0;
418 auio.uio_iov = &iov;
419 auio.uio_iovcnt = 1;
420 auio.uio_resid = msglen;
421 if (flags & MSG_USERSPACE)
422 auio.uio_segflg = UIO_USERSPACE;
423 else
424 auio.uio_segflg = UIO_SYSSPACE;
425 auio.uio_extflg = UIO_COPY_DEFAULT;
426 auio.uio_limit = 0;
427 auio.uio_fmode = KSOCKET_FMODE(ks);
428
429 msghdr.msg_name = (char *)name;
430 msghdr.msg_namelen = *namelen;
431 msghdr.msg_control = NULL;
432 msghdr.msg_controllen = 0;
433 msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
434 MSG_DONTWAIT | MSG_USERSPACE);
435
436 error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr);
437 if (error != 0) {
438 if (recv != NULL)
439 *recv = 0;
440 return (error);
441 }
442 if (recv != NULL)
443 *recv = msglen - auio.uio_resid;
444
445 bcopy(msghdr.msg_name, name, msghdr.msg_namelen);
446 bcopy(&msghdr.msg_namelen, namelen, sizeof (msghdr.msg_namelen));
447 return (0);
448 }
449
450 int
ksocket_recvmsg(ksocket_t ks,struct nmsghdr * msg,int flags,size_t * recv,struct cred * cr)451 ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recv,
452 struct cred *cr)
453 {
454 int error;
455 ssize_t len;
456 int i;
457 struct uio auio;
458
459 /* All Solaris components should pass a cred for this operation. */
460 ASSERT(cr != NULL);
461
462 if (!KSOCKET_VALID(ks)) {
463 if (recv != NULL)
464 *recv = 0;
465 return (ENOTSOCK);
466 }
467
468 bzero(&auio, sizeof (struct uio));
469 auio.uio_loffset = 0;
470 auio.uio_iov = msg->msg_iov;
471 auio.uio_iovcnt = msg->msg_iovlen;
472 if (msg->msg_flags & MSG_USERSPACE)
473 auio.uio_segflg = UIO_USERSPACE;
474 else
475 auio.uio_segflg = UIO_SYSSPACE;
476 auio.uio_extflg = UIO_COPY_DEFAULT;
477 auio.uio_limit = 0;
478 auio.uio_fmode = KSOCKET_FMODE(ks);
479 len = 0;
480
481 for (i = 0; i < msg->msg_iovlen; i++) {
482 ssize_t iovlen;
483 iovlen = (msg->msg_iov)[i].iov_len;
484 len += iovlen;
485 if (len < 0 || iovlen < 0)
486 return (EINVAL);
487 }
488 auio.uio_resid = len;
489
490 msg->msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
491 MSG_DONTWAIT | MSG_USERSPACE);
492
493 error = socket_recvmsg(KSTOSO(ks), msg, &auio, cr);
494 if (error != 0) {
495 if (recv != NULL)
496 *recv = 0;
497 return (error);
498 }
499 if (recv != NULL)
500 *recv = len - auio.uio_resid;
501 return (0);
502
503 }
504
505 int
ksocket_shutdown(ksocket_t ks,int how,struct cred * cr)506 ksocket_shutdown(ksocket_t ks, int how, struct cred *cr)
507 {
508 struct sonode *so;
509
510 /* All Solaris components should pass a cred for this operation. */
511 ASSERT(cr != NULL);
512
513 if (!KSOCKET_VALID(ks))
514 return (ENOTSOCK);
515
516 so = KSTOSO(ks);
517
518 return (socket_shutdown(so, how, cr));
519 }
520
521 int
ksocket_close(ksocket_t ks,struct cred * cr)522 ksocket_close(ksocket_t ks, struct cred *cr)
523 {
524 struct sonode *so;
525 so = KSTOSO(ks);
526
527 /* All Solaris components should pass a cred for this operation. */
528 ASSERT(cr != NULL);
529
530 mutex_enter(&so->so_lock);
531
532 if (!KSOCKET_VALID(ks)) {
533 mutex_exit(&so->so_lock);
534 return (ENOTSOCK);
535 }
536
537 so->so_state |= SS_CLOSING;
538
539 if (so->so_count > 1) {
540 mutex_enter(&so->so_acceptq_lock);
541 cv_broadcast(&so->so_acceptq_cv);
542 mutex_exit(&so->so_acceptq_lock);
543 cv_broadcast(&so->so_rcv_cv);
544 cv_broadcast(&so->so_state_cv);
545 cv_broadcast(&so->so_single_cv);
546 cv_broadcast(&so->so_read_cv);
547 cv_broadcast(&so->so_snd_cv);
548 cv_broadcast(&so->so_copy_cv);
549 }
550 while (so->so_count > 1)
551 cv_wait(&so->so_closing_cv, &so->so_lock);
552
553 mutex_exit(&so->so_lock);
554 /* Remove callbacks, if any */
555 (void) ksocket_setcallbacks(ks, NULL, NULL, cr);
556
557 (void) socket_close(so, 0, cr);
558 socket_destroy(so);
559
560 return (0);
561 }
562
563 int
ksocket_getsockname(ksocket_t ks,struct sockaddr * addr,socklen_t * addrlen,struct cred * cr)564 ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
565 struct cred *cr)
566 {
567 struct sonode *so;
568
569 /* All Solaris components should pass a cred for this operation. */
570 ASSERT(cr != NULL);
571
572 if (!KSOCKET_VALID(ks))
573 return (ENOTSOCK);
574
575 so = KSTOSO(ks);
576
577 if (addrlen == NULL || (addr == NULL && *addrlen != 0))
578 return (EFAULT);
579
580 return (socket_getsockname(so, addr, addrlen, cr));
581 }
582
583 int
ksocket_getpeername(ksocket_t ks,struct sockaddr * addr,socklen_t * addrlen,struct cred * cr)584 ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
585 struct cred *cr)
586 {
587 struct sonode *so;
588
589 /* All Solaris components should pass a cred for this operation. */
590 ASSERT(cr != NULL);
591
592 if (!KSOCKET_VALID(ks))
593 return (ENOTSOCK);
594
595 so = KSTOSO(ks);
596
597 if (addrlen == NULL || (addr == NULL && *addrlen != 0))
598 return (EFAULT);
599
600 return (socket_getpeername(so, addr, addrlen, B_FALSE, cr));
601 }
602
603 int
ksocket_getsockopt(ksocket_t ks,int level,int optname,void * optval,int * optlen,struct cred * cr)604 ksocket_getsockopt(ksocket_t ks, int level, int optname, void *optval,
605 int *optlen, struct cred *cr)
606 {
607 struct sonode *so;
608
609 /* All Solaris components should pass a cred for this operation. */
610 ASSERT(cr != NULL);
611
612 if (!KSOCKET_VALID(ks))
613 return (ENOTSOCK);
614
615 so = KSTOSO(ks);
616
617 if (optlen == NULL)
618 return (EFAULT);
619 if (*optlen > SO_MAXARGSIZE)
620 return (EINVAL);
621
622 return (socket_getsockopt(so, level, optname, optval,
623 (socklen_t *)optlen, 0, cr));
624 }
625
626 int
ksocket_setsockopt(ksocket_t ks,int level,int optname,const void * optval,int optlen,struct cred * cr)627 ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval,
628 int optlen, struct cred *cr)
629 {
630 struct sonode *so;
631
632 /* All Solaris components should pass a cred for this operation. */
633 ASSERT(cr != NULL);
634
635 if (!KSOCKET_VALID(ks))
636 return (ENOTSOCK);
637
638 so = KSTOSO(ks);
639
640 if (optval == NULL)
641 optlen = 0;
642
643 return (socket_setsockopt(so, level, optname, optval,
644 (t_uscalar_t)optlen, cr));
645 }
646
647 /* ARGSUSED */
648 int
ksocket_setcallbacks(ksocket_t ks,ksocket_callbacks_t * cb,void * arg,struct cred * cr)649 ksocket_setcallbacks(ksocket_t ks, ksocket_callbacks_t *cb, void *arg,
650 struct cred *cr)
651 {
652 struct sonode *so;
653
654 /* All Solaris components should pass a cred for this operation. */
655 ASSERT(cr != NULL);
656
657 if (!KSOCKET_VALID(ks))
658 return (ENOTSOCK);
659
660 so = KSTOSO(ks);
661
662 if (cb == NULL && arg != NULL)
663 return (EFAULT);
664 if (cb == NULL) {
665 mutex_enter(&so->so_lock);
666 bzero(&(so->so_ksock_callbacks), sizeof (ksocket_callbacks_t));
667 so->so_ksock_cb_arg = NULL;
668 mutex_exit(&so->so_lock);
669 } else {
670 mutex_enter(&so->so_lock);
671 SETCALLBACK(so, cb, connected, KSOCKET_CB_CONNECTED)
672 SETCALLBACK(so, cb, connectfailed, KSOCKET_CB_CONNECTFAILED)
673 SETCALLBACK(so, cb, disconnected, KSOCKET_CB_DISCONNECTED)
674 SETCALLBACK(so, cb, newdata, KSOCKET_CB_NEWDATA)
675 SETCALLBACK(so, cb, newconn, KSOCKET_CB_NEWCONN)
676 SETCALLBACK(so, cb, cansend, KSOCKET_CB_CANSEND)
677 SETCALLBACK(so, cb, oobdata, KSOCKET_CB_OOBDATA)
678 SETCALLBACK(so, cb, cantsendmore, KSOCKET_CB_CANTSENDMORE)
679 SETCALLBACK(so, cb, cantrecvmore, KSOCKET_CB_CANTRECVMORE)
680 so->so_ksock_cb_arg = arg;
681 mutex_exit(&so->so_lock);
682 }
683 return (0);
684 }
685
686 int
ksocket_ioctl(ksocket_t ks,int cmd,intptr_t arg,int * rvalp,struct cred * cr)687 ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvalp, struct cred *cr)
688 {
689 struct sonode *so;
690 int rval;
691
692 /* All Solaris components should pass a cred for this operation. */
693 ASSERT(cr != NULL);
694
695 if (!KSOCKET_VALID(ks))
696 return (ENOTSOCK);
697
698 so = KSTOSO(ks);
699
700 switch (cmd) {
701 default:
702 /* STREAM iotcls are not supported */
703 if ((cmd & 0xffffff00U) == STR) {
704 rval = EOPNOTSUPP;
705 } else {
706 rval = socket_ioctl(so, cmd, arg,
707 KSOCKET_FMODE(ks) | FKIOCTL, cr, rvalp);
708 }
709 break;
710 case FIOASYNC:
711 case SIOCSPGRP:
712 case FIOSETOWN:
713 case SIOCGPGRP:
714 case FIOGETOWN:
715 rval = EOPNOTSUPP;
716 break;
717 }
718
719 return (rval);
720 }
721
722 /*
723 * Wait for an input event, similar to t_kspoll().
724 * Ideas and code borrowed from ../devpoll.c
725 * Basically, setup just enough poll data structures so
726 * we can block on a CV until timeout or pollwakeup().
727 */
728 int
ksocket_spoll(ksocket_t ks,int timo,short events,short * revents,struct cred * cr)729 ksocket_spoll(ksocket_t ks, int timo, short events, short *revents,
730 struct cred *cr)
731 {
732 struct sonode *so;
733 pollhead_t *php, *php2;
734 polldat_t *pdp;
735 pollcache_t *pcp;
736 int error;
737 clock_t expires = 0;
738 clock_t rval;
739
740 /* All Solaris components should pass a cred for this operation. */
741 ASSERT(cr != NULL);
742 ASSERT(curthread->t_pollcache == NULL);
743
744 if (revents == NULL)
745 return (EINVAL);
746 if (!KSOCKET_VALID(ks))
747 return (ENOTSOCK);
748 so = KSTOSO(ks);
749
750 /*
751 * Check if there are any events already pending.
752 * If we're not willing to block, (timo == 0) then
753 * pass "anyyet">0 to socket_poll so it can skip
754 * some work. Othewise pass "anyyet"=0 and if
755 * there are no events pending, it will fill in
756 * the pollhead pointer we need for pollwakeup().
757 *
758 * XXX - pollrelock() logic needs to know which
759 * which pollcache lock to grab. It'd be a
760 * cleaner solution if we could pass pcp as
761 * an arguement in VOP_POLL interface instead
762 * of implicitly passing it using thread_t
763 * struct. On the other hand, changing VOP_POLL
764 * interface will require all driver/file system
765 * poll routine to change. May want to revisit
766 * the tradeoff later.
767 */
768 php = NULL;
769 *revents = 0;
770 pcp = pcache_alloc();
771 pcache_create(pcp, 1);
772
773 mutex_enter(&pcp->pc_lock);
774 curthread->t_pollcache = pcp;
775 error = socket_poll(so, (short)events, (timo == 0),
776 revents, &php);
777 curthread->t_pollcache = NULL;
778 mutex_exit(&pcp->pc_lock);
779
780 if (error != 0 || *revents != 0 || timo == 0)
781 goto out;
782
783 /*
784 * Need to block. Did not get *revents, so the
785 * php should be non-NULL, but let's verify.
786 * Also compute when our sleep expires.
787 */
788 if (php == NULL) {
789 error = EIO;
790 goto out;
791 }
792 if (timo > 0)
793 expires = ddi_get_lbolt() +
794 MSEC_TO_TICK_ROUNDUP(timo);
795
796 /*
797 * Setup: pollhead -> polldat -> pollcache
798 * needed for pollwakeup()
799 * pdp should be freed by pcache_destroy
800 */
801 pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP);
802 pdp->pd_fd = 0;
803 pdp->pd_events = events;
804 pdp->pd_pcache = pcp;
805 pcache_insert_fd(pcp, pdp, 1);
806 pollhead_insert(php, pdp);
807 pdp->pd_php = php;
808
809 mutex_enter(&pcp->pc_lock);
810 while (!(so->so_state & SS_CLOSING)) {
811 pcp->pc_flag = 0;
812
813 /* Ditto pcp comment above. */
814 curthread->t_pollcache = pcp;
815 error = socket_poll(so, (short)events, 0,
816 revents, &php2);
817 curthread->t_pollcache = NULL;
818 ASSERT(php2 == php);
819
820 if (error != 0 || *revents != 0)
821 break;
822
823 if (pcp->pc_flag & T_POLLWAKE)
824 continue;
825
826 if (timo == -1) {
827 rval = cv_wait_sig(&pcp->pc_cv, &pcp->pc_lock);
828 } else {
829 rval = cv_timedwait_sig(&pcp->pc_cv, &pcp->pc_lock,
830 expires);
831 }
832 if (rval <= 0) {
833 if (rval == 0)
834 error = EINTR;
835 break;
836 }
837 }
838 mutex_exit(&pcp->pc_lock);
839
840 if (pdp->pd_php != NULL) {
841 pollhead_delete(pdp->pd_php, pdp);
842 pdp->pd_php = NULL;
843 pdp->pd_fd = NULL;
844 }
845
846 /*
847 * pollwakeup() may still interact with this pollcache. Wait until
848 * it is done.
849 */
850 mutex_enter(&pcp->pc_no_exit);
851 ASSERT(pcp->pc_busy >= 0);
852 while (pcp->pc_busy > 0)
853 cv_wait(&pcp->pc_busy_cv, &pcp->pc_no_exit);
854 mutex_exit(&pcp->pc_no_exit);
855 out:
856 pcache_destroy(pcp);
857 return (error);
858 }
859
860 int
ksocket_sendmblk(ksocket_t ks,struct nmsghdr * msg,int flags,mblk_t ** mpp,cred_t * cr)861 ksocket_sendmblk(ksocket_t ks, struct nmsghdr *msg, int flags,
862 mblk_t **mpp, cred_t *cr)
863 {
864 struct sonode *so;
865 int i_val;
866 socklen_t val_len;
867 mblk_t *mp = *mpp;
868 int error;
869
870 /* All Solaris components should pass a cred for this operation. */
871 ASSERT(cr != NULL);
872
873 if (!KSOCKET_VALID(ks))
874 return (ENOTSOCK);
875
876 so = KSTOSO(ks);
877
878 if (flags & MSG_MBLK_QUICKRELE) {
879 error = socket_getsockopt(so, SOL_SOCKET, SO_SND_COPYAVOID,
880 &i_val, &val_len, 0, cr);
881 if (error != 0)
882 return (error);
883
884 /* Zero copy is not enable */
885 if (i_val == 0)
886 return (ECANCELED);
887
888 for (; mp != NULL; mp = mp->b_cont)
889 mp->b_datap->db_struioflag |= STRUIO_ZC;
890 }
891
892 error = socket_sendmblk(so, msg, flags, cr, mpp);
893
894 return (error);
895 }
896
897
898 void
ksocket_hold(ksocket_t ks)899 ksocket_hold(ksocket_t ks)
900 {
901 struct sonode *so;
902 so = KSTOSO(ks);
903
904 if (!mutex_owned(&so->so_lock)) {
905 mutex_enter(&so->so_lock);
906 so->so_count++;
907 mutex_exit(&so->so_lock);
908 } else
909 so->so_count++;
910 }
911
912 void
ksocket_rele(ksocket_t ks)913 ksocket_rele(ksocket_t ks)
914 {
915 struct sonode *so;
916
917 so = KSTOSO(ks);
918 /*
919 * When so_count equals 1 means no thread working on this ksocket
920 */
921 if (so->so_count < 2)
922 cmn_err(CE_PANIC, "ksocket_rele: sonode ref count 0 or 1");
923
924 if (!mutex_owned(&so->so_lock)) {
925 mutex_enter(&so->so_lock);
926 if (--so->so_count == 1)
927 cv_signal(&so->so_closing_cv);
928 mutex_exit(&so->so_lock);
929 } else {
930 if (--so->so_count == 1)
931 cv_signal(&so->so_closing_cv);
932 }
933 }
934