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