1*97fd5147Sthorpej /* $NetBSD: sockin.c,v 1.67 2022/09/03 02:53:18 thorpej Exp $ */
2ad9bbd7bSpooka
3ad9bbd7bSpooka /*
439cb5b51Spooka * Copyright (c) 2008, 2009 Antti Kantee. All Rights Reserved.
5ad9bbd7bSpooka *
6ad9bbd7bSpooka * Redistribution and use in source and binary forms, with or without
7ad9bbd7bSpooka * modification, are permitted provided that the following conditions
8ad9bbd7bSpooka * are met:
9ad9bbd7bSpooka * 1. Redistributions of source code must retain the above copyright
10ad9bbd7bSpooka * notice, this list of conditions and the following disclaimer.
11ad9bbd7bSpooka * 2. Redistributions in binary form must reproduce the above copyright
12ad9bbd7bSpooka * notice, this list of conditions and the following disclaimer in the
13ad9bbd7bSpooka * documentation and/or other materials provided with the distribution.
14ad9bbd7bSpooka *
15ad9bbd7bSpooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16ad9bbd7bSpooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17ad9bbd7bSpooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18ad9bbd7bSpooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19ad9bbd7bSpooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20ad9bbd7bSpooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21ad9bbd7bSpooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22ad9bbd7bSpooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23ad9bbd7bSpooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24ad9bbd7bSpooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25ad9bbd7bSpooka * SUCH DAMAGE.
26ad9bbd7bSpooka */
27ad9bbd7bSpooka
28a768afd6Spooka #include <sys/cdefs.h>
29*97fd5147Sthorpej __KERNEL_RCSID(0, "$NetBSD: sockin.c,v 1.67 2022/09/03 02:53:18 thorpej Exp $");
30a768afd6Spooka
31ad9bbd7bSpooka #include <sys/param.h>
32ad9bbd7bSpooka #include <sys/condvar.h>
33ad9bbd7bSpooka #include <sys/domain.h>
34ad9bbd7bSpooka #include <sys/kmem.h>
35ad9bbd7bSpooka #include <sys/kthread.h>
36ad9bbd7bSpooka #include <sys/mbuf.h>
37ad9bbd7bSpooka #include <sys/mutex.h>
3853da9055Sstacktic #include <sys/once.h>
39ad9bbd7bSpooka #include <sys/poll.h>
40ad9bbd7bSpooka #include <sys/protosw.h>
41ad9bbd7bSpooka #include <sys/queue.h>
42ad9bbd7bSpooka #include <sys/socket.h>
43ad9bbd7bSpooka #include <sys/socketvar.h>
44ad9bbd7bSpooka #include <sys/time.h>
45ad9bbd7bSpooka
463694a148Spooka #include <net/bpf.h>
473694a148Spooka #include <net/if.h>
48d6457e83Spooka #include <net/radix.h>
49d6457e83Spooka
50ad9bbd7bSpooka #include <netinet/in.h>
51ad9bbd7bSpooka #include <netinet/in_systm.h>
52ad9bbd7bSpooka #include <netinet/ip.h>
53ad9bbd7bSpooka
546bb51422Spooka #include <rump-sys/kern.h>
556bb51422Spooka
56ad9bbd7bSpooka #include <rump/rumpuser.h>
57ad9bbd7bSpooka
5800328592Spooka #include "sockin_user.h"
5939cb5b51Spooka
60ad9bbd7bSpooka /*
61ad9bbd7bSpooka * An inet communication domain which uses the socket interface.
6275b2fca2Spooka * Supports IPv4 & IPv6 UDP/TCP.
63ad9bbd7bSpooka */
64ad9bbd7bSpooka
65ad9bbd7bSpooka DOMAIN_DEFINE(sockindomain);
663df1f0e3Sstacktic DOMAIN_DEFINE(sockin6domain);
673df1f0e3Sstacktic
6853da9055Sstacktic static int sockin_do_init(void);
69ad9bbd7bSpooka static void sockin_init(void);
704ae03c18Srmind static int sockin_attach(struct socket *, int);
714ae03c18Srmind static void sockin_detach(struct socket *);
72eddf3af3Srtr static int sockin_accept(struct socket *, struct sockaddr *);
738cf67cc6Srtr static int sockin_connect2(struct socket *, struct socket *);
74a2ba5e69Srtr static int sockin_bind(struct socket *, struct sockaddr *, struct lwp *);
75ce6a5ff6Srtr static int sockin_listen(struct socket *, struct lwp *);
76fd12cf39Srtr static int sockin_connect(struct socket *, struct sockaddr *, struct lwp *);
77892163b8Srtr static int sockin_disconnect(struct socket *);
78892163b8Srtr static int sockin_shutdown(struct socket *);
79892163b8Srtr static int sockin_abort(struct socket *);
800dedd977Srtr static int sockin_ioctl(struct socket *, u_long, void *, struct ifnet *);
810f199192Srtr static int sockin_stat(struct socket *, struct stat *);
82eddf3af3Srtr static int sockin_peeraddr(struct socket *, struct sockaddr *);
83eddf3af3Srtr static int sockin_sockaddr(struct socket *, struct sockaddr *);
84822872eaSrtr static int sockin_rcvd(struct socket *, int, struct lwp *);
8535b22fa9Srtr static int sockin_recvoob(struct socket *, struct mbuf *, int);
86fd12cf39Srtr static int sockin_send(struct socket *, struct mbuf *, struct sockaddr *,
87651e5bd3Srtr struct mbuf *, struct lwp *);
8835b22fa9Srtr static int sockin_sendoob(struct socket *, struct mbuf *, struct mbuf *);
898cf67cc6Srtr static int sockin_purgeif(struct socket *, struct ifnet *);
90eaff187cSpooka static int sockin_ctloutput(int op, struct socket *, struct sockopt *);
91ad9bbd7bSpooka
9237af0cc7Srmind static const struct pr_usrreqs sockin_usrreqs = {
934ae03c18Srmind .pr_attach = sockin_attach,
944ae03c18Srmind .pr_detach = sockin_detach,
95d27b133dSrtr .pr_accept = sockin_accept,
966dd8eef0Srtr .pr_bind = sockin_bind,
976dd8eef0Srtr .pr_listen = sockin_listen,
98ad6ae402Srtr .pr_connect = sockin_connect,
998cf67cc6Srtr .pr_connect2 = sockin_connect2,
100892163b8Srtr .pr_disconnect = sockin_disconnect,
101892163b8Srtr .pr_shutdown = sockin_shutdown,
102892163b8Srtr .pr_abort = sockin_abort,
103d54d7ab2Srtr .pr_ioctl = sockin_ioctl,
1040f199192Srtr .pr_stat = sockin_stat,
105d575eb54Srtr .pr_peeraddr = sockin_peeraddr,
106d575eb54Srtr .pr_sockaddr = sockin_sockaddr,
107822872eaSrtr .pr_rcvd = sockin_rcvd,
10835b22fa9Srtr .pr_recvoob = sockin_recvoob,
109651e5bd3Srtr .pr_send = sockin_send,
11035b22fa9Srtr .pr_sendoob = sockin_sendoob,
1118cf67cc6Srtr .pr_purgeif = sockin_purgeif,
11237af0cc7Srmind };
11337af0cc7Srmind
114ad9bbd7bSpooka const struct protosw sockinsw[] = {
1157dd6651aSpooka {
1167dd6651aSpooka .pr_type = SOCK_DGRAM,
117ad9bbd7bSpooka .pr_domain = &sockindomain,
118ad9bbd7bSpooka .pr_protocol = IPPROTO_UDP,
119ad9bbd7bSpooka .pr_flags = PR_ATOMIC|PR_ADDR,
12037af0cc7Srmind .pr_usrreqs = &sockin_usrreqs,
121eaff187cSpooka .pr_ctloutput = sockin_ctloutput,
1227dd6651aSpooka },
1237dd6651aSpooka {
1247dd6651aSpooka .pr_type = SOCK_STREAM,
1257dd6651aSpooka .pr_domain = &sockindomain,
1267dd6651aSpooka .pr_protocol = IPPROTO_TCP,
1277dd6651aSpooka .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LISTEN|PR_ABRTACPTDIS,
12837af0cc7Srmind .pr_usrreqs = &sockin_usrreqs,
129eaff187cSpooka .pr_ctloutput = sockin_ctloutput,
130ad9bbd7bSpooka }};
1313df1f0e3Sstacktic const struct protosw sockin6sw[] = {
1323df1f0e3Sstacktic {
1333df1f0e3Sstacktic .pr_type = SOCK_DGRAM,
1343df1f0e3Sstacktic .pr_domain = &sockin6domain,
1353df1f0e3Sstacktic .pr_protocol = IPPROTO_UDP,
1363df1f0e3Sstacktic .pr_flags = PR_ATOMIC|PR_ADDR,
13737af0cc7Srmind .pr_usrreqs = &sockin_usrreqs,
1383df1f0e3Sstacktic .pr_ctloutput = sockin_ctloutput,
1393df1f0e3Sstacktic },
1403df1f0e3Sstacktic {
1413df1f0e3Sstacktic .pr_type = SOCK_STREAM,
1423df1f0e3Sstacktic .pr_domain = &sockin6domain,
1433df1f0e3Sstacktic .pr_protocol = IPPROTO_TCP,
1443df1f0e3Sstacktic .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LISTEN|PR_ABRTACPTDIS,
14537af0cc7Srmind .pr_usrreqs = &sockin_usrreqs,
1463df1f0e3Sstacktic .pr_ctloutput = sockin_ctloutput,
1473df1f0e3Sstacktic }};
148ad9bbd7bSpooka
149ad9bbd7bSpooka struct domain sockindomain = {
150ad9bbd7bSpooka .dom_family = PF_INET,
151ad9bbd7bSpooka .dom_name = "socket_inet",
1527dd6651aSpooka .dom_init = sockin_init,
153ad9bbd7bSpooka .dom_externalize = NULL,
154ad9bbd7bSpooka .dom_dispose = NULL,
155ad9bbd7bSpooka .dom_protosw = sockinsw,
1567dd6651aSpooka .dom_protoswNPROTOSW = &sockinsw[__arraycount(sockinsw)],
157060522deSdyoung .dom_rtattach = rt_inithead,
158d6457e83Spooka .dom_rtoffset = 32,
159d6457e83Spooka .dom_maxrtkey = sizeof(struct sockaddr_in),
160ad9bbd7bSpooka .dom_ifattach = NULL,
161ad9bbd7bSpooka .dom_ifdetach = NULL,
162ad9bbd7bSpooka .dom_link = { NULL },
163ad9bbd7bSpooka .dom_mowner = MOWNER_INIT("",""),
164ad9bbd7bSpooka .dom_sockaddr_cmp = NULL
165ad9bbd7bSpooka };
1663df1f0e3Sstacktic struct domain sockin6domain = {
1673df1f0e3Sstacktic .dom_family = PF_INET6,
1683df1f0e3Sstacktic .dom_name = "socket_inet6",
1693df1f0e3Sstacktic .dom_init = sockin_init,
1703df1f0e3Sstacktic .dom_externalize = NULL,
1713df1f0e3Sstacktic .dom_dispose = NULL,
1723df1f0e3Sstacktic .dom_protosw = sockin6sw,
1733df1f0e3Sstacktic .dom_protoswNPROTOSW = &sockin6sw[__arraycount(sockin6sw)],
1743df1f0e3Sstacktic .dom_rtattach = rt_inithead,
1753df1f0e3Sstacktic .dom_rtoffset = 32,
1763df1f0e3Sstacktic .dom_maxrtkey = sizeof(struct sockaddr_in6),
1773df1f0e3Sstacktic .dom_ifattach = NULL,
1783df1f0e3Sstacktic .dom_ifdetach = NULL,
1793df1f0e3Sstacktic .dom_link = { NULL },
1803df1f0e3Sstacktic .dom_mowner = MOWNER_INIT("",""),
1813df1f0e3Sstacktic .dom_sockaddr_cmp = NULL
1823df1f0e3Sstacktic };
183ad9bbd7bSpooka
1848447026cSpooka #define SO2S(so) ((intptr_t)(so->so_internal))
1857dd6651aSpooka #define SOCKIN_SBSIZE 65536
186ad9bbd7bSpooka
187eebcd280Spooka struct sockin_unit {
188eebcd280Spooka struct socket *su_so;
189eebcd280Spooka
190eebcd280Spooka LIST_ENTRY(sockin_unit) su_entries;
191eebcd280Spooka };
192eebcd280Spooka static LIST_HEAD(, sockin_unit) su_ent = LIST_HEAD_INITIALIZER(su_ent);
193eebcd280Spooka static kmutex_t su_mtx;
194eebcd280Spooka static bool rebuild;
195eebcd280Spooka static int nsock;
196eebcd280Spooka
1973694a148Spooka /* XXX: for the bpf hack */
1983694a148Spooka static struct ifnet sockin_if;
ifpromisc(struct ifnet * ifp,int pswitch)1993694a148Spooka int ifpromisc(struct ifnet *ifp, int pswitch) { return 0; }
2003694a148Spooka
201eebcd280Spooka static int
registersock(struct socket * so,int news)202eebcd280Spooka registersock(struct socket *so, int news)
203eebcd280Spooka {
204eebcd280Spooka struct sockin_unit *su;
205eebcd280Spooka
206eebcd280Spooka su = kmem_alloc(sizeof(*su), KM_NOSLEEP);
207eebcd280Spooka if (!su)
208eebcd280Spooka return ENOMEM;
209eebcd280Spooka
210eebcd280Spooka so->so_internal = (void *)(intptr_t)news;
211eebcd280Spooka su->su_so = so;
212eebcd280Spooka
213eebcd280Spooka mutex_enter(&su_mtx);
214eebcd280Spooka LIST_INSERT_HEAD(&su_ent, su, su_entries);
215eebcd280Spooka nsock++;
216eebcd280Spooka rebuild = true;
217eebcd280Spooka mutex_exit(&su_mtx);
218eebcd280Spooka
219eebcd280Spooka return 0;
220eebcd280Spooka }
221eebcd280Spooka
222ad9bbd7bSpooka static void
removesock(struct socket * so)223d1543896Spooka removesock(struct socket *so)
224d1543896Spooka {
225d1543896Spooka struct sockin_unit *su_iter;
226d1543896Spooka
227d1543896Spooka mutex_enter(&su_mtx);
228d1543896Spooka LIST_FOREACH(su_iter, &su_ent, su_entries) {
229d1543896Spooka if (su_iter->su_so == so)
230d1543896Spooka break;
231d1543896Spooka }
232d1543896Spooka if (!su_iter)
233d1543896Spooka panic("no such socket");
234d1543896Spooka
235d1543896Spooka LIST_REMOVE(su_iter, su_entries);
236d1543896Spooka nsock--;
237d1543896Spooka rebuild = true;
238d1543896Spooka mutex_exit(&su_mtx);
239d1543896Spooka
24032a34307Spooka rumpuser_close(SO2S(su_iter->su_so));
241d1543896Spooka kmem_free(su_iter, sizeof(*su_iter));
242d1543896Spooka }
243d1543896Spooka
244d1543896Spooka static void
sockin_process(struct socket * so)245ad9bbd7bSpooka sockin_process(struct socket *so)
246ad9bbd7bSpooka {
2473df1f0e3Sstacktic struct sockaddr_in6 from;
248ad9bbd7bSpooka struct iovec io;
249ad9bbd7bSpooka struct msghdr rmsg;
250ad9bbd7bSpooka struct mbuf *m;
251b062b6a6Spooka size_t n, plen;
252ad9bbd7bSpooka int error;
253ad9bbd7bSpooka
254ad9bbd7bSpooka m = m_gethdr(M_WAIT, MT_DATA);
2558b70996eSpooka if (so->so_proto->pr_type == SOCK_DGRAM) {
2568b70996eSpooka plen = IP_MAXPACKET;
2578b70996eSpooka MEXTMALLOC(m, plen, M_DONTWAIT);
2588b70996eSpooka } else {
2598b70996eSpooka plen = MCLBYTES;
2608b70996eSpooka MCLGET(m, M_DONTWAIT);
2618b70996eSpooka }
2628b70996eSpooka if ((m->m_flags & M_EXT) == 0) {
2638b70996eSpooka m_freem(m);
2648b70996eSpooka return;
2658b70996eSpooka }
266ad9bbd7bSpooka
267ad9bbd7bSpooka memset(&rmsg, 0, sizeof(rmsg));
268ad9bbd7bSpooka io.iov_base = mtod(m, void *);
269ad9bbd7bSpooka io.iov_len = plen;
270ad9bbd7bSpooka rmsg.msg_iov = &io;
271ad9bbd7bSpooka rmsg.msg_iovlen = 1;
272ad9bbd7bSpooka rmsg.msg_name = (struct sockaddr *)&from;
273ad9bbd7bSpooka rmsg.msg_namelen = sizeof(from);
274ad9bbd7bSpooka
275b062b6a6Spooka error = rumpcomp_sockin_recvmsg(SO2S(so), &rmsg, 0, &n);
276b043cb36Spooka if (error || n == 0) {
277ad9bbd7bSpooka m_freem(m);
278d1543896Spooka
279d1543896Spooka /* Treat a TCP socket a goner */
2804581312dSpooka if (error != EAGAIN && so->so_proto->pr_type == SOCK_STREAM) {
281afe25e20Spooka mutex_enter(softnet_lock);
282d1543896Spooka soisdisconnected(so);
283afe25e20Spooka mutex_exit(softnet_lock);
284d1543896Spooka removesock(so);
285d1543896Spooka }
286ad9bbd7bSpooka return;
287ad9bbd7bSpooka }
288ad9bbd7bSpooka m->m_len = m->m_pkthdr.len = n;
289ad9bbd7bSpooka
2903cd62456Smsaitoh bpf_mtap_af(&sockin_if, AF_UNSPEC, m, BPF_D_IN);
2913694a148Spooka
292afe25e20Spooka mutex_enter(softnet_lock);
2937dd6651aSpooka if (so->so_proto->pr_type == SOCK_DGRAM) {
294ad9bbd7bSpooka if (!sbappendaddr(&so->so_rcv, rmsg.msg_name, m, NULL)) {
295ad9bbd7bSpooka m_freem(m);
296ad9bbd7bSpooka }
2977dd6651aSpooka } else {
2987dd6651aSpooka sbappendstream(&so->so_rcv, m);
2997dd6651aSpooka }
3007dd6651aSpooka
301ad9bbd7bSpooka sorwakeup(so);
302afe25e20Spooka mutex_exit(softnet_lock);
303ad9bbd7bSpooka }
304ad9bbd7bSpooka
305eebcd280Spooka static void
sockin_waccept(struct socket * so)3064a86612dSrtr sockin_waccept(struct socket *so)
307eebcd280Spooka {
308eebcd280Spooka struct socket *nso;
3093df1f0e3Sstacktic struct sockaddr_in6 sin;
310eebcd280Spooka int news, error, slen;
311eebcd280Spooka
312eebcd280Spooka slen = sizeof(sin);
31332a34307Spooka error = rumpcomp_sockin_accept(SO2S(so), (struct sockaddr *)&sin,
31432a34307Spooka &slen, &news);
31532a34307Spooka if (error)
316eebcd280Spooka return;
317eebcd280Spooka
318afe25e20Spooka mutex_enter(softnet_lock);
3198088e729Srmind nso = sonewconn(so, true);
320afe25e20Spooka if (nso == NULL)
321eebcd280Spooka goto errout;
322eebcd280Spooka if (registersock(nso, news) != 0)
323eebcd280Spooka goto errout;
324afe25e20Spooka mutex_exit(softnet_lock);
325eebcd280Spooka return;
326eebcd280Spooka
327eebcd280Spooka errout:
32832a34307Spooka rumpuser_close(news);
329eebcd280Spooka if (nso)
330eebcd280Spooka soclose(nso);
331afe25e20Spooka mutex_exit(softnet_lock);
332eebcd280Spooka }
333eebcd280Spooka
334ad9bbd7bSpooka #define POLLTIMEOUT 100 /* check for new entries every 100ms */
335ad9bbd7bSpooka
336ad9bbd7bSpooka /* XXX: doesn't handle socket (kernel) locking properly? */
337ad9bbd7bSpooka static void
sockinworker(void * arg)338ad9bbd7bSpooka sockinworker(void *arg)
339ad9bbd7bSpooka {
340ad9bbd7bSpooka struct pollfd *pfds = NULL, *npfds;
341ad9bbd7bSpooka struct sockin_unit *su_iter;
342eebcd280Spooka struct socket *so;
343ad9bbd7bSpooka int cursock = 0, i, rv, error;
344ad9bbd7bSpooka
345ad9bbd7bSpooka /*
346ad9bbd7bSpooka * Loop reading requests. Check for new sockets periodically
347ad9bbd7bSpooka * (could be smarter, but I'm lazy).
348ad9bbd7bSpooka */
349ad9bbd7bSpooka for (;;) {
350ad9bbd7bSpooka if (rebuild) {
351ad9bbd7bSpooka npfds = NULL;
352ad9bbd7bSpooka mutex_enter(&su_mtx);
353ad9bbd7bSpooka if (nsock)
354ad9bbd7bSpooka npfds = kmem_alloc(nsock * sizeof(*npfds),
355ad9bbd7bSpooka KM_NOSLEEP);
356ad9bbd7bSpooka if (npfds || nsock == 0) {
357ad9bbd7bSpooka if (pfds)
358ad9bbd7bSpooka kmem_free(pfds, cursock*sizeof(*pfds));
359ad9bbd7bSpooka pfds = npfds;
360ad9bbd7bSpooka cursock = nsock;
361ad9bbd7bSpooka rebuild = false;
362ad9bbd7bSpooka
363ad9bbd7bSpooka i = 0;
364ad9bbd7bSpooka LIST_FOREACH(su_iter, &su_ent, su_entries) {
365ad9bbd7bSpooka pfds[i].fd = SO2S(su_iter->su_so);
366ad9bbd7bSpooka pfds[i].events = POLLIN;
367ad9bbd7bSpooka pfds[i].revents = 0;
368ad9bbd7bSpooka i++;
369ad9bbd7bSpooka }
370ad9bbd7bSpooka KASSERT(i == nsock);
371ad9bbd7bSpooka }
372ad9bbd7bSpooka mutex_exit(&su_mtx);
373ad9bbd7bSpooka }
374ad9bbd7bSpooka
375ad9bbd7bSpooka /* find affected sockets & process */
37632a34307Spooka error = rumpcomp_sockin_poll(pfds, cursock, POLLTIMEOUT, &rv);
37732a34307Spooka for (i = 0; i < cursock && rv > 0 && error == 0; i++) {
378ad9bbd7bSpooka if (pfds[i].revents & POLLIN) {
379ad9bbd7bSpooka mutex_enter(&su_mtx);
380ad9bbd7bSpooka LIST_FOREACH(su_iter, &su_ent, su_entries) {
381ad9bbd7bSpooka if (SO2S(su_iter->su_so)==pfds[i].fd) {
382eebcd280Spooka so = su_iter->su_so;
383eebcd280Spooka mutex_exit(&su_mtx);
384eebcd280Spooka if(so->so_options&SO_ACCEPTCONN)
3854a86612dSrtr sockin_waccept(so);
386eebcd280Spooka else
387eebcd280Spooka sockin_process(so);
388eebcd280Spooka mutex_enter(&su_mtx);
389ad9bbd7bSpooka break;
390ad9bbd7bSpooka }
391ad9bbd7bSpooka }
392ad9bbd7bSpooka /* if we can't find it, just wing it */
393ad9bbd7bSpooka KASSERT(rebuild || su_iter);
394ad9bbd7bSpooka mutex_exit(&su_mtx);
395ad9bbd7bSpooka pfds[i].revents = 0;
396ad9bbd7bSpooka rv--;
397ad9bbd7bSpooka i = -1;
398ad9bbd7bSpooka continue;
399ad9bbd7bSpooka }
400ad9bbd7bSpooka
401ad9bbd7bSpooka /* something else? ignore */
402ad9bbd7bSpooka if (pfds[i].revents) {
403ad9bbd7bSpooka pfds[i].revents = 0;
404ad9bbd7bSpooka rv--;
405ad9bbd7bSpooka }
406ad9bbd7bSpooka }
407ad9bbd7bSpooka KASSERT(rv <= 0);
408ad9bbd7bSpooka }
409ad9bbd7bSpooka
410ad9bbd7bSpooka }
411ad9bbd7bSpooka
41253da9055Sstacktic static int
sockin_do_init(void)41353da9055Sstacktic sockin_do_init(void)
414ad9bbd7bSpooka {
415ad9bbd7bSpooka int rv;
416ad9bbd7bSpooka
41739cb5b51Spooka if (rump_threads) {
418ad9bbd7bSpooka if ((rv = kthread_create(PRI_NONE, 0, NULL, sockinworker,
419ad9bbd7bSpooka NULL, NULL, "sockwork")) != 0)
420ad9bbd7bSpooka panic("sockin_init: could not create worker thread\n");
42139cb5b51Spooka } else {
42239cb5b51Spooka printf("sockin_init: no threads => no worker thread\n");
42339cb5b51Spooka }
424ad9bbd7bSpooka mutex_init(&su_mtx, MUTEX_DEFAULT, IPL_NONE);
4253694a148Spooka strlcpy(sockin_if.if_xname, "sockin0", sizeof(sockin_if.if_xname));
42658e86755Sjoerg bpf_attach(&sockin_if, DLT_NULL, 0);
42753da9055Sstacktic return 0;
42853da9055Sstacktic }
42953da9055Sstacktic
43053da9055Sstacktic static void
sockin_init(void)43153da9055Sstacktic sockin_init(void)
43253da9055Sstacktic {
43353da9055Sstacktic static ONCE_DECL(init);
43453da9055Sstacktic
43553da9055Sstacktic RUN_ONCE(&init, sockin_do_init);
436ad9bbd7bSpooka }
437ad9bbd7bSpooka
438ad9bbd7bSpooka static int
sockin_attach(struct socket * so,int proto)4394ae03c18Srmind sockin_attach(struct socket *so, int proto)
440ad9bbd7bSpooka {
4414ae03c18Srmind const int type = so->so_proto->pr_type;
4424ae03c18Srmind int error, news, family;
443ad9bbd7bSpooka
444ad9bbd7bSpooka sosetlock(so);
4457dd6651aSpooka if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
4467dd6651aSpooka error = soreserve(so, SOCKIN_SBSIZE, SOCKIN_SBSIZE);
4477dd6651aSpooka if (error)
4484ae03c18Srmind return error;
4497dd6651aSpooka }
450ad9bbd7bSpooka
4513731822aSpooka family = so->so_proto->pr_domain->dom_family;
4523731822aSpooka KASSERT(family == PF_INET || family == PF_INET6);
4534ae03c18Srmind error = rumpcomp_sockin_socket(family, type, 0, &news);
454b062b6a6Spooka if (error)
4554ae03c18Srmind return error;
456ad9bbd7bSpooka
4574ae03c18Srmind /* For UDP sockets, make sure we can send/recv maximum. */
4584ae03c18Srmind if (type == SOCK_DGRAM) {
4594ae03c18Srmind int sbsize = SOCKIN_SBSIZE;
46032a34307Spooka error = rumpcomp_sockin_setsockopt(news,
461e3425032Spooka SOL_SOCKET, SO_SNDBUF,
46232a34307Spooka &sbsize, sizeof(sbsize));
463291f141cSpooka sbsize = SOCKIN_SBSIZE;
46432a34307Spooka error = rumpcomp_sockin_setsockopt(news,
465e3425032Spooka SOL_SOCKET, SO_RCVBUF,
46632a34307Spooka &sbsize, sizeof(sbsize));
467291f141cSpooka }
468291f141cSpooka
469eebcd280Spooka if ((error = registersock(so, news)) != 0)
47032a34307Spooka rumpuser_close(news);
471eebcd280Spooka
4724ae03c18Srmind return error;
473ad9bbd7bSpooka }
474ad9bbd7bSpooka
4754ae03c18Srmind static void
sockin_detach(struct socket * so)4764ae03c18Srmind sockin_detach(struct socket *so)
4774ae03c18Srmind {
4784ae03c18Srmind panic("sockin_detach: IMPLEMENT ME\n");
4794ae03c18Srmind }
4804ae03c18Srmind
4814ae03c18Srmind static int
sockin_accept(struct socket * so,struct sockaddr * nam)482eddf3af3Srtr sockin_accept(struct socket *so, struct sockaddr *nam)
483d27b133dSrtr {
484d27b133dSrtr KASSERT(solocked(so));
485d27b133dSrtr
486d27b133dSrtr /* we do all the work in the worker thread */
487d27b133dSrtr return 0;
488d27b133dSrtr }
489d27b133dSrtr
490d27b133dSrtr static int
sockin_bind(struct socket * so,struct sockaddr * nam,struct lwp * l)491a2ba5e69Srtr sockin_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
4926dd8eef0Srtr {
4936dd8eef0Srtr KASSERT(solocked(so));
4946dd8eef0Srtr KASSERT(nam != NULL);
4956dd8eef0Srtr
496a2ba5e69Srtr return rumpcomp_sockin_bind(SO2S(so), nam, nam->sa_len);
4976dd8eef0Srtr }
4986dd8eef0Srtr
4996dd8eef0Srtr static int
sockin_listen(struct socket * so,struct lwp * l)500ce6a5ff6Srtr sockin_listen(struct socket *so, struct lwp *l)
5016dd8eef0Srtr {
5026dd8eef0Srtr KASSERT(solocked(so));
5036dd8eef0Srtr
5046dd8eef0Srtr return rumpcomp_sockin_listen(SO2S(so), so->so_qlimit);
5056dd8eef0Srtr }
5066dd8eef0Srtr
5076dd8eef0Srtr static int
sockin_connect(struct socket * so,struct sockaddr * nam,struct lwp * l)508fd12cf39Srtr sockin_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
509ad6ae402Srtr {
510ad6ae402Srtr int error = 0;
511ad6ae402Srtr
512ad6ae402Srtr KASSERT(solocked(so));
513ad6ae402Srtr KASSERT(nam != NULL);
514ad6ae402Srtr
515fd12cf39Srtr error = rumpcomp_sockin_connect(SO2S(so), nam, nam->sa_len);
516ad6ae402Srtr if (error == 0)
517ad6ae402Srtr soisconnected(so);
518ad6ae402Srtr
519ad6ae402Srtr return error;
520ad6ae402Srtr }
521ad6ae402Srtr
522892163b8Srtr static int
sockin_connect2(struct socket * so,struct socket * so2)5238cf67cc6Srtr sockin_connect2(struct socket *so, struct socket *so2)
5248cf67cc6Srtr {
5258cf67cc6Srtr KASSERT(solocked(so));
5268cf67cc6Srtr
5278cf67cc6Srtr panic("sockin_connect2: IMPLEMENT ME, connect2 not supported");
5288cf67cc6Srtr }
5298cf67cc6Srtr
5308cf67cc6Srtr static int
sockin_disconnect(struct socket * so)531892163b8Srtr sockin_disconnect(struct socket *so)
532892163b8Srtr {
533892163b8Srtr KASSERT(solocked(so));
534892163b8Srtr
535892163b8Srtr panic("sockin_disconnect: IMPLEMENT ME, disconnect not supported");
536892163b8Srtr }
537892163b8Srtr
538892163b8Srtr static int
sockin_shutdown(struct socket * so)539892163b8Srtr sockin_shutdown(struct socket *so)
540892163b8Srtr {
541892163b8Srtr KASSERT(solocked(so));
542892163b8Srtr
543892163b8Srtr removesock(so);
544892163b8Srtr return 0;
545892163b8Srtr }
546892163b8Srtr
547892163b8Srtr static int
sockin_abort(struct socket * so)548892163b8Srtr sockin_abort(struct socket *so)
549892163b8Srtr {
550892163b8Srtr KASSERT(solocked(so));
551892163b8Srtr
552892163b8Srtr panic("sockin_abort: IMPLEMENT ME, abort not supported");
553892163b8Srtr }
554ad6ae402Srtr
555ad6ae402Srtr static int
sockin_ioctl(struct socket * so,u_long cmd,void * nam,struct ifnet * ifp)5560dedd977Srtr sockin_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
557d54d7ab2Srtr {
558d54d7ab2Srtr return ENOTTY;
559d54d7ab2Srtr }
560d54d7ab2Srtr
561d54d7ab2Srtr static int
sockin_stat(struct socket * so,struct stat * ub)5620f199192Srtr sockin_stat(struct socket *so, struct stat *ub)
5630f199192Srtr {
564ff90c29dSrtr KASSERT(solocked(so));
565ff90c29dSrtr
566909a1fc6Srtr return 0;
5670f199192Srtr }
5680f199192Srtr
5690f199192Srtr static int
sockin_peeraddr(struct socket * so,struct sockaddr * nam)570eddf3af3Srtr sockin_peeraddr(struct socket *so, struct sockaddr *nam)
571d575eb54Srtr {
572d575eb54Srtr KASSERT(solocked(so));
573d575eb54Srtr
574d575eb54Srtr int error = 0;
575eddf3af3Srtr int slen = nam->sa_len;
576d575eb54Srtr
577d575eb54Srtr error = rumpcomp_sockin_getname(SO2S(so),
578eddf3af3Srtr nam, &slen, RUMPCOMP_SOCKIN_PEERNAME);
579d575eb54Srtr if (error == 0)
580eddf3af3Srtr nam->sa_len = slen;
581d575eb54Srtr return error;
582d575eb54Srtr }
583d575eb54Srtr
584d575eb54Srtr static int
sockin_sockaddr(struct socket * so,struct sockaddr * nam)585eddf3af3Srtr sockin_sockaddr(struct socket *so, struct sockaddr *nam)
586d575eb54Srtr {
587d575eb54Srtr KASSERT(solocked(so));
588d575eb54Srtr
589d575eb54Srtr int error = 0;
590eddf3af3Srtr int slen = nam->sa_len;
591d575eb54Srtr
592d575eb54Srtr error = rumpcomp_sockin_getname(SO2S(so),
593eddf3af3Srtr nam, &slen, RUMPCOMP_SOCKIN_SOCKNAME);
594d575eb54Srtr if (error == 0)
595eddf3af3Srtr nam->sa_len = slen;
596d575eb54Srtr return error;
597d575eb54Srtr }
598d575eb54Srtr
599d575eb54Srtr static int
sockin_rcvd(struct socket * so,int flags,struct lwp * l)600822872eaSrtr sockin_rcvd(struct socket *so, int flags, struct lwp *l)
601822872eaSrtr {
602822872eaSrtr KASSERT(solocked(so));
603822872eaSrtr
604822872eaSrtr panic("sockin_rcvd: IMPLEMENT ME, rcvd not supported");
605822872eaSrtr }
606822872eaSrtr
607822872eaSrtr static int
sockin_recvoob(struct socket * so,struct mbuf * m,int flags)60835b22fa9Srtr sockin_recvoob(struct socket *so, struct mbuf *m, int flags)
60935b22fa9Srtr {
610892163b8Srtr KASSERT(solocked(so));
611892163b8Srtr
61235b22fa9Srtr panic("sockin_recvoob: IMPLEMENT ME, recvoob not supported");
61335b22fa9Srtr }
61435b22fa9Srtr
61535b22fa9Srtr static int
sockin_send(struct socket * so,struct mbuf * m,struct sockaddr * saddr,struct mbuf * control,struct lwp * l)616fd12cf39Srtr sockin_send(struct socket *so, struct mbuf *m, struct sockaddr *saddr,
6174ae03c18Srmind struct mbuf *control, struct lwp *l)
6184ae03c18Srmind {
619ad9bbd7bSpooka struct msghdr mhdr;
6208cd44ca8Stron size_t iov_max, i;
6213ad0ebd5Stron struct iovec iov_buf[32], *iov;
622ad9bbd7bSpooka struct mbuf *m2;
623b062b6a6Spooka size_t tot, n;
624651e5bd3Srtr int error = 0;
6258cd44ca8Stron int s;
626ad9bbd7bSpooka
6273cd62456Smsaitoh bpf_mtap_af(&sockin_if, AF_UNSPEC, m, BPF_D_OUT);
6283694a148Spooka
629ad9bbd7bSpooka memset(&mhdr, 0, sizeof(mhdr));
630ad9bbd7bSpooka
6318cd44ca8Stron iov_max = 0;
6328cd44ca8Stron for (m2 = m; m2 != NULL; m2 = m2->m_next) {
6338cd44ca8Stron iov_max++;
6348cd44ca8Stron }
6358cd44ca8Stron
6363ad0ebd5Stron if (iov_max <= __arraycount(iov_buf)) {
6373ad0ebd5Stron iov = iov_buf;
6383ad0ebd5Stron } else {
6393ad0ebd5Stron iov = kmem_alloc(sizeof(struct iovec) * iov_max,
6403ad0ebd5Stron KM_SLEEP);
6413ad0ebd5Stron }
6428cd44ca8Stron
643ad9bbd7bSpooka tot = 0;
6448cd44ca8Stron for (i = 0, m2 = m; m2 != NULL; m2 = m2->m_next, i++) {
645ad9bbd7bSpooka iov[i].iov_base = m2->m_data;
646ad9bbd7bSpooka iov[i].iov_len = m2->m_len;
647ad9bbd7bSpooka tot += m2->m_len;
648ad9bbd7bSpooka }
6497dd6651aSpooka mhdr.msg_iov = iov;
6507dd6651aSpooka mhdr.msg_iovlen = i;
6518447026cSpooka s = SO2S(so);
6527dd6651aSpooka
653fd12cf39Srtr if (saddr != NULL) {
654bcf80a6fSpooka mhdr.msg_name = saddr;
655bcf80a6fSpooka mhdr.msg_namelen = saddr->sa_len;
656bcf80a6fSpooka }
657bcf80a6fSpooka
658b062b6a6Spooka rumpcomp_sockin_sendmsg(s, &mhdr, 0, &n);
6597dd6651aSpooka
6603ad0ebd5Stron if (iov != iov_buf)
6618cd44ca8Stron kmem_free(iov, sizeof(struct iovec) * iov_max);
6628cd44ca8Stron
663ad9bbd7bSpooka m_freem(m);
664ad9bbd7bSpooka m_freem(control);
66539cb5b51Spooka
666ad9bbd7bSpooka /* this assumes too many things to list.. buthey, testing */
66739cb5b51Spooka if (!rump_threads)
668ad9bbd7bSpooka sockin_process(so);
669ad9bbd7bSpooka
670651e5bd3Srtr return error;
671651e5bd3Srtr }
672651e5bd3Srtr
673651e5bd3Srtr static int
sockin_sendoob(struct socket * so,struct mbuf * m,struct mbuf * control)674651e5bd3Srtr sockin_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
675651e5bd3Srtr {
676651e5bd3Srtr KASSERT(solocked(so));
677651e5bd3Srtr
678651e5bd3Srtr panic("sockin_sendoob: IMPLEMENT ME, sendoob not supported");
679651e5bd3Srtr }
680651e5bd3Srtr
681651e5bd3Srtr static int
sockin_purgeif(struct socket * so,struct ifnet * ifp)6828cf67cc6Srtr sockin_purgeif(struct socket *so, struct ifnet *ifp)
6838cf67cc6Srtr {
6848cf67cc6Srtr
6858cf67cc6Srtr panic("sockin_purgeif: IMPLEMENT ME, purgeif not supported");
6868cf67cc6Srtr }
6878cf67cc6Srtr
6888cf67cc6Srtr static int
sockin_ctloutput(int op,struct socket * so,struct sockopt * sopt)689eaff187cSpooka sockin_ctloutput(int op, struct socket *so, struct sockopt *sopt)
690eaff187cSpooka {
691eaff187cSpooka
69232a34307Spooka return rumpcomp_sockin_setsockopt(SO2S(so), sopt->sopt_level,
69332a34307Spooka sopt->sopt_name, sopt->sopt_data, sopt->sopt_size);
694eaff187cSpooka }
695cd5f3c7dSpooka
696cd5f3c7dSpooka int sockin_unavailable(void);
697cd5f3c7dSpooka int
sockin_unavailable(void)698cd5f3c7dSpooka sockin_unavailable(void)
699cd5f3c7dSpooka {
700cd5f3c7dSpooka
701cd5f3c7dSpooka panic("interface not available in with sockin");
702cd5f3c7dSpooka }
703cd5f3c7dSpooka __strong_alias(rtrequest,sockin_unavailable);
704cd5f3c7dSpooka __strong_alias(ifunit,sockin_unavailable);
705cd5f3c7dSpooka __strong_alias(ifreq_setaddr,sockin_unavailable);
706aeb231ccSozaki-r __strong_alias(rt_delete_matched_entries,sockin_unavailable);
707