sockin.c revision 1.48 1 /* $NetBSD: sockin.c,v 1.48 2014/07/09 14:41:43 rtr Exp $ */
2
3 /*
4 * Copyright (c) 2008, 2009 Antti Kantee. All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: sockin.c,v 1.48 2014/07/09 14:41:43 rtr Exp $");
30
31 #include <sys/param.h>
32 #include <sys/condvar.h>
33 #include <sys/domain.h>
34 #include <sys/kmem.h>
35 #include <sys/kthread.h>
36 #include <sys/mbuf.h>
37 #include <sys/mutex.h>
38 #include <sys/once.h>
39 #include <sys/poll.h>
40 #include <sys/protosw.h>
41 #include <sys/queue.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/time.h>
45
46 #include <net/bpf.h>
47 #include <net/if.h>
48 #include <net/radix.h>
49
50 #include <netinet/in.h>
51 #include <netinet/in_systm.h>
52 #include <netinet/ip.h>
53
54 #include <rump/rumpuser.h>
55
56 #include "rump_private.h"
57 #include "sockin_user.h"
58
59 /*
60 * An inet communication domain which uses the socket interface.
61 * Supports IPv4 & IPv6 UDP/TCP.
62 */
63
64 DOMAIN_DEFINE(sockindomain);
65 DOMAIN_DEFINE(sockin6domain);
66
67 static int sockin_do_init(void);
68 static void sockin_init(void);
69 static int sockin_attach(struct socket *, int);
70 static void sockin_detach(struct socket *);
71 static int sockin_accept(struct socket *, struct mbuf *);
72 static int sockin_ioctl(struct socket *, u_long, void *, struct ifnet *);
73 static int sockin_stat(struct socket *, struct stat *);
74 static int sockin_peeraddr(struct socket *, struct mbuf *);
75 static int sockin_sockaddr(struct socket *, struct mbuf *);
76 static int sockin_usrreq(struct socket *, int, struct mbuf *,
77 struct mbuf *, struct mbuf *, struct lwp *);
78 static int sockin_ctloutput(int op, struct socket *, struct sockopt *);
79
80 static const struct pr_usrreqs sockin_usrreqs = {
81 .pr_attach = sockin_attach,
82 .pr_detach = sockin_detach,
83 .pr_accept = sockin_accept,
84 .pr_ioctl = sockin_ioctl,
85 .pr_stat = sockin_stat,
86 .pr_peeraddr = sockin_peeraddr,
87 .pr_sockaddr = sockin_sockaddr,
88 .pr_generic = sockin_usrreq,
89 };
90
91 const struct protosw sockinsw[] = {
92 {
93 .pr_type = SOCK_DGRAM,
94 .pr_domain = &sockindomain,
95 .pr_protocol = IPPROTO_UDP,
96 .pr_flags = PR_ATOMIC|PR_ADDR,
97 .pr_usrreqs = &sockin_usrreqs,
98 .pr_ctloutput = sockin_ctloutput,
99 },
100 {
101 .pr_type = SOCK_STREAM,
102 .pr_domain = &sockindomain,
103 .pr_protocol = IPPROTO_TCP,
104 .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LISTEN|PR_ABRTACPTDIS,
105 .pr_usrreqs = &sockin_usrreqs,
106 .pr_ctloutput = sockin_ctloutput,
107 }};
108 const struct protosw sockin6sw[] = {
109 {
110 .pr_type = SOCK_DGRAM,
111 .pr_domain = &sockin6domain,
112 .pr_protocol = IPPROTO_UDP,
113 .pr_flags = PR_ATOMIC|PR_ADDR,
114 .pr_usrreqs = &sockin_usrreqs,
115 .pr_ctloutput = sockin_ctloutput,
116 },
117 {
118 .pr_type = SOCK_STREAM,
119 .pr_domain = &sockin6domain,
120 .pr_protocol = IPPROTO_TCP,
121 .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LISTEN|PR_ABRTACPTDIS,
122 .pr_usrreqs = &sockin_usrreqs,
123 .pr_ctloutput = sockin_ctloutput,
124 }};
125
126 struct domain sockindomain = {
127 .dom_family = PF_INET,
128 .dom_name = "socket_inet",
129 .dom_init = sockin_init,
130 .dom_externalize = NULL,
131 .dom_dispose = NULL,
132 .dom_protosw = sockinsw,
133 .dom_protoswNPROTOSW = &sockinsw[__arraycount(sockinsw)],
134 .dom_rtattach = rt_inithead,
135 .dom_rtoffset = 32,
136 .dom_maxrtkey = sizeof(struct sockaddr_in),
137 .dom_ifattach = NULL,
138 .dom_ifdetach = NULL,
139 .dom_ifqueues = { NULL },
140 .dom_link = { NULL },
141 .dom_mowner = MOWNER_INIT("",""),
142 .dom_rtcache = { NULL },
143 .dom_sockaddr_cmp = NULL
144 };
145 struct domain sockin6domain = {
146 .dom_family = PF_INET6,
147 .dom_name = "socket_inet6",
148 .dom_init = sockin_init,
149 .dom_externalize = NULL,
150 .dom_dispose = NULL,
151 .dom_protosw = sockin6sw,
152 .dom_protoswNPROTOSW = &sockin6sw[__arraycount(sockin6sw)],
153 .dom_rtattach = rt_inithead,
154 .dom_rtoffset = 32,
155 .dom_maxrtkey = sizeof(struct sockaddr_in6),
156 .dom_ifattach = NULL,
157 .dom_ifdetach = NULL,
158 .dom_ifqueues = { NULL },
159 .dom_link = { NULL },
160 .dom_mowner = MOWNER_INIT("",""),
161 .dom_rtcache = { NULL },
162 .dom_sockaddr_cmp = NULL
163 };
164
165 #define SO2S(so) ((intptr_t)(so->so_internal))
166 #define SOCKIN_SBSIZE 65536
167
168 struct sockin_unit {
169 struct socket *su_so;
170
171 LIST_ENTRY(sockin_unit) su_entries;
172 };
173 static LIST_HEAD(, sockin_unit) su_ent = LIST_HEAD_INITIALIZER(su_ent);
174 static kmutex_t su_mtx;
175 static bool rebuild;
176 static int nsock;
177
178 /* XXX: for the bpf hack */
179 static struct ifnet sockin_if;
180 int ifpromisc(struct ifnet *ifp, int pswitch) { return 0; }
181
182 static int
183 registersock(struct socket *so, int news)
184 {
185 struct sockin_unit *su;
186
187 su = kmem_alloc(sizeof(*su), KM_NOSLEEP);
188 if (!su)
189 return ENOMEM;
190
191 so->so_internal = (void *)(intptr_t)news;
192 su->su_so = so;
193
194 mutex_enter(&su_mtx);
195 LIST_INSERT_HEAD(&su_ent, su, su_entries);
196 nsock++;
197 rebuild = true;
198 mutex_exit(&su_mtx);
199
200 return 0;
201 }
202
203 static void
204 removesock(struct socket *so)
205 {
206 struct sockin_unit *su_iter;
207
208 mutex_enter(&su_mtx);
209 LIST_FOREACH(su_iter, &su_ent, su_entries) {
210 if (su_iter->su_so == so)
211 break;
212 }
213 if (!su_iter)
214 panic("no such socket");
215
216 LIST_REMOVE(su_iter, su_entries);
217 nsock--;
218 rebuild = true;
219 mutex_exit(&su_mtx);
220
221 rumpuser_close(SO2S(su_iter->su_so));
222 kmem_free(su_iter, sizeof(*su_iter));
223 }
224
225 static void
226 sockin_process(struct socket *so)
227 {
228 struct sockaddr_in6 from;
229 struct iovec io;
230 struct msghdr rmsg;
231 struct mbuf *m;
232 size_t n, plen;
233 int error;
234
235 m = m_gethdr(M_WAIT, MT_DATA);
236 if (so->so_proto->pr_type == SOCK_DGRAM) {
237 plen = IP_MAXPACKET;
238 MEXTMALLOC(m, plen, M_DONTWAIT);
239 } else {
240 plen = MCLBYTES;
241 MCLGET(m, M_DONTWAIT);
242 }
243 if ((m->m_flags & M_EXT) == 0) {
244 m_freem(m);
245 return;
246 }
247
248 memset(&rmsg, 0, sizeof(rmsg));
249 io.iov_base = mtod(m, void *);
250 io.iov_len = plen;
251 rmsg.msg_iov = &io;
252 rmsg.msg_iovlen = 1;
253 rmsg.msg_name = (struct sockaddr *)&from;
254 rmsg.msg_namelen = sizeof(from);
255
256 error = rumpcomp_sockin_recvmsg(SO2S(so), &rmsg, 0, &n);
257 if (error || n == 0) {
258 m_freem(m);
259
260 /* Treat a TCP socket a goner */
261 if (error != EAGAIN && so->so_proto->pr_type == SOCK_STREAM) {
262 mutex_enter(softnet_lock);
263 soisdisconnected(so);
264 mutex_exit(softnet_lock);
265 removesock(so);
266 }
267 return;
268 }
269 m->m_len = m->m_pkthdr.len = n;
270
271 bpf_mtap_af(&sockin_if, AF_UNSPEC, m);
272
273 mutex_enter(softnet_lock);
274 if (so->so_proto->pr_type == SOCK_DGRAM) {
275 if (!sbappendaddr(&so->so_rcv, rmsg.msg_name, m, NULL)) {
276 m_freem(m);
277 }
278 } else {
279 sbappendstream(&so->so_rcv, m);
280 }
281
282 sorwakeup(so);
283 mutex_exit(softnet_lock);
284 }
285
286 static void
287 sockin_accept(struct socket *so)
288 {
289 struct socket *nso;
290 struct sockaddr_in6 sin;
291 int news, error, slen;
292
293 slen = sizeof(sin);
294 error = rumpcomp_sockin_accept(SO2S(so), (struct sockaddr *)&sin,
295 &slen, &news);
296 if (error)
297 return;
298
299 mutex_enter(softnet_lock);
300 nso = sonewconn(so, true);
301 if (nso == NULL)
302 goto errout;
303 if (registersock(nso, news) != 0)
304 goto errout;
305 mutex_exit(softnet_lock);
306 return;
307
308 errout:
309 rumpuser_close(news);
310 if (nso)
311 soclose(nso);
312 mutex_exit(softnet_lock);
313 }
314
315 #define POLLTIMEOUT 100 /* check for new entries every 100ms */
316
317 /* XXX: doesn't handle socket (kernel) locking properly? */
318 static void
319 sockinworker(void *arg)
320 {
321 struct pollfd *pfds = NULL, *npfds;
322 struct sockin_unit *su_iter;
323 struct socket *so;
324 int cursock = 0, i, rv, error;
325
326 /*
327 * Loop reading requests. Check for new sockets periodically
328 * (could be smarter, but I'm lazy).
329 */
330 for (;;) {
331 if (rebuild) {
332 npfds = NULL;
333 mutex_enter(&su_mtx);
334 if (nsock)
335 npfds = kmem_alloc(nsock * sizeof(*npfds),
336 KM_NOSLEEP);
337 if (npfds || nsock == 0) {
338 if (pfds)
339 kmem_free(pfds, cursock*sizeof(*pfds));
340 pfds = npfds;
341 cursock = nsock;
342 rebuild = false;
343
344 i = 0;
345 LIST_FOREACH(su_iter, &su_ent, su_entries) {
346 pfds[i].fd = SO2S(su_iter->su_so);
347 pfds[i].events = POLLIN;
348 pfds[i].revents = 0;
349 i++;
350 }
351 KASSERT(i == nsock);
352 }
353 mutex_exit(&su_mtx);
354 }
355
356 /* find affected sockets & process */
357 error = rumpcomp_sockin_poll(pfds, cursock, POLLTIMEOUT, &rv);
358 for (i = 0; i < cursock && rv > 0 && error == 0; i++) {
359 if (pfds[i].revents & POLLIN) {
360 mutex_enter(&su_mtx);
361 LIST_FOREACH(su_iter, &su_ent, su_entries) {
362 if (SO2S(su_iter->su_so)==pfds[i].fd) {
363 so = su_iter->su_so;
364 mutex_exit(&su_mtx);
365 if(so->so_options&SO_ACCEPTCONN)
366 sockin_accept(so);
367 else
368 sockin_process(so);
369 mutex_enter(&su_mtx);
370 break;
371 }
372 }
373 /* if we can't find it, just wing it */
374 KASSERT(rebuild || su_iter);
375 mutex_exit(&su_mtx);
376 pfds[i].revents = 0;
377 rv--;
378 i = -1;
379 continue;
380 }
381
382 /* something else? ignore */
383 if (pfds[i].revents) {
384 pfds[i].revents = 0;
385 rv--;
386 }
387 }
388 KASSERT(rv <= 0);
389 }
390
391 }
392
393 static int
394 sockin_do_init(void)
395 {
396 int rv;
397
398 if (rump_threads) {
399 if ((rv = kthread_create(PRI_NONE, 0, NULL, sockinworker,
400 NULL, NULL, "sockwork")) != 0)
401 panic("sockin_init: could not create worker thread\n");
402 } else {
403 printf("sockin_init: no threads => no worker thread\n");
404 }
405 mutex_init(&su_mtx, MUTEX_DEFAULT, IPL_NONE);
406 strlcpy(sockin_if.if_xname, "sockin0", sizeof(sockin_if.if_xname));
407 bpf_attach(&sockin_if, DLT_NULL, 0);
408 return 0;
409 }
410
411 static void
412 sockin_init(void)
413 {
414 static ONCE_DECL(init);
415
416 RUN_ONCE(&init, sockin_do_init);
417 }
418
419 static int
420 sockin_attach(struct socket *so, int proto)
421 {
422 const int type = so->so_proto->pr_type;
423 int error, news, family;
424
425 sosetlock(so);
426 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
427 error = soreserve(so, SOCKIN_SBSIZE, SOCKIN_SBSIZE);
428 if (error)
429 return error;
430 }
431
432 family = so->so_proto->pr_domain->dom_family;
433 KASSERT(family == PF_INET || family == PF_INET6);
434 error = rumpcomp_sockin_socket(family, type, 0, &news);
435 if (error)
436 return error;
437
438 /* For UDP sockets, make sure we can send/recv maximum. */
439 if (type == SOCK_DGRAM) {
440 int sbsize = SOCKIN_SBSIZE;
441 error = rumpcomp_sockin_setsockopt(news,
442 SOL_SOCKET, SO_SNDBUF,
443 &sbsize, sizeof(sbsize));
444 sbsize = SOCKIN_SBSIZE;
445 error = rumpcomp_sockin_setsockopt(news,
446 SOL_SOCKET, SO_RCVBUF,
447 &sbsize, sizeof(sbsize));
448 }
449
450 if ((error = registersock(so, news)) != 0)
451 rumpuser_close(news);
452
453 return error;
454 }
455
456 static void
457 sockin_detach(struct socket *so)
458 {
459 panic("sockin_detach: IMPLEMENT ME\n");
460 }
461
462 static int
463 sockin_accept(struct socket *so, struct mbuf *nam)
464 {
465 KASSERT(solocked(so));
466
467 /* we do all the work in the worker thread */
468 return 0;
469 }
470
471 static int
472 sockin_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
473 {
474 return ENOTTY;
475 }
476
477 static int
478 sockin_stat(struct socket *so, struct stat *ub)
479 {
480 KASSERT(solocked(so));
481
482 return 0;
483 }
484
485 static int
486 sockin_peeraddr(struct socket *so, struct mbuf *nam)
487 {
488 KASSERT(solocked(so));
489
490 int error = 0;
491 int slen = nam->m_len;
492
493 error = rumpcomp_sockin_getname(SO2S(so),
494 mtod(nam, struct sockaddr *), &slen, RUMPCOMP_SOCKIN_PEERNAME);
495 if (error == 0)
496 nam->m_len = slen;
497 return error;
498 }
499
500 static int
501 sockin_sockaddr(struct socket *so, struct mbuf *nam)
502 {
503 KASSERT(solocked(so));
504
505 int error = 0;
506 int slen = nam->m_len;
507
508 error = rumpcomp_sockin_getname(SO2S(so),
509 mtod(nam, struct sockaddr *), &slen, RUMPCOMP_SOCKIN_SOCKNAME);
510 if (error == 0)
511 nam->m_len = slen;
512 return error;
513 }
514
515 static int
516 sockin_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
517 struct mbuf *control, struct lwp *l)
518 {
519 int error = 0;
520
521 KASSERT(req != PRU_ACCEPT);
522 KASSERT(req != PRU_CONTROL);
523 KASSERT(req != PRU_SENSE);
524 KASSERT(req != PRU_PEERADDR);
525 KASSERT(req != PRU_SOCKADDR);
526
527 switch (req) {
528 case PRU_BIND:
529 error = rumpcomp_sockin_bind(SO2S(so),
530 mtod(nam, const struct sockaddr *),
531 nam->m_len);
532 break;
533
534 case PRU_CONNECT:
535 error = rumpcomp_sockin_connect(SO2S(so),
536 mtod(nam, struct sockaddr *), nam->m_len);
537 if (error == 0)
538 soisconnected(so);
539 break;
540
541 case PRU_LISTEN:
542 error = rumpcomp_sockin_listen(SO2S(so), so->so_qlimit);
543 break;
544
545 case PRU_SEND:
546 {
547 struct sockaddr *saddr;
548 struct msghdr mhdr;
549 size_t iov_max, i;
550 struct iovec iov_buf[32], *iov;
551 struct mbuf *m2;
552 size_t tot, n;
553 int s;
554
555 bpf_mtap_af(&sockin_if, AF_UNSPEC, m);
556
557 memset(&mhdr, 0, sizeof(mhdr));
558
559 iov_max = 0;
560 for (m2 = m; m2 != NULL; m2 = m2->m_next) {
561 iov_max++;
562 }
563
564 if (iov_max <= __arraycount(iov_buf)) {
565 iov = iov_buf;
566 } else {
567 iov = kmem_alloc(sizeof(struct iovec) * iov_max,
568 KM_SLEEP);
569 }
570
571 tot = 0;
572 for (i = 0, m2 = m; m2 != NULL; m2 = m2->m_next, i++) {
573 iov[i].iov_base = m2->m_data;
574 iov[i].iov_len = m2->m_len;
575 tot += m2->m_len;
576 }
577 mhdr.msg_iov = iov;
578 mhdr.msg_iovlen = i;
579 s = SO2S(so);
580
581 if (nam != NULL) {
582 saddr = mtod(nam, struct sockaddr *);
583 mhdr.msg_name = saddr;
584 mhdr.msg_namelen = saddr->sa_len;
585 }
586
587 rumpcomp_sockin_sendmsg(s, &mhdr, 0, &n);
588
589 if (iov != iov_buf)
590 kmem_free(iov, sizeof(struct iovec) * iov_max);
591
592 m_freem(m);
593 m_freem(control);
594
595 /* this assumes too many things to list.. buthey, testing */
596 if (!rump_threads)
597 sockin_process(so);
598 }
599 break;
600
601 case PRU_SHUTDOWN:
602 removesock(so);
603 break;
604
605 default:
606 panic("sockin_usrreq: IMPLEMENT ME, req %d not supported", req);
607 }
608
609 return error;
610 }
611
612 static int
613 sockin_ctloutput(int op, struct socket *so, struct sockopt *sopt)
614 {
615
616 return rumpcomp_sockin_setsockopt(SO2S(so), sopt->sopt_level,
617 sopt->sopt_name, sopt->sopt_data, sopt->sopt_size);
618 }
619
620 int sockin_unavailable(void);
621 int
622 sockin_unavailable(void)
623 {
624
625 panic("interface not available in with sockin");
626 }
627 __strong_alias(rtrequest,sockin_unavailable);
628 __strong_alias(ifunit,sockin_unavailable);
629 __strong_alias(ifreq_setaddr,sockin_unavailable);
630