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