ksocket.c revision 8348:4137e18bfaf0
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 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
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/cmn_err.h>
35#include <sys/ksocket.h>
36#include <io/ksocket/ksocket_impl.h>
37#include <fs/sockfs/sockcommon.h>
38
39#define	SOCKETMOD_TCP	"tcp"
40#define	SOCKETMOD_UDP	"udp"
41/*
42 * Kernel Sockets
43 *
44 * Mostly a wrapper around the private socket_* functions.
45 */
46int
47ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags,
48    struct cred *cr)
49{
50	static const int version = SOV_DEFAULT;
51	int error = 0;
52	struct sonode *so;
53	*ksp = NULL;
54
55	if (domain == AF_NCA || domain == AF_UNIX)
56		return (EAFNOSUPPORT);
57
58	ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP);
59	so = socket_create(domain, type, protocol, NULL, NULL, version, flags,
60	    cr, &error);
61	if (so == NULL) {
62		if (error == EAFNOSUPPORT) {
63			char *mod = NULL;
64
65			/*
66			 * Could be that root file sytem is not loaded or
67			 * soconfig has not run yet.
68			 */
69			if (type == SOCK_STREAM && (domain == AF_INET ||
70			    domain == AF_INET6) && (protocol == 0 ||
71			    protocol == IPPROTO_TCP)) {
72					mod = SOCKETMOD_TCP;
73			} else if (type == SOCK_DGRAM && (domain == AF_INET ||
74			    domain == AF_INET6) && (protocol == 0 ||
75			    protocol == IPPROTO_UDP)) {
76					mod = SOCKETMOD_UDP;
77			} else {
78				return (EAFNOSUPPORT);
79			}
80
81			so = socket_create(domain, type, protocol, NULL,
82			    mod, version, flags, cr, &error);
83			if (so == NULL)
84				return (error);
85		} else {
86			return (error);
87		}
88	}
89
90	so->so_mode |= SM_KERNEL;
91
92	*ksp = SOTOKS(so);
93
94	return (0);
95}
96int
97ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
98    struct cred *cr)
99{
100	int error;
101
102	if (!KSOCKET_VALID(ks))
103		return (ENOTSOCK);
104
105	error = socket_bind(KSTOSO(ks), addr, addrlen, _SOBIND_SOCKBSD, cr);
106
107	return (error);
108}
109
110int
111ksocket_listen(ksocket_t ks, int backlog, struct cred *cr)
112{
113	if (!KSOCKET_VALID(ks))
114		return (ENOTSOCK);
115
116	return (socket_listen(KSTOSO(ks), backlog, cr));
117}
118
119int
120ksocket_accept(ksocket_t ks, struct sockaddr *addr,
121    socklen_t *addrlenp, ksocket_t *nks, struct cred *cr)
122{
123	int error;
124	struct sonode *nso = NULL;
125
126	*nks = NULL;
127
128	if (!KSOCKET_VALID(ks))
129		return (ENOTSOCK);
130
131	if (addr != NULL && addrlenp == NULL)
132		return (EFAULT);
133
134	error = socket_accept(KSTOSO(ks), KSOCKET_FMODE(ks), cr, &nso);
135	if (error != 0)
136		return (error);
137
138	ASSERT(nso != NULL);
139
140	nso->so_mode |= SM_KERNEL;
141
142	if (addr != NULL && addrlenp != NULL) {
143		error = socket_getpeername(nso, addr, addrlenp, B_TRUE, cr);
144		if (error != 0) {
145			(void) socket_close(nso, 0, cr);
146			socket_destroy(nso);
147			return ((error == ENOTCONN) ? ECONNABORTED : error);
148		}
149	}
150
151	*nks = SOTOKS(nso);
152
153	return (error);
154}
155
156int
157ksocket_connect(ksocket_t ks, const struct sockaddr *addr, socklen_t addrlen,
158    struct cred *cr)
159{
160	if (!KSOCKET_VALID(ks))
161		return (ENOTSOCK);
162
163	return (socket_connect(KSTOSO(ks), addr, addrlen,
164	    KSOCKET_FMODE(ks), 0, cr));
165}
166
167int
168ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags,
169    size_t *sent, struct cred *cr)
170{
171	int error;
172	struct nmsghdr msghdr;
173	struct uio auio;
174	struct iovec iov;
175
176	if (!KSOCKET_VALID(ks)) {
177		if (sent != NULL)
178			*sent = 0;
179		return (ENOTSOCK);
180	}
181
182	iov.iov_base = msg;
183	iov.iov_len = msglen;
184
185	bzero(&auio, sizeof (struct uio));
186	auio.uio_loffset = 0;
187	auio.uio_iov = &iov;
188	auio.uio_iovcnt = 1;
189	auio.uio_resid = msglen;
190	if (flags & MSG_USERSPACE)
191		auio.uio_segflg = UIO_USERSPACE;
192	else
193		auio.uio_segflg = UIO_SYSSPACE;
194	auio.uio_extflg = UIO_COPY_DEFAULT;
195	auio.uio_limit = 0;
196	auio.uio_fmode = KSOCKET_FMODE(ks);
197
198	msghdr.msg_name = NULL;
199	msghdr.msg_namelen = 0;
200	msghdr.msg_control = NULL;
201	msghdr.msg_controllen = 0;
202	msghdr.msg_flags = flags | MSG_EOR;
203
204	error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr);
205	if (error != 0) {
206		if (sent != NULL)
207			*sent = 0;
208		return (error);
209	}
210
211	if (sent != NULL)
212		*sent = msglen - auio.uio_resid;
213	return (0);
214}
215
216int
217ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags,
218    struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr)
219{
220	int error;
221	struct nmsghdr msghdr;
222	struct uio auio;
223	struct iovec iov;
224
225	if (!KSOCKET_VALID(ks)) {
226		if (sent != NULL)
227			*sent = 0;
228		return (ENOTSOCK);
229	}
230
231	iov.iov_base = msg;
232	iov.iov_len = msglen;
233
234	bzero(&auio, sizeof (struct uio));
235	auio.uio_loffset = 0;
236	auio.uio_iov = &iov;
237	auio.uio_iovcnt = 1;
238	auio.uio_resid = msglen;
239	if (flags & MSG_USERSPACE)
240		auio.uio_segflg = UIO_USERSPACE;
241	else
242		auio.uio_segflg = UIO_SYSSPACE;
243	auio.uio_extflg = UIO_COPY_DEFAULT;
244	auio.uio_limit = 0;
245	auio.uio_fmode = KSOCKET_FMODE(ks);
246
247	msghdr.msg_iov = &iov;
248	msghdr.msg_iovlen = 1;
249	msghdr.msg_name = (char *)name;
250	msghdr.msg_namelen = namelen;
251	msghdr.msg_control = NULL;
252	msghdr.msg_controllen = 0;
253	msghdr.msg_flags = flags | MSG_EOR;
254
255	error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr);
256	if (error != 0) {
257		if (sent != NULL)
258			*sent = 0;
259		return (error);
260	}
261	if (sent != NULL)
262		*sent = msglen - auio.uio_resid;
263	return (0);
264}
265
266int
267ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags,
268    size_t *sent, struct cred *cr)
269{
270	int error;
271	ssize_t len;
272	int i;
273	struct uio auio;
274
275	if (!KSOCKET_VALID(ks)) {
276		if (sent != NULL)
277			*sent = 0;
278		return (ENOTSOCK);
279	}
280
281	bzero(&auio, sizeof (struct uio));
282	auio.uio_loffset = 0;
283	auio.uio_iov = msg->msg_iov;
284	auio.uio_iovcnt = msg->msg_iovlen;
285	if (flags & MSG_USERSPACE)
286		auio.uio_segflg = UIO_USERSPACE;
287	else
288		auio.uio_segflg = UIO_SYSSPACE;
289	auio.uio_extflg = UIO_COPY_DEFAULT;
290	auio.uio_limit = 0;
291	auio.uio_fmode = KSOCKET_FMODE(ks);
292	len = 0;
293	for (i = 0; i < msg->msg_iovlen; i++) {
294		ssize_t iovlen;
295		iovlen = (msg->msg_iov)[i].iov_len;
296		len += iovlen;
297		if (len < 0 || iovlen < 0)
298			return (EINVAL);
299	}
300	auio.uio_resid = len;
301
302	msg->msg_flags = flags | MSG_EOR;
303
304	error = socket_sendmsg(KSTOSO(ks), msg, &auio, cr);
305	if (error != 0) {
306		if (sent != NULL)
307			*sent = 0;
308		return (error);
309	}
310
311	if (sent != NULL)
312		*sent = len - auio.uio_resid;
313	return (0);
314}
315
316
317int
318ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags,
319    size_t *recv, struct cred *cr)
320{
321	int error;
322	struct nmsghdr msghdr;
323	struct uio auio;
324	struct iovec iov;
325
326	if (!KSOCKET_VALID(ks)) {
327		if (recv != NULL)
328			*recv = 0;
329		return (ENOTSOCK);
330	}
331
332	iov.iov_base = msg;
333	iov.iov_len = msglen;
334
335	bzero(&auio, sizeof (struct uio));
336	auio.uio_loffset = 0;
337	auio.uio_iov = &iov;
338	auio.uio_iovcnt = 1;
339	auio.uio_resid = msglen;
340	if (flags & MSG_USERSPACE)
341		auio.uio_segflg = UIO_USERSPACE;
342	else
343		auio.uio_segflg = UIO_SYSSPACE;
344	auio.uio_extflg = UIO_COPY_DEFAULT;
345	auio.uio_limit = 0;
346	auio.uio_fmode = KSOCKET_FMODE(ks);
347
348	msghdr.msg_name = NULL;
349	msghdr.msg_namelen = 0;
350	msghdr.msg_control = NULL;
351	msghdr.msg_controllen = 0;
352	msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
353	    MSG_DONTWAIT | MSG_USERSPACE);
354
355	error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr);
356	if (error != 0) {
357		if (recv != NULL)
358			*recv = 0;
359		return (error);
360	}
361
362	if (recv != NULL)
363		*recv = msglen - auio.uio_resid;
364	return (0);
365}
366
367int
368ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags,
369    struct sockaddr *name, socklen_t *namelen, size_t *recv, struct cred *cr)
370{
371	int error;
372	struct nmsghdr msghdr;
373	struct uio auio;
374	struct iovec iov;
375
376	if (!KSOCKET_VALID(ks)) {
377		if (recv != NULL)
378			*recv = 0;
379		return (ENOTSOCK);
380	}
381
382	iov.iov_base = msg;
383	iov.iov_len = msglen;
384
385	bzero(&auio, sizeof (struct uio));
386	auio.uio_loffset = 0;
387	auio.uio_iov = &iov;
388	auio.uio_iovcnt = 1;
389	auio.uio_resid = msglen;
390	if (flags & MSG_USERSPACE)
391		auio.uio_segflg = UIO_USERSPACE;
392	else
393		auio.uio_segflg = UIO_SYSSPACE;
394	auio.uio_extflg = UIO_COPY_DEFAULT;
395	auio.uio_limit = 0;
396	auio.uio_fmode = KSOCKET_FMODE(ks);
397
398	msghdr.msg_name = (char *)name;
399	msghdr.msg_namelen = *namelen;
400	msghdr.msg_control = NULL;
401	msghdr.msg_controllen = 0;
402	msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
403	    MSG_DONTWAIT | MSG_USERSPACE);
404
405	error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr);
406	if (error != 0) {
407		if (recv != NULL)
408			*recv = 0;
409		return (error);
410	}
411	if (recv != NULL)
412		*recv = msglen - auio.uio_resid;
413
414	bcopy(msghdr.msg_name, name, msghdr.msg_namelen);
415	bcopy(&msghdr.msg_namelen, namelen, sizeof (msghdr.msg_namelen));
416	return (0);
417}
418
419int
420ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recv,
421    struct cred *cr)
422{
423	int error;
424	ssize_t len;
425	int i;
426	struct uio auio;
427
428	if (!KSOCKET_VALID(ks)) {
429		if (recv != NULL)
430			*recv = 0;
431		return (ENOTSOCK);
432	}
433
434	bzero(&auio, sizeof (struct uio));
435	auio.uio_loffset = 0;
436	auio.uio_iov = msg->msg_iov;
437	auio.uio_iovcnt = msg->msg_iovlen;
438	if (msg->msg_flags & MSG_USERSPACE)
439		auio.uio_segflg = UIO_USERSPACE;
440	else
441		auio.uio_segflg = UIO_SYSSPACE;
442	auio.uio_extflg = UIO_COPY_DEFAULT;
443	auio.uio_limit = 0;
444	auio.uio_fmode = KSOCKET_FMODE(ks);
445	len = 0;
446
447	for (i = 0; i < msg->msg_iovlen; i++) {
448		ssize_t iovlen;
449		iovlen = (msg->msg_iov)[i].iov_len;
450		len += iovlen;
451		if (len < 0 || iovlen < 0)
452			return (EINVAL);
453	}
454	auio.uio_resid = len;
455
456	msg->msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
457	    MSG_DONTWAIT | MSG_USERSPACE);
458
459	error = socket_recvmsg(KSTOSO(ks), msg, &auio, cr);
460	if (error != 0) {
461		if (recv != NULL)
462			*recv = 0;
463		return (error);
464	}
465	if (recv != NULL)
466		*recv = len - auio.uio_resid;
467	return (0);
468
469}
470
471int
472ksocket_shutdown(ksocket_t ks, int how, struct cred *cr)
473{
474	struct sonode *so;
475
476	if (!KSOCKET_VALID(ks))
477		return (ENOTSOCK);
478
479	so = KSTOSO(ks);
480
481	return (socket_shutdown(so, how, cr));
482}
483
484int
485ksocket_close(ksocket_t ks, struct cred *cr)
486{
487	struct sonode *so;
488	so = KSTOSO(ks);
489
490	mutex_enter(&so->so_lock);
491
492	if (!KSOCKET_VALID(ks)) {
493		mutex_exit(&so->so_lock);
494		return (ENOTSOCK);
495	}
496
497	so->so_state |= SS_CLOSING;
498
499	if (so->so_count > 1) {
500		mutex_enter(&so->so_acceptq_lock);
501		cv_broadcast(&so->so_acceptq_cv);
502		mutex_exit(&so->so_acceptq_lock);
503		cv_broadcast(&so->so_rcv_cv);
504		cv_broadcast(&so->so_state_cv);
505		cv_broadcast(&so->so_want_cv);
506		cv_broadcast(&so->so_snd_cv);
507		cv_broadcast(&so->so_copy_cv);
508	}
509	while (so->so_count > 1)
510		cv_wait(&so->so_closing_cv, &so->so_lock);
511
512	mutex_exit(&so->so_lock);
513	/* Remove callbacks, if any */
514	(void) ksocket_setcallbacks(ks, NULL, NULL, cr);
515
516	(void) socket_close(so, 0, cr);
517	socket_destroy(so);
518
519	return (0);
520}
521
522int
523ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
524    struct cred *cr)
525{
526	struct sonode *so;
527
528	if (!KSOCKET_VALID(ks))
529		return (ENOTSOCK);
530
531	so = KSTOSO(ks);
532
533	if (addrlen == NULL || (addr == NULL && *addrlen != 0))
534		return (EFAULT);
535
536	return (socket_getsockname(so, addr, addrlen, cr));
537}
538
539int
540ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
541    struct cred *cr)
542{
543	struct sonode *so;
544
545	if (!KSOCKET_VALID(ks))
546		return (ENOTSOCK);
547
548	so = KSTOSO(ks);
549
550	if (addrlen == NULL || (addr == NULL && *addrlen != 0))
551		return (EFAULT);
552
553	return (socket_getpeername(so, addr, addrlen, B_FALSE, cr));
554}
555
556int
557ksocket_getsockopt(ksocket_t ks, int level, int optname, void *optval,
558    int *optlen, struct cred *cr)
559{
560	struct sonode *so;
561
562	if (!KSOCKET_VALID(ks))
563		return (ENOTSOCK);
564
565	so = KSTOSO(ks);
566
567	if (optlen == NULL)
568		return (EFAULT);
569	if (*optlen > SO_MAXARGSIZE)
570		return (EINVAL);
571
572	return (socket_getsockopt(so, level, optname, optval,
573	    (socklen_t *)optlen, 0, cr));
574}
575
576int
577ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval,
578    int optlen, struct cred *cr)
579{
580	struct sonode *so;
581
582	if (!KSOCKET_VALID(ks))
583		return (ENOTSOCK);
584
585	so = KSTOSO(ks);
586
587	if (optval == NULL)
588		optlen = 0;
589
590	return (socket_setsockopt(so, level, optname, optval,
591	    (t_uscalar_t)optlen, cr));
592}
593
594/* ARGSUSED */
595int
596ksocket_setcallbacks(ksocket_t ks, ksocket_callbacks_t *cb, void *arg,
597    struct cred *cr)
598{
599	struct sonode *so;
600
601	if (!KSOCKET_VALID(ks))
602		return (ENOTSOCK);
603
604	so = KSTOSO(ks);
605
606	if (cb == NULL && arg != NULL)
607		return (EFAULT);
608	if (cb == NULL) {
609		mutex_enter(&so->so_lock);
610		bzero(&(so->so_ksock_callbacks), sizeof (ksocket_callbacks_t));
611		so->so_ksock_cb_arg = NULL;
612		mutex_exit(&so->so_lock);
613	} else {
614		mutex_enter(&so->so_lock);
615		SETCALLBACK(so, cb, connected, KSOCKET_CB_CONNECTED)
616		SETCALLBACK(so, cb, connectfailed, KSOCKET_CB_CONNECTFAILED)
617		SETCALLBACK(so, cb, disconnected, KSOCKET_CB_DISCONNECTED)
618		SETCALLBACK(so, cb, newdata, KSOCKET_CB_NEWDATA)
619		SETCALLBACK(so, cb, newconn, KSOCKET_CB_NEWCONN)
620		SETCALLBACK(so, cb, cansend, KSOCKET_CB_CANSEND)
621		SETCALLBACK(so, cb, oobdata, KSOCKET_CB_OOBDATA)
622		SETCALLBACK(so, cb, cantsendmore, KSOCKET_CB_CANTSENDMORE)
623		SETCALLBACK(so, cb, cantrecvmore, KSOCKET_CB_CANTRECVMORE)
624		so->so_ksock_cb_arg = arg;
625		mutex_exit(&so->so_lock);
626	}
627	return (0);
628}
629
630int
631ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvalp, struct cred *cr)
632{
633	struct sonode *so;
634	int rval;
635
636	if (!KSOCKET_VALID(ks))
637		return (ENOTSOCK);
638
639	so = KSTOSO(ks);
640
641	switch (cmd) {
642	default:
643		/* STREAM iotcls are not supported */
644		if ((cmd & 0xffffff00U) == STR) {
645			rval = EOPNOTSUPP;
646		} else {
647			rval = socket_ioctl(so, cmd, arg,
648			    KSOCKET_FMODE(ks) | FKIOCTL, cr, rvalp);
649		}
650		break;
651	case FIOASYNC:
652	case SIOCSPGRP:
653	case FIOSETOWN:
654	case SIOCGPGRP:
655	case FIOGETOWN:
656		rval = EOPNOTSUPP;
657		break;
658	}
659
660	return (rval);
661}
662
663int
664ksocket_sendmblk(ksocket_t ks, struct nmsghdr *msg, int flags,
665    mblk_t **mpp, cred_t *cr)
666{
667	struct		sonode *so;
668	int		i_val;
669	socklen_t	val_len;
670	mblk_t		*mp = *mpp;
671	int		error;
672
673	if (!KSOCKET_VALID(ks))
674		return (ENOTSOCK);
675
676	so = KSTOSO(ks);
677
678	if (flags & MSG_MBLK_QUICKRELE) {
679		error = socket_getsockopt(so, SOL_SOCKET, SO_SND_COPYAVOID,
680		    &i_val, &val_len, 0, CRED());
681		if (error != 0)
682			return (error);
683
684		/* Zero copy is not enable */
685		if (i_val == 0)
686			return (ECANCELED);
687
688		for (; mp != NULL; mp = mp->b_cont)
689			mp->b_datap->db_struioflag |= STRUIO_ZC;
690	}
691
692	error = socket_sendmblk(so, msg, flags, cr, mpp);
693
694	return (error);
695}
696
697
698void
699ksocket_hold(ksocket_t ks)
700{
701	struct sonode *so;
702	so = KSTOSO(ks);
703
704	if (!mutex_owned(&so->so_lock)) {
705		mutex_enter(&so->so_lock);
706		so->so_count++;
707		mutex_exit(&so->so_lock);
708	} else
709		so->so_count++;
710}
711
712void
713ksocket_rele(ksocket_t ks)
714{
715	struct sonode *so;
716
717	so = KSTOSO(ks);
718	/*
719	 * When so_count equals 1 means no thread working on this ksocket
720	 */
721	if (so->so_count < 2)
722		cmn_err(CE_PANIC, "ksocket_rele: sonode ref count 0 or 1");
723
724	if (!mutex_owned(&so->so_lock)) {
725		mutex_enter(&so->so_lock);
726		if (--so->so_count == 1)
727			cv_signal(&so->so_closing_cv);
728		mutex_exit(&so->so_lock);
729	} else {
730		if (--so->so_count == 1)
731			cv_signal(&so->so_closing_cv);
732	}
733}
734