Home | History | Annotate | Line # | Download | only in libsockin
sockin_user.c revision 1.3
      1 /*	$NetBSD: sockin_user.c,v 1.3 2019/01/27 02:08:50 pgoyette Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2008 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_user.c,v 1.3 2019/01/27 02:08:50 pgoyette Exp $");
     30 
     31 /* for struct msghdr content visibility */
     32 #define _XOPEN_SOURCE 4
     33 #define _XOPEN_SOURCE_EXTENDED 1
     34 
     35 #ifndef _KERNEL
     36 #include <sys/types.h>
     37 #include <sys/socket.h>
     38 
     39 #include <errno.h>
     40 #include <poll.h>
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include <stdint.h>
     44 
     45 #include <rump/rumpuser_component.h>
     46 #include <rump/rumpdefs.h>
     47 
     48 #include "sockin_user.h"
     49 
     50 #define seterror(_v_) if ((_v_) == -1) rv = errno; else rv = 0;
     51 
     52 #ifndef __arraycount
     53 #define __arraycount(a) (sizeof(a) / sizeof(*a))
     54 #endif
     55 
     56 #ifndef __UNCONST
     57 #define __UNCONST(a) ((void*)(const void*)a)
     58 #endif
     59 
     60 #include <netinet/in.h>
     61 #include <netinet/tcp.h>
     62 #include <netinet/udp.h>
     63 
     64 
     65 static int translate_so_sockopt(int);
     66 static int translate_ip_sockopt(int);
     67 static int translate_tcp_sockopt(int);
     68 static int translate_domain(int);
     69 
     70 #define translate(_a_) case RUMP_##_a_: return _a_
     71 static int
     72 translate_so_sockopt(int lopt)
     73 {
     74 
     75 	switch (lopt) {
     76 	translate(SO_DEBUG);
     77 #ifndef SO_REUSEPORT
     78 	case RUMP_SO_REUSEPORT: return SO_REUSEADDR;
     79 #else
     80 	translate(SO_REUSEPORT);
     81 #endif
     82 	translate(SO_TYPE);
     83 	translate(SO_ERROR);
     84 	translate(SO_DONTROUTE);
     85 	translate(SO_BROADCAST);
     86 	translate(SO_SNDBUF);
     87 	translate(SO_RCVBUF);
     88 	translate(SO_KEEPALIVE);
     89 	translate(SO_OOBINLINE);
     90 	translate(SO_LINGER);
     91 	default: return -1;
     92 	}
     93 }
     94 
     95 static int
     96 translate_ip_sockopt(int lopt)
     97 {
     98 
     99 	switch (lopt) {
    100 	translate(IP_TOS);
    101 	translate(IP_TTL);
    102 	translate(IP_HDRINCL);
    103 	translate(IP_MULTICAST_TTL);
    104 	translate(IP_MULTICAST_LOOP);
    105 	translate(IP_MULTICAST_IF);
    106 	translate(IP_ADD_MEMBERSHIP);
    107 	translate(IP_DROP_MEMBERSHIP);
    108 	default: return -1;
    109 	}
    110 }
    111 
    112 static int
    113 translate_tcp_sockopt(int lopt)
    114 {
    115 
    116 	switch (lopt) {
    117 	translate(TCP_NODELAY);
    118 	translate(TCP_MAXSEG);
    119 	default: return -1;
    120 	}
    121 }
    122 
    123 static int
    124 translate_domain(int domain)
    125 {
    126 
    127 	switch (domain) {
    128 	translate(AF_INET);
    129 	translate(AF_INET6);
    130 	default: return AF_UNSPEC;
    131 	}
    132 }
    133 
    134 #undef translate
    135 
    136 static void
    137 translate_sockopt(int *levelp, int *namep)
    138 {
    139 	int level, name;
    140 
    141 	level = *levelp;
    142 	name = *namep;
    143 
    144 	switch (level) {
    145 	case RUMP_SOL_SOCKET:
    146 		level = SOL_SOCKET;
    147 		name = translate_so_sockopt(name);
    148 		break;
    149 	case RUMP_IPPROTO_IP:
    150 #ifdef SOL_IP
    151 		level = SOL_IP;
    152 #else
    153 		level = IPPROTO_IP;
    154 #endif
    155 		name = translate_ip_sockopt(name);
    156 		break;
    157 	case RUMP_IPPROTO_TCP:
    158 #ifdef SOL_TCP
    159 		level = SOL_TCP;
    160 #else
    161 		level = IPPROTO_TCP;
    162 #endif
    163 		name = translate_tcp_sockopt(name);
    164 		break;
    165 	case RUMP_IPPROTO_UDP:
    166 #ifdef SOL_UDP
    167 		level = SOL_UDP;
    168 #else
    169 		level = IPPROTO_UDP;
    170 #endif
    171 		name = -1;
    172 		break;
    173 	default:
    174 		level = -1;
    175 	}
    176 	*levelp = level;
    177 	*namep = name;
    178 }
    179 
    180 #ifndef __NetBSD__
    181 static const struct {
    182 	int bfl;
    183 	int lfl;
    184 } bsd_to_native_msg_flags_[] = {
    185 	{RUMP_MSG_OOB,		MSG_OOB},
    186 	{RUMP_MSG_PEEK,		MSG_PEEK},
    187 	{RUMP_MSG_DONTROUTE,	MSG_DONTROUTE},
    188 	{RUMP_MSG_EOR,		MSG_EOR},
    189 	{RUMP_MSG_TRUNC,	MSG_TRUNC},
    190 	{RUMP_MSG_CTRUNC,	MSG_CTRUNC},
    191 	{RUMP_MSG_WAITALL,	MSG_WAITALL},
    192 	{RUMP_MSG_DONTWAIT,	MSG_DONTWAIT},
    193 
    194 	/* might be better to always set NOSIGNAL ... */
    195 #ifdef MSG_NOSIGNAL
    196 	{RUMP_MSG_NOSIGNAL,	MSG_NOSIGNAL},
    197 #endif
    198 };
    199 
    200 static int native_to_bsd_msg_flags(int);
    201 
    202 static int
    203 native_to_bsd_msg_flags(int lflag)
    204 {
    205 	unsigned int i;
    206 	int bfl, lfl;
    207 	int bflag = 0;
    208 
    209 	if (lflag == 0)
    210 		return (0);
    211 
    212 	for(i = 0; i < __arraycount(bsd_to_native_msg_flags_); i++) {
    213 		bfl = bsd_to_native_msg_flags_[i].bfl;
    214 		lfl = bsd_to_native_msg_flags_[i].lfl;
    215 
    216 		if (lflag & lfl) {
    217 			lflag ^= lfl;
    218 			bflag |= bfl;
    219 		}
    220 	}
    221 	if (lflag != 0)
    222 		return (-1);
    223 
    224 	return (bflag);
    225 }
    226 
    227 static int
    228 bsd_to_native_msg_flags(int bflag)
    229 {
    230 	unsigned int i;
    231 	int lflag = 0;
    232 
    233 	if (bflag == 0)
    234 		return (0);
    235 
    236 	for(i = 0; i < __arraycount(bsd_to_native_msg_flags_); i++) {
    237 		if (bflag & bsd_to_native_msg_flags_[i].bfl)
    238 			lflag |= bsd_to_native_msg_flags_[i].lfl;
    239 	}
    240 
    241 	return (lflag);
    242 }
    243 #endif
    244 
    245 struct rump_sockaddr {
    246 	uint8_t	sa_len;	    /* total length */
    247 	uint8_t	sa_family;	/* address family */
    248 	char	sa_data[14];	/* actually longer; address value */
    249 };
    250 
    251 struct rump_msghdr {
    252 	void		*msg_name;	/* optional address */
    253 	uint32_t	msg_namelen;	/* size of address */
    254 	struct iovec	*msg_iov;	/* scatter/gather array */
    255 	int		msg_iovlen;	/* # elements in msg_iov */
    256 	void		*msg_control;	/* ancillary data, see below */
    257 	uint32_t	msg_controllen;	/* ancillary data buffer len */
    258 	int		msg_flags;	/* flags on received message */
    259 };
    260 
    261 static struct sockaddr *translate_sockaddr(const struct sockaddr *,
    262 		uint32_t);
    263 static void translate_sockaddr_back(const struct sockaddr *,
    264 		struct rump_sockaddr *, uint32_t len);
    265 static struct msghdr *translate_msghdr(const struct rump_msghdr *, int *);
    266 static void translate_msghdr_back(const struct msghdr *, struct rump_msghdr *);
    267 
    268 #if defined(__NetBSD__)
    269 static struct sockaddr *
    270 translate_sockaddr(const struct sockaddr *addr, uint32_t len)
    271 {
    272 
    273 	return (struct sockaddr *)__UNCONST(addr);
    274 }
    275 
    276 static void
    277 translate_sockaddr_back(const struct sockaddr *laddr,
    278 		struct rump_sockaddr *baddr, uint32_t len)
    279 {
    280 
    281 	return;
    282 }
    283 
    284 static struct msghdr *
    285 translate_msghdr(const struct rump_msghdr *bmsg, int *flags)
    286 {
    287 
    288 	return (struct msghdr *)__UNCONST(bmsg);
    289 }
    290 
    291 static void
    292 translate_msghdr_back(const struct msghdr *lmsg, struct rump_msghdr *bmsg)
    293 {
    294 
    295 	return;
    296 }
    297 
    298 #else
    299 static struct sockaddr *
    300 translate_sockaddr(const struct sockaddr *addr, uint32_t len)
    301 {
    302 	struct sockaddr *laddr;
    303 	const struct rump_sockaddr *baddr;
    304 
    305 	baddr = (const struct rump_sockaddr *)addr;
    306 	laddr = malloc(len);
    307 	if (laddr == NULL)
    308 		return NULL;
    309 	memcpy(laddr, baddr, len);
    310 	laddr->sa_family = translate_domain(baddr->sa_family);
    311 	/* No sa_len for Linux and SunOS */
    312 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
    313 	laddr->sa_len = len;
    314 #endif
    315 	return laddr;
    316 }
    317 
    318 #define translate_back(_a_) case _a_: return RUMP_##_a_
    319 static int translate_domain_back(int);
    320 static int
    321 translate_domain_back(int domain)
    322 {
    323 
    324 	switch (domain) {
    325 	translate_back(AF_INET);
    326 	translate_back(AF_INET6);
    327 	default: return RUMP_AF_UNSPEC;
    328 	}
    329 }
    330 #undef translate_back
    331 
    332 static void
    333 translate_sockaddr_back(const struct sockaddr *laddr,
    334 		struct rump_sockaddr *baddr,
    335 		uint32_t len)
    336 {
    337 
    338 	if (baddr != NULL) {
    339 		memcpy(baddr, laddr, len);
    340 		baddr->sa_family = translate_domain_back(laddr->sa_family);
    341 		baddr->sa_len = len;
    342 	}
    343 	free(__UNCONST(laddr));
    344 }
    345 
    346 static struct msghdr *
    347 translate_msghdr(const struct rump_msghdr *bmsg, int *flags)
    348 {
    349 	struct msghdr *rv;
    350 
    351 	*flags = bsd_to_native_msg_flags(*flags);
    352 	if (*flags < 0)
    353 		*flags = 0;
    354 
    355 	rv = malloc(sizeof(*rv));
    356 	rv->msg_namelen = bmsg->msg_namelen;
    357 	rv->msg_iov = bmsg->msg_iov;
    358 	rv->msg_iovlen = bmsg->msg_iovlen;
    359 	rv->msg_control = bmsg->msg_control;
    360 	rv->msg_controllen = bmsg->msg_controllen;
    361 	rv->msg_flags = 0;
    362 
    363 	if (bmsg->msg_name != NULL) {
    364 		rv->msg_name = translate_sockaddr(bmsg->msg_name,
    365 				bmsg->msg_namelen);
    366 		if (rv->msg_name == NULL) {
    367 			free(rv);
    368 			return NULL;
    369 		}
    370 	} else
    371 		rv->msg_name = NULL;
    372 	return rv;
    373 }
    374 
    375 static void
    376 translate_msghdr_back(const struct msghdr *lmsg, struct rump_msghdr *bmsg)
    377 {
    378 
    379 	if (bmsg == NULL) {
    380 		if (lmsg->msg_name != NULL)
    381 			free(lmsg->msg_name);
    382 		free(__UNCONST(lmsg));
    383 		return;
    384 	}
    385 	bmsg->msg_namelen = lmsg->msg_namelen;
    386 	bmsg->msg_iov = lmsg->msg_iov;
    387 	bmsg->msg_iovlen = lmsg->msg_iovlen;
    388 	bmsg->msg_control = lmsg->msg_control;
    389 	bmsg->msg_controllen = lmsg->msg_controllen;
    390 	bmsg->msg_flags = native_to_bsd_msg_flags(lmsg->msg_flags);
    391 
    392 	if (lmsg->msg_name != NULL)
    393 		translate_sockaddr_back(lmsg->msg_name, bmsg->msg_name,
    394 				bmsg->msg_namelen);
    395 	else
    396 		bmsg->msg_name = NULL;
    397 
    398 	free(__UNCONST(lmsg));
    399 }
    400 #endif
    401 
    402 int
    403 rumpcomp_sockin_socket(int domain, int type, int proto, int *s)
    404 {
    405 	void *cookie;
    406 	int rv;
    407 
    408 	domain = translate_domain(domain);
    409 
    410 	cookie = rumpuser_component_unschedule();
    411 	*s = socket(domain, type, proto);
    412 	seterror(*s);
    413 	rumpuser_component_schedule(cookie);
    414 
    415 	return rumpuser_component_errtrans(rv);
    416 }
    417 
    418 int
    419 rumpcomp_sockin_sendmsg(int s, const struct msghdr *msg, int flags, size_t *snd)
    420 {
    421 	void *cookie;
    422 	ssize_t nn;
    423 	int rv;
    424 
    425 	msg = translate_msghdr((struct rump_msghdr *)msg, &flags);
    426 
    427 	cookie = rumpuser_component_unschedule();
    428 	nn = sendmsg(s, msg, flags);
    429 	seterror(nn);
    430 	*snd = (size_t)nn;
    431 	rumpuser_component_schedule(cookie);
    432 
    433 	translate_msghdr_back(msg, NULL);
    434 
    435 	return rumpuser_component_errtrans(rv);
    436 }
    437 
    438 int
    439 rumpcomp_sockin_recvmsg(int s, struct msghdr *msg, int flags, size_t *rcv)
    440 {
    441 	void *cookie;
    442 	ssize_t nn;
    443 	int rv;
    444 	struct rump_msghdr *saveptr;
    445 
    446 	saveptr = (struct rump_msghdr *)msg;
    447 	msg = translate_msghdr(saveptr, &flags);
    448 
    449 	cookie = rumpuser_component_unschedule();
    450 	nn = recvmsg(s, msg, flags);
    451 	seterror(nn);
    452 	*rcv = (size_t)nn;
    453 	rumpuser_component_schedule(cookie);
    454 
    455 	translate_msghdr_back(msg, saveptr);
    456 
    457 	return rumpuser_component_errtrans(rv);
    458 }
    459 
    460 int
    461 rumpcomp_sockin_connect(int s, const struct sockaddr *name, int len)
    462 {
    463 	void *cookie;
    464 	int rv;
    465 
    466 	name = translate_sockaddr(name, len);
    467 
    468 	cookie = rumpuser_component_unschedule();
    469 	rv = connect(s, name, (socklen_t)len);
    470 	seterror(rv);
    471 	rumpuser_component_schedule(cookie);
    472 
    473 	translate_sockaddr_back(name, NULL, len);
    474 
    475 	return rumpuser_component_errtrans(rv);
    476 }
    477 
    478 int
    479 rumpcomp_sockin_bind(int s, const struct sockaddr *name, int len)
    480 {
    481 	void *cookie;
    482 	int rv;
    483 
    484 	name = translate_sockaddr(name, len);
    485 
    486 	cookie = rumpuser_component_unschedule();
    487 	rv = bind(s, name, (socklen_t)len);
    488 	seterror(rv);
    489 	rumpuser_component_schedule(cookie);
    490 
    491 	translate_sockaddr_back(name, NULL, len);
    492 
    493 	return rumpuser_component_errtrans(rv);
    494 }
    495 
    496 int
    497 rumpcomp_sockin_accept(int s, struct sockaddr *name, int *lenp, int *s2)
    498 {
    499 	void *cookie;
    500 	int rv;
    501 	struct rump_sockaddr *saveptr;
    502 
    503 	saveptr = (struct rump_sockaddr *)name;
    504 	name = translate_sockaddr(name, *lenp);
    505 
    506 	cookie = rumpuser_component_unschedule();
    507 	*s2 = accept(s, name, (socklen_t *)lenp);
    508 	seterror(*s2);
    509 	rumpuser_component_schedule(cookie);
    510 
    511 	translate_sockaddr_back(name, saveptr, *lenp);
    512 
    513 	return rumpuser_component_errtrans(rv);
    514 }
    515 
    516 int
    517 rumpcomp_sockin_listen(int s, int backlog)
    518 {
    519 	void *cookie;
    520 	int rv;
    521 
    522 	cookie = rumpuser_component_unschedule();
    523 	rv = listen(s, backlog);
    524 	seterror(rv);
    525 	rumpuser_component_schedule(cookie);
    526 
    527 	return rumpuser_component_errtrans(rv);
    528 }
    529 
    530 int
    531 rumpcomp_sockin_getname(int s, struct sockaddr *so, int *lenp,
    532 	enum rumpcomp_sockin_getnametype which)
    533 {
    534 	socklen_t slen = *lenp;
    535 	int rv;
    536 	struct rump_sockaddr *saveptr;
    537 
    538 	saveptr = (struct rump_sockaddr *)so;
    539 	so = translate_sockaddr(so, *lenp);
    540 
    541 	if (which == RUMPCOMP_SOCKIN_SOCKNAME)
    542 		rv = getsockname(s, so, &slen);
    543 	else
    544 		rv = getpeername(s, so, &slen);
    545 
    546 	seterror(rv);
    547 	translate_sockaddr_back(so, saveptr, *lenp);
    548 
    549 	*lenp = slen;
    550 
    551 	return rumpuser_component_errtrans(rv);
    552 }
    553 
    554 int
    555 rumpcomp_sockin_setsockopt(int s, int level, int name,
    556 	const void *data, int dlen)
    557 {
    558 	socklen_t slen = dlen;
    559 	int rv;
    560 
    561 	translate_sockopt(&level, &name);
    562 	if (level == -1 || name == -1) {
    563 #ifdef SETSOCKOPT_STRICT
    564 		errno = EINVAL;
    565 		rv = -1;
    566 #else
    567 		rv = 0;
    568 #endif
    569 	} else
    570 		rv = setsockopt(s, level, name, data, slen);
    571 
    572 	seterror(rv);
    573 
    574 	return rumpuser_component_errtrans(rv);
    575 }
    576 
    577 int
    578 rumpcomp_sockin_poll(struct pollfd *fds, int nfds, int timeout, int *nready)
    579 {
    580 	void *cookie;
    581 	int rv;
    582 
    583 	cookie = rumpuser_component_unschedule();
    584 	*nready = poll(fds, (nfds_t)nfds, timeout);
    585 	seterror(*nready);
    586 	rumpuser_component_schedule(cookie);
    587 
    588 	return rumpuser_component_errtrans(rv);
    589 }
    590 #endif
    591