passt: Fix build with gcc 7, use std=c99, enable some more Clang checkers

Unions and structs, you all have names now.

Take the chance to enable bugprone-reserved-identifier,
cert-dcl37-c, and cert-dcl51-cpp checkers in clang-tidy.

Provide a ffsl() weak declaration using gcc built-in.

Start reordering includes, but that's not enough for the
llvm-include-order checker yet.

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
Stefano Brivio 2021-10-21 04:26:08 +02:00
parent 6257a2752e
commit dd942eaa48
24 changed files with 300 additions and 284 deletions

View file

@ -9,7 +9,7 @@
# Copyright (c) 2021 Red Hat GmbH # Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com> # Author: Stefano Brivio <sbrivio@redhat.com>
CFLAGS += -Wall -Wextra -pedantic CFLAGS += -Wall -Wextra -pedantic -std=c99 -D_XOPEN_SOURCE=700 -D_GNU_SOURCE
CFLAGS += -DRLIMIT_STACK_VAL=$(shell ulimit -s) CFLAGS += -DRLIMIT_STACK_VAL=$(shell ulimit -s)
CFLAGS += -DPAGE_SIZE=$(shell getconf PAGE_SIZE) CFLAGS += -DPAGE_SIZE=$(shell getconf PAGE_SIZE)
CFLAGS += -DNETNS_RUN_DIR=\"/run/netns\" CFLAGS += -DNETNS_RUN_DIR=\"/run/netns\"
@ -120,9 +120,6 @@ pkgs:
# - hicpp-signed-bitwise # - hicpp-signed-bitwise
# Those are needed for syscalls, epoll_wait flags, etc. # Those are needed for syscalls, epoll_wait flags, etc.
# #
# - bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp
# This flags _GNU_SOURCE, currently needed
#
# - llvm-include-order # - llvm-include-order
# TODO: not really important, but nice to fix eventually # TODO: not really important, but nice to fix eventually
# #
@ -155,7 +152,6 @@ clang-tidy: $(wildcard *.c)
-readability-magic-numbers,\ -readability-magic-numbers,\
-llvmlibc-restrict-system-libc-headers,\ -llvmlibc-restrict-system-libc-headers,\
-hicpp-signed-bitwise,\ -hicpp-signed-bitwise,\
-bugprone-reserved-identifier,-cert-dcl37-c,-cert-dcl51-cpp,\
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,\ -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,\
-llvm-include-order,\ -llvm-include-order,\
-cppcoreguidelines-avoid-magic-numbers,\ -cppcoreguidelines-avoid-magic-numbers,\

26
arp.c
View file

@ -12,24 +12,24 @@
* Author: Stefano Brivio <sbrivio@redhat.com> * Author: Stefano Brivio <sbrivio@redhat.com>
*/ */
#include <stdio.h> #include <arpa/inet.h>
#include <stddef.h> #include <limits.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/udp.h>
#include <net/if.h> #include <net/if.h>
#include <net/if_arp.h> #include <net/if_arp.h>
#include <arpa/inet.h> #include <netinet/if_ether.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <linux/ipv6.h>
#include "util.h" #include "util.h"
#include "passt.h"
#include "dhcp.h"
#include "tap.h"
#include "arp.h" #include "arp.h"
#include "dhcp.h"
#include "passt.h"
#include "tap.h"
/** /**
* arp() - Check if this is an ARP message, reply as needed * arp() - Check if this is an ARP message, reply as needed

View file

@ -46,12 +46,11 @@
* See the comment to csum_avx2() for further details. * See the comment to csum_avx2() for further details.
*/ */
#include <stdint.h>
#include <stddef.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <stddef.h>
#include <stdint.h>
/** /**
* sum_16b() - Calculate sum of 16-bit words * sum_16b() - Calculate sum of 16-bit words

18
conf.c
View file

@ -14,32 +14,30 @@
* #syscalls stat * #syscalls stat
*/ */
#define _GNU_SOURCE #include <arpa/inet.h>
#include <sched.h> #include <errno.h>
#include <fcntl.h>
#include <getopt.h> #include <getopt.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <sched.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <syslog.h> #include <syslog.h>
#include <time.h> #include <time.h>
#include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <linux/if_ether.h> #include <netinet/if_ether.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h> #include <linux/ipv6.h>
#include "util.h" #include "util.h"
#include "passt.h" #include "passt.h"
#include "netlink.h"
#include "udp.h" #include "udp.h"
#include "tcp.h" #include "tcp.h"
#include "netlink.h"
#include "pasta.h" #include "pasta.h"
/** /**

19
dhcp.c
View file

@ -12,23 +12,24 @@
* Author: Stefano Brivio <sbrivio@redhat.com> * Author: Stefano Brivio <sbrivio@redhat.com>
*/ */
#include <stdio.h> #include <arpa/inet.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/udp.h>
#include <net/if.h>
#include <arpa/inet.h>
#include "checksum.h" #include <linux/ipv6.h>
#include "util.h" #include "util.h"
#include "checksum.h"
#include "passt.h" #include "passt.h"
#include "dhcp.h"
#include "tap.h" #include "tap.h"
#include "dhcp.h"
/** /**
* struct opt - DHCP option * struct opt - DHCP option

View file

@ -12,19 +12,20 @@
* Author: Stefano Brivio <sbrivio@redhat.com> * Author: Stefano Brivio <sbrivio@redhat.com>
*/ */
#include <arpa/inet.h>
#include <net/if_arp.h>
#include <net/if.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/if_ether.h>
#include <stdio.h> #include <stdio.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/udp.h>
#include <net/if.h>
#include <net/if_arp.h>
#include "util.h" #include "util.h"
#include "passt.h" #include "passt.h"
@ -205,9 +206,9 @@ struct msg_hdr {
} __attribute__((__packed__)); } __attribute__((__packed__));
#if __BYTE_ORDER == __BIG_ENDIAN #if __BYTE_ORDER == __BIG_ENDIAN
#define UH_RESP { 547, 546, 0, 0, } #define UH_RESP {{{ 547, 546, 0, 0, }}}
#else #else
#define UH_RESP { __bswap_constant_16(547), __bswap_constant_16(546), 0, 0 } #define UH_RESP {{{ __bswap_constant_16(547), __bswap_constant_16(546), 0, 0 }}}
#endif #endif
/** /**
@ -316,26 +317,26 @@ static struct opt_hdr *dhcpv6_opt(struct opt_hdr *o, uint16_t type, size_t *len)
/** /**
* dhcpv6_ia_notonlink() - Check if any IA contains non-appropriate addresses * dhcpv6_ia_notonlink() - Check if any IA contains non-appropriate addresses
* @o: First option header to check for IAs * @o: First option header to check for IAs
* @len: Remaining message length, host order * @rem_len: Remaining message length, host order
* @addr: Address we want to lease to the client * @addr: Address we want to lease to the client
* *
* Return: pointer to non-appropriate IA_NA or IA_TA, if any, NULL otherwise * Return: pointer to non-appropriate IA_NA or IA_TA, if any, NULL otherwise
*/ */
static struct opt_hdr *dhcpv6_ia_notonlink(struct opt_hdr *o, size_t len, static struct opt_hdr *dhcpv6_ia_notonlink(struct opt_hdr *o, size_t rem_len,
struct in6_addr *addr) struct in6_addr *addr)
{ {
struct opt_hdr *ia, *ia_addr; struct opt_hdr *ia, *ia_addr;
char buf[INET6_ADDRSTRLEN]; char buf[INET6_ADDRSTRLEN];
struct in6_addr *req_addr; struct in6_addr *req_addr;
size_t __len; size_t len;
int ia_type; int ia_type;
ia_type = OPT_IA_NA; ia_type = OPT_IA_NA;
ia_ta: ia_ta:
__len = len; len = rem_len;
ia = o; ia = o;
while ((ia = dhcpv6_opt(ia, ia_type, &__len))) { while ((ia = dhcpv6_opt(ia, ia_type, &len))) {
size_t ia_len = ntohs(ia->l); size_t ia_len = ntohs(ia->l);
if (ia_type == OPT_IA_NA) { if (ia_type == OPT_IA_NA) {

42
icmp.c
View file

@ -12,12 +12,14 @@
* Author: Stefano Brivio <sbrivio@redhat.com> * Author: Stefano Brivio <sbrivio@redhat.com>
*/ */
#include <stdio.h>
#include <errno.h> #include <errno.h>
#include <limits.h>
#include <net/ethernet.h> #include <net/ethernet.h>
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <stdio.h>
#include <limits.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
@ -25,12 +27,11 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/icmp.h>
#include <linux/icmpv6.h>
#include <time.h> #include <time.h>
#include <linux/icmpv6.h>
#include <linux/ipv6.h>
#include "util.h" #include "util.h"
#include "passt.h" #include "passt.h"
#include "tap.h" #include "tap.h"
@ -39,19 +40,19 @@
#define ICMP_ECHO_TIMEOUT 60 /* s, timeout for ICMP socket activity */ #define ICMP_ECHO_TIMEOUT 60 /* s, timeout for ICMP socket activity */
/** /**
* struct icmp_id - Tracking information for single ICMP echo identifier * struct icmp_id_sock - Tracking information for single ICMP echo identifier
* @sock: Bound socket for identifier * @sock: Bound socket for identifier
* @ts: Last associated activity from tap, seconds * @ts: Last associated activity from tap, seconds
* @seq: Last sequence number sent to tap, host order * @seq: Last sequence number sent to tap, host order
*/ */
struct icmp_id { struct icmp_id_sock {
int sock; int sock;
time_t ts; time_t ts;
uint16_t seq; uint16_t seq;
}; };
/* Indexed by ICMP echo identifier */ /* Indexed by ICMP echo identifier */
static struct icmp_id icmp_id_map [IP_VERSIONS][USHRT_MAX]; static struct icmp_id_sock icmp_id_map [IP_VERSIONS][USHRT_MAX];
/* Bitmaps, activity monitoring needed for identifier */ /* Bitmaps, activity monitoring needed for identifier */
static uint8_t icmp_act [IP_VERSIONS][USHRT_MAX / 8]; static uint8_t icmp_act [IP_VERSIONS][USHRT_MAX / 8];
@ -70,6 +71,7 @@ void icmp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0xff, 0xff, 0, 0, 0xff, 0xff,
0, 0, 0, 0 } }; 0, 0, 0, 0 } };
union icmp_epoll_ref *iref = &ref.r.p.icmp;
struct sockaddr_storage sr; struct sockaddr_storage sr;
socklen_t sl = sizeof(sr); socklen_t sl = sizeof(sr);
char buf[USHRT_MAX]; char buf[USHRT_MAX];
@ -79,11 +81,11 @@ void icmp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
(void)events; (void)events;
(void)now; (void)now;
n = recvfrom(ref.s, buf, sizeof(buf), 0, (struct sockaddr *)&sr, &sl); n = recvfrom(ref.r.s, buf, sizeof(buf), 0, (struct sockaddr *)&sr, &sl);
if (n < 0) if (n < 0)
return; return;
if (ref.icmp.v6) { if (iref->icmp.v6) {
struct sockaddr_in6 *sr6 = (struct sockaddr_in6 *)&sr; struct sockaddr_in6 *sr6 = (struct sockaddr_in6 *)&sr;
struct icmp6hdr *ih = (struct icmp6hdr *)buf; struct icmp6hdr *ih = (struct icmp6hdr *)buf;
@ -92,8 +94,8 @@ void icmp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
/* If bind() fails e.g. because of a broken SELinux policy, this /* If bind() fails e.g. because of a broken SELinux policy, this
* might happen. Fix up the identifier to match the sent one. * might happen. Fix up the identifier to match the sent one.
*/ */
if (id != ref.icmp.id) if (id != iref->icmp.id)
ih->icmp6_identifier = htons(ref.icmp.id); ih->icmp6_identifier = htons(iref->icmp.id);
/* In PASTA mode, we'll get any reply we send, discard them. */ /* In PASTA mode, we'll get any reply we send, discard them. */
if (c->mode == MODE_PASTA) { if (c->mode == MODE_PASTA) {
@ -111,8 +113,8 @@ void icmp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
struct icmphdr *ih = (struct icmphdr *)buf; struct icmphdr *ih = (struct icmphdr *)buf;
id = ntohs(ih->un.echo.id); id = ntohs(ih->un.echo.id);
if (id != ref.icmp.id) if (id != iref->icmp.id)
ih->un.echo.id = htons(ref.icmp.id); ih->un.echo.id = htons(iref->icmp.id);
if (c->mode == MODE_PASTA) { if (c->mode == MODE_PASTA) {
seq = ntohs(ih->un.echo.sequence); seq = ntohs(ih->un.echo.sequence);
@ -146,7 +148,7 @@ int icmp_tap_handler(struct ctx *c, int af, void *addr,
(void)count; (void)count;
if (af == AF_INET) { if (af == AF_INET) {
union icmp_epoll_ref iref = { .v6 = 0 }; union icmp_epoll_ref iref = { .icmp.v6 = 0 };
struct sockaddr_in sa = { struct sockaddr_in sa = {
.sin_family = AF_INET, .sin_family = AF_INET,
.sin_addr = { .s_addr = INADDR_ANY }, .sin_addr = { .s_addr = INADDR_ANY },
@ -161,7 +163,7 @@ int icmp_tap_handler(struct ctx *c, int af, void *addr,
sa.sin_port = ih->un.echo.id; sa.sin_port = ih->un.echo.id;
iref.id = id = ntohs(ih->un.echo.id); iref.icmp.id = id = ntohs(ih->un.echo.id);
if ((s = icmp_id_map[V4][id].sock) <= 0) { if ((s = icmp_id_map[V4][id].sock) <= 0) {
s = sock_l4(c, AF_INET, IPPROTO_ICMP, id, 0, iref.u32); s = sock_l4(c, AF_INET, IPPROTO_ICMP, id, 0, iref.u32);
@ -177,7 +179,7 @@ int icmp_tap_handler(struct ctx *c, int af, void *addr,
sendto(s, ih, msg[0].l4_len, MSG_NOSIGNAL, sendto(s, ih, msg[0].l4_len, MSG_NOSIGNAL,
(struct sockaddr *)&sa, sizeof(sa)); (struct sockaddr *)&sa, sizeof(sa));
} else if (af == AF_INET6) { } else if (af == AF_INET6) {
union icmp_epoll_ref iref = { .v6 = 1 }; union icmp_epoll_ref iref = { .icmp.v6 = 1 };
struct sockaddr_in6 sa = { struct sockaddr_in6 sa = {
.sin6_family = AF_INET6, .sin6_family = AF_INET6,
.sin6_addr = IN6ADDR_ANY_INIT, .sin6_addr = IN6ADDR_ANY_INIT,
@ -193,7 +195,7 @@ int icmp_tap_handler(struct ctx *c, int af, void *addr,
sa.sin6_port = ih->icmp6_identifier; sa.sin6_port = ih->icmp6_identifier;
iref.id = id = ntohs(ih->icmp6_identifier); iref.icmp.id = id = ntohs(ih->icmp6_identifier);
if ((s = icmp_id_map[V6][id].sock) <= 0) { if ((s = icmp_id_map[V6][id].sock) <= 0) {
s = sock_l4(c, AF_INET6, IPPROTO_ICMPV6, id, 0, s = sock_l4(c, AF_INET6, IPPROTO_ICMPV6, id, 0,
iref.u32); iref.u32);
@ -229,7 +231,7 @@ fail_sock:
static void icmp_timer_one(struct ctx *c, int v6, uint16_t id, static void icmp_timer_one(struct ctx *c, int v6, uint16_t id,
struct timespec *ts) struct timespec *ts)
{ {
struct icmp_id *id_map = &icmp_id_map[v6 ? V6 : V4][id]; struct icmp_id_sock *id_map = &icmp_id_map[v6 ? V6 : V4][id];
if (ts->tv_sec - id_map->ts <= ICMP_ECHO_TIMEOUT) if (ts->tv_sec - id_map->ts <= ICMP_ECHO_TIMEOUT)
return; return;

2
icmp.h
View file

@ -26,7 +26,7 @@ union icmp_epoll_ref {
struct { struct {
uint32_t v6:1, uint32_t v6:1,
id:16; id:16;
}; } icmp;
uint32_t u32; uint32_t u32;
}; };

2
igmp.c
View file

@ -13,4 +13,4 @@
*/ */
/* TO BE IMPLEMENTED */ /* TO BE IMPLEMENTED */
__attribute__((__unused__)) static void __(void) { } __attribute__((__unused__)) static void unused(void) { }

2
mld.c
View file

@ -13,4 +13,4 @@
*/ */
/* TO BE IMPLEMENTED */ /* TO BE IMPLEMENTED */
__attribute__((__unused__)) static void __(void) { } __attribute__((__unused__)) static void unused(void) { }

10
ndp.c
View file

@ -19,13 +19,13 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <linux/if_ether.h> #include <netinet/ip.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include <linux/udp.h>
#include <net/if.h> #include <net/if.h>
#include <net/if_arp.h> #include <net/if_arp.h>
#include <netinet/if_ether.h>
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include "checksum.h" #include "checksum.h"
#include "util.h" #include "util.h"

View file

@ -12,7 +12,6 @@
* Author: Stefano Brivio <sbrivio@redhat.com> * Author: Stefano Brivio <sbrivio@redhat.com>
*/ */
#define _GNU_SOURCE
#include <sched.h> #include <sched.h>
#include <string.h> #include <string.h>
#include <stddef.h> #include <stddef.h>
@ -24,7 +23,9 @@
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <linux/if_ether.h> #include <netinet/if_ether.h>
#include <linux/ipv6.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
@ -38,12 +39,12 @@ static int nl_sock_ns = -1;
static int nl_seq; static int nl_seq;
/** /**
* __nl_sock_init() - Set up netlink sockets in init and target namespace * nl_sock_init_do() - Set up netlink sockets in init and target namespace
* @arg: Execution context * @arg: Execution context
* *
* Return: 0 * Return: 0
*/ */
static int __nl_sock_init(void *arg) static int nl_sock_init_do(void *arg)
{ {
struct sockaddr_nl addr = { .nl_family = AF_NETLINK, }; struct sockaddr_nl addr = { .nl_family = AF_NETLINK, };
struct ctx *c = (struct ctx *)arg; struct ctx *c = (struct ctx *)arg;
@ -65,7 +66,7 @@ ns:
} }
/** /**
* nl_sock_init() - Call __nl_sock_init() and check for failures * nl_sock_init() - Call nl_sock_init_do() and check for failures
* @c: Execution context * @c: Execution context
* *
* Return: -EIO if sockets couldn't be set up, 0 otherwise * Return: -EIO if sockets couldn't be set up, 0 otherwise
@ -73,11 +74,11 @@ ns:
int nl_sock_init(struct ctx *c) int nl_sock_init(struct ctx *c)
{ {
if (c->mode == MODE_PASTA) { if (c->mode == MODE_PASTA) {
NS_CALL(__nl_sock_init, c); NS_CALL(nl_sock_init_do, c);
if (nl_sock_ns == -1) if (nl_sock_ns == -1)
return -EIO; return -EIO;
} else { } else {
__nl_sock_init(NULL); nl_sock_init_do(NULL);
} }
if (nl_sock == -1) if (nl_sock == -1)
@ -267,7 +268,7 @@ void nl_route(int ns, unsigned int ifi, sa_family_t af, void *gw)
uint32_t a; uint32_t a;
uint8_t end; uint8_t end;
} r4; } r4;
}; } set;
} req = { } req = {
.nlh.nlmsg_type = set ? RTM_NEWROUTE : RTM_GETROUTE, .nlh.nlmsg_type = set ? RTM_NEWROUTE : RTM_GETROUTE,
.nlh.nlmsg_flags = NLM_F_REQUEST, .nlh.nlmsg_flags = NLM_F_REQUEST,
@ -290,29 +291,33 @@ void nl_route(int ns, unsigned int ifi, sa_family_t af, void *gw)
if (set) { if (set) {
if (af == AF_INET6) { if (af == AF_INET6) {
size_t rta_len = RTA_LENGTH(sizeof(req.set.r6.d));
req.nlh.nlmsg_len = sizeof(req); req.nlh.nlmsg_len = sizeof(req);
req.r6.rta_dst.rta_type = RTA_DST; req.set.r6.rta_dst.rta_type = RTA_DST;
req.r6.rta_dst.rta_len = RTA_LENGTH(sizeof(req.r6.d)); req.set.r6.rta_dst.rta_len = rta_len;
memcpy(&req.r6.a, gw, sizeof(req.r6.a)); memcpy(&req.set.r6.a, gw, sizeof(req.set.r6.a));
req.r6.rta_gw.rta_type = RTA_GATEWAY; req.set.r6.rta_gw.rta_type = RTA_GATEWAY;
req.r6.rta_gw.rta_len = RTA_LENGTH(sizeof(req.r6.a)); req.set.r6.rta_gw.rta_len = rta_len;
} else { } else {
req.nlh.nlmsg_len = offsetof(struct req_t, r4.end); size_t rta_len = RTA_LENGTH(sizeof(req.set.r4.d));
req.r4.rta_dst.rta_type = RTA_DST; req.nlh.nlmsg_len = offsetof(struct req_t, set.r4.end);
req.r4.rta_dst.rta_len = RTA_LENGTH(sizeof(req.r4.d));
req.r4.a = *(uint32_t *)gw; req.set.r4.rta_dst.rta_type = RTA_DST;
req.r4.rta_gw.rta_type = RTA_GATEWAY; req.set.r4.rta_dst.rta_len = rta_len;
req.r4.rta_gw.rta_len = RTA_LENGTH(sizeof(req.r4.a));
req.set.r4.a = *(uint32_t *)gw;
req.set.r4.rta_gw.rta_type = RTA_GATEWAY;
req.set.r4.rta_gw.rta_len = rta_len;
} }
req.rtm.rtm_protocol = RTPROT_BOOT; req.rtm.rtm_protocol = RTPROT_BOOT;
req.nlh.nlmsg_flags |= NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE; req.nlh.nlmsg_flags |= NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
} else { } else {
req.nlh.nlmsg_len = offsetof(struct req_t, r6); req.nlh.nlmsg_len = offsetof(struct req_t, set.r6);
req.nlh.nlmsg_flags |= NLM_F_DUMP; req.nlh.nlmsg_flags |= NLM_F_DUMP;
} }
@ -376,7 +381,7 @@ void nl_addr(int ns, unsigned int ifi, sa_family_t af,
struct rtattr rta_a; struct rtattr rta_a;
struct in6_addr a; struct in6_addr a;
} a6; } a6;
}; } set;
} req = { } req = {
.nlh.nlmsg_type = set ? RTM_NEWADDR : RTM_GETADDR, .nlh.nlmsg_type = set ? RTM_NEWADDR : RTM_GETADDR,
.nlh.nlmsg_flags = NLM_F_REQUEST, .nlh.nlmsg_flags = NLM_F_REQUEST,
@ -395,22 +400,26 @@ void nl_addr(int ns, unsigned int ifi, sa_family_t af,
if (set) { if (set) {
if (af == AF_INET6) { if (af == AF_INET6) {
size_t rta_len = sizeof(req.set.a6.l);
req.nlh.nlmsg_len = sizeof(req); req.nlh.nlmsg_len = sizeof(req);
memcpy(&req.a6.l, addr, sizeof(req.a6.l)); memcpy(&req.set.a6.l, addr, sizeof(req.set.a6.l));
req.a6.rta_l.rta_len = RTA_LENGTH(sizeof(req.a6.l)); req.set.a6.rta_l.rta_len = rta_len;
req.a4.rta_l.rta_type = IFA_LOCAL; req.set.a4.rta_l.rta_type = IFA_LOCAL;
memcpy(&req.a6.a, addr, sizeof(req.a6.a)); memcpy(&req.set.a6.a, addr, sizeof(req.set.a6.a));
req.a6.rta_a.rta_len = RTA_LENGTH(sizeof(req.a6.a)); req.set.a6.rta_a.rta_len = rta_len;
req.a6.rta_a.rta_type = IFA_ADDRESS; req.set.a6.rta_a.rta_type = IFA_ADDRESS;
} else { } else {
req.nlh.nlmsg_len = offsetof(struct req_t, a4.end); size_t rta_len = sizeof(req.set.a4.l);
req.a4.l = req.a4.a = *(uint32_t *)addr; req.nlh.nlmsg_len = offsetof(struct req_t, set.a4.end);
req.a4.rta_l.rta_len = RTA_LENGTH(sizeof(req.a4.l));
req.a4.rta_l.rta_type = IFA_LOCAL; req.set.a4.l = req.set.a4.a = *(uint32_t *)addr;
req.a4.rta_a.rta_len = RTA_LENGTH(sizeof(req.a4.a)); req.set.a4.rta_l.rta_len = rta_len;
req.a4.rta_a.rta_type = IFA_ADDRESS; req.set.a4.rta_l.rta_type = IFA_LOCAL;
req.set.a4.rta_a.rta_len = rta_len;
req.set.a4.rta_a.rta_type = IFA_ADDRESS;
} }
req.ifa.ifa_scope = RT_SCOPE_UNIVERSE; req.ifa.ifa_scope = RT_SCOPE_UNIVERSE;
@ -475,7 +484,7 @@ void nl_link(int ns, unsigned int ifi, void *mac, int up, int mtu)
union { union {
unsigned char mac[ETH_ALEN]; unsigned char mac[ETH_ALEN];
unsigned int mtu; unsigned int mtu;
}; } set;
} req = { } req = {
.nlh.nlmsg_type = change ? RTM_NEWLINK : RTM_GETLINK, .nlh.nlmsg_type = change ? RTM_NEWLINK : RTM_GETLINK,
.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
@ -494,7 +503,7 @@ void nl_link(int ns, unsigned int ifi, void *mac, int up, int mtu)
if (!MAC_IS_ZERO(mac)) { if (!MAC_IS_ZERO(mac)) {
req.nlh.nlmsg_len = sizeof(req); req.nlh.nlmsg_len = sizeof(req);
memcpy(req.mac, mac, ETH_ALEN); memcpy(req.set.mac, mac, ETH_ALEN);
req.rta.rta_type = IFLA_ADDRESS; req.rta.rta_type = IFLA_ADDRESS;
req.rta.rta_len = RTA_LENGTH(ETH_ALEN); req.rta.rta_len = RTA_LENGTH(ETH_ALEN);
nl_req(ns, buf, &req, req.nlh.nlmsg_len); nl_req(ns, buf, &req, req.nlh.nlmsg_len);
@ -503,7 +512,7 @@ void nl_link(int ns, unsigned int ifi, void *mac, int up, int mtu)
if (mtu) { if (mtu) {
req.nlh.nlmsg_len = sizeof(req); req.nlh.nlmsg_len = sizeof(req);
req.mtu = mtu; req.set.mtu = mtu;
req.rta.rta_type = IFLA_MTU; req.rta.rta_type = IFLA_MTU;
req.rta.rta_len = RTA_LENGTH(sizeof(unsigned int)); req.rta.rta_len = RTA_LENGTH(sizeof(unsigned int));
nl_req(ns, buf, &req, req.nlh.nlmsg_len); nl_req(ns, buf, &req, req.nlh.nlmsg_len);

33
passt.c
View file

@ -19,7 +19,6 @@
* created in a separate network namespace). * created in a separate network namespace).
*/ */
#define _GNU_SOURCE
#include <sched.h> #include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <sys/epoll.h> #include <sys/epoll.h>
@ -32,15 +31,7 @@
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <linux/if_ether.h> #include <netinet/ip.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmpv6.h>
#include <linux/un.h>
#include <linux/if_link.h>
#include <net/ethernet.h> #include <net/ethernet.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -51,14 +42,20 @@
#include <time.h> #include <time.h>
#include <syslog.h> #include <syslog.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <linux/seccomp.h>
#include <linux/audit.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <linux/filter.h>
#include <stddef.h> #include <stddef.h>
#include <linux/capability.h>
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/if_ether.h>
#include <linux/seccomp.h>
#include <linux/audit.h>
#include <linux/filter.h>
#include <linux/capability.h>
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include "seccomp.h" #include "seccomp.h"
#include "util.h" #include "util.h"
@ -100,14 +97,14 @@ static void sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
{ {
debug("%s: %s packet from socket %i (events: 0x%08x)", debug("%s: %s packet from socket %i (events: 0x%08x)",
c->mode == MODE_PASST ? "passt" : "pasta", c->mode == MODE_PASST ? "passt" : "pasta",
IP_PROTO_STR(ref.proto), ref.s, events); IP_PROTO_STR(ref.r.proto), ref.r.s, events);
if (!c->no_tcp && ref.proto == IPPROTO_TCP) if (!c->no_tcp && ref.r.proto == IPPROTO_TCP)
tcp_sock_handler( c, ref, events, now); tcp_sock_handler( c, ref, events, now);
else if (!c->no_udp && ref.proto == IPPROTO_UDP) else if (!c->no_udp && ref.r.proto == IPPROTO_UDP)
udp_sock_handler( c, ref, events, now); udp_sock_handler( c, ref, events, now);
else if (!c->no_icmp && else if (!c->no_icmp &&
(ref.proto == IPPROTO_ICMP || ref.proto == IPPROTO_ICMPV6)) (ref.r.proto == IPPROTO_ICMP || ref.r.proto == IPPROTO_ICMPV6))
icmp_sock_handler(c, ref, events, now); icmp_sock_handler(c, ref, events, now);
} }

View file

@ -51,8 +51,8 @@ union epoll_ref {
union udp_epoll_ref udp; union udp_epoll_ref udp;
union icmp_epoll_ref icmp; union icmp_epoll_ref icmp;
uint32_t data; uint32_t data;
}; } p;
}; } r;
uint64_t u64; uint64_t u64;
}; };

View file

@ -15,7 +15,6 @@
* #syscalls:pasta geteuid getdents64 readlink setsid nanosleep clock_nanosleep * #syscalls:pasta geteuid getdents64 readlink setsid nanosleep clock_nanosleep
*/ */
#define _GNU_SOURCE
#include <sched.h> #include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -36,6 +35,8 @@
#include <net/ethernet.h> #include <net/ethernet.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <linux/ipv6.h>
#include "util.h" #include "util.h"
#include "passt.h" #include "passt.h"
#include "netlink.h" #include "netlink.h"

3
pcap.c
View file

@ -12,7 +12,6 @@
* Author: Stefano Brivio <sbrivio@redhat.com> * Author: Stefano Brivio <sbrivio@redhat.com>
*/ */
#define _GNU_SOURCE
#include <stdio.h> #include <stdio.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
@ -29,6 +28,8 @@
#include <unistd.h> #include <unistd.h>
#include <net/if.h> #include <net/if.h>
#include <linux/ipv6.h>
#include "util.h" #include "util.h"
#include "passt.h" #include "passt.h"

6
qrap.c
View file

@ -19,14 +19,14 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <errno.h> #include <errno.h>
#include <linux/if_ether.h>
#include <linux/ipv6.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <linux/un.h>
#include <limits.h> #include <limits.h>
#include <fcntl.h> #include <fcntl.h>
#include <net/if_arp.h> #include <net/if_arp.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/if_ether.h>
#include <linux/ipv6.h>
#include "util.h" #include "util.h"
#include "passt.h" #include "passt.h"

13
tap.c
View file

@ -14,7 +14,6 @@
* #syscalls recvfrom sendto * #syscalls recvfrom sendto
*/ */
#define _GNU_SOURCE
#include <sched.h> #include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
@ -34,14 +33,14 @@
#include <sys/uio.h> #include <sys/uio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <linux/un.h> #include <netinet/ip.h>
#include <linux/if.h> #include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <netinet/if_ether.h>
#include <linux/if_tun.h> #include <linux/if_tun.h>
#include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <linux/icmpv6.h> #include <linux/icmpv6.h>
#include "checksum.h" #include "checksum.h"

164
tcp.c
View file

@ -307,7 +307,6 @@
* #syscalls pipe pipe2 * #syscalls pipe pipe2
*/ */
#define _GNU_SOURCE
#include <sched.h> #include <sched.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
@ -317,6 +316,7 @@
#include <net/ethernet.h> #include <net/ethernet.h>
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/ip.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
@ -326,11 +326,11 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <unistd.h> #include <unistd.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include <time.h> #include <time.h>
#include <linux/ipv6.h>
#include <linux/tcp.h> /* For struct tcp_info */
#include "checksum.h" #include "checksum.h"
#include "util.h" #include "util.h"
#include "passt.h" #include "passt.h"
@ -1019,14 +1019,14 @@ static void tcp_sock6_iov_init(void)
* tcp_opt_get() - Get option, and value if any, from TCP header * tcp_opt_get() - Get option, and value if any, from TCP header
* @th: Pointer to TCP header * @th: Pointer to TCP header
* @len: Length of buffer, including TCP header * @len: Length of buffer, including TCP header
* @__type: Option type to look for * @type: Option type to look for
* @__optlen: Optional, filled with option length if passed * @optlen_set: Optional, filled with option length if passed
* @__value: Optional, set to start of option value if passed * @value_set: Optional, set to start of option value if passed
* *
* Return: Option value, meaningful for up to 4 bytes, -1 if not found * Return: Option value, meaningful for up to 4 bytes, -1 if not found
*/ */
static int tcp_opt_get(struct tcphdr *th, size_t len, uint8_t __type, static int tcp_opt_get(struct tcphdr *th, size_t len, uint8_t type_search,
uint8_t *__optlen, char **__value) uint8_t *optlen_set, char **value_set)
{ {
uint8_t type, optlen; uint8_t type, optlen;
char *p; char *p;
@ -1049,13 +1049,13 @@ static int tcp_opt_get(struct tcphdr *th, size_t len, uint8_t __type,
optlen = *(p++) - 2; optlen = *(p++) - 2;
len -= 2; len -= 2;
if (type != __type) if (type != type_search)
break; break;
if (__optlen) if (optlen_set)
*__optlen = optlen; *optlen_set = optlen;
if (__value) if (value_set)
*__value = p; *value_set = p;
switch (optlen) { switch (optlen) {
case 0: case 0:
@ -1249,9 +1249,9 @@ static struct tcp_tap_conn *tcp_hash_lookup(struct ctx *c, int af, void *addr,
static void tcp_tap_epoll_mask(struct ctx *c, struct tcp_tap_conn *conn, static void tcp_tap_epoll_mask(struct ctx *c, struct tcp_tap_conn *conn,
uint32_t events) uint32_t events)
{ {
union epoll_ref ref = { .proto = IPPROTO_TCP, .s = conn->sock, union epoll_ref ref = { .r.proto = IPPROTO_TCP, .r.s = conn->sock,
.tcp.index = conn - tt, .r.p.tcp.tcp.index = conn - tt,
.tcp.v6 = CONN_V6(conn) }; .r.p.tcp.tcp.v6 = CONN_V6(conn) };
struct epoll_event ev = { .data.u64 = ref.u64, .events = events }; struct epoll_event ev = { .data.u64 = ref.u64, .events = events };
if (conn->events == events) if (conn->events == events)
@ -1547,7 +1547,7 @@ static int tcp_update_seqack_wnd(struct ctx *c, struct tcp_tap_conn *conn,
uint32_t prev_ack_to_tap = conn->seq_ack_to_tap; uint32_t prev_ack_to_tap = conn->seq_ack_to_tap;
uint32_t prev_wnd_to_tap = conn->wnd_to_tap; uint32_t prev_wnd_to_tap = conn->wnd_to_tap;
socklen_t sl = sizeof(*info); socklen_t sl = sizeof(*info);
struct tcp_info __info; struct tcp_info info_new;
int s = conn->sock; int s = conn->sock;
if (conn->state > ESTABLISHED || (flags & (DUP_ACK | FORCE_ACK)) || if (conn->state > ESTABLISHED || (flags & (DUP_ACK | FORCE_ACK)) ||
@ -1556,7 +1556,7 @@ static int tcp_update_seqack_wnd(struct ctx *c, struct tcp_tap_conn *conn,
conn->seq_ack_to_tap = conn->seq_from_tap; conn->seq_ack_to_tap = conn->seq_from_tap;
} else if (conn->seq_ack_to_tap != conn->seq_from_tap) { } else if (conn->seq_ack_to_tap != conn->seq_from_tap) {
if (!info) { if (!info) {
info = &__info; info = &info_new;
if (getsockopt(s, SOL_TCP, TCP_INFO, info, &sl)) if (getsockopt(s, SOL_TCP, TCP_INFO, info, &sl))
return 0; return 0;
} }
@ -1578,7 +1578,7 @@ static int tcp_update_seqack_wnd(struct ctx *c, struct tcp_tap_conn *conn,
if (conn->wnd_to_tap > WINDOW_DEFAULT) if (conn->wnd_to_tap > WINDOW_DEFAULT)
goto out; goto out;
info = &__info; info = &info_new;
if (getsockopt(s, SOL_TCP, TCP_INFO, info, &sl)) if (getsockopt(s, SOL_TCP, TCP_INFO, info, &sl))
goto out; goto out;
} }
@ -1876,6 +1876,7 @@ static void tcp_conn_from_tap(struct ctx *c, int af, void *addr,
struct tcphdr *th, size_t len, struct tcphdr *th, size_t len,
struct timespec *now) struct timespec *now)
{ {
union epoll_ref ref = { .r.proto = IPPROTO_TCP };
struct sockaddr_in addr4 = { struct sockaddr_in addr4 = {
.sin_family = AF_INET, .sin_family = AF_INET,
.sin_port = th->dest, .sin_port = th->dest,
@ -1886,7 +1887,6 @@ static void tcp_conn_from_tap(struct ctx *c, int af, void *addr,
.sin6_port = th->dest, .sin6_port = th->dest,
.sin6_addr = *(struct in6_addr *)addr, .sin6_addr = *(struct in6_addr *)addr,
}; };
union epoll_ref ref = { .proto = IPPROTO_TCP };
int i, s, *sock_pool_p, mss; int i, s, *sock_pool_p, mss;
const struct sockaddr *sa; const struct sockaddr *sa;
struct tcp_tap_conn *conn; struct tcp_tap_conn *conn;
@ -1901,15 +1901,16 @@ static void tcp_conn_from_tap(struct ctx *c, int af, void *addr,
sock_pool_p = &init_sock_pool6[i]; sock_pool_p = &init_sock_pool6[i];
else else
sock_pool_p = &init_sock_pool4[i]; sock_pool_p = &init_sock_pool4[i];
if ((ref.s = s = *sock_pool_p) >= 0) { if ((ref.r.s = s = *sock_pool_p) >= 0) {
*sock_pool_p = -1; *sock_pool_p = -1;
break; break;
} }
} }
if (s < 0) if (s < 0) {
ref.s = s = socket(af, SOCK_STREAM | SOCK_NONBLOCK, s = socket(af, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
IPPROTO_TCP); ref.r.s = s;
}
if (s < 0) if (s < 0)
return; return;
@ -2016,7 +2017,7 @@ static void tcp_conn_from_tap(struct ctx *c, int af, void *addr,
} }
conn->events = ev.events; conn->events = ev.events;
ref.tcp.index = conn - tt; ref.r.p.tcp.tcp.index = conn - tt;
ev.data.u64 = ref.u64; ev.data.u64 = ref.u64;
epoll_ctl(c->epollfd, EPOLL_CTL_ADD, s, &ev); epoll_ctl(c->epollfd, EPOLL_CTL_ADD, s, &ev);
} }
@ -2029,10 +2030,12 @@ static void tcp_conn_from_tap(struct ctx *c, int af, void *addr,
static void tcp_table_splice_compact(struct ctx *c, static void tcp_table_splice_compact(struct ctx *c,
struct tcp_splice_conn *hole) struct tcp_splice_conn *hole)
{ {
union epoll_ref ref_from = { .proto = IPPROTO_TCP, .tcp.splice = 1, union epoll_ref ref_from = { .r.proto = IPPROTO_TCP,
.tcp.index = hole - ts }; .r.p.tcp.tcp.splice = 1,
union epoll_ref ref_to = { .proto = IPPROTO_TCP, .tcp.splice = 1, .r.p.tcp.tcp.index = hole - ts };
.tcp.index = hole - ts }; union epoll_ref ref_to = { .r.proto = IPPROTO_TCP,
.r.p.tcp.tcp.splice = 1,
.r.p.tcp.tcp.index = hole - ts };
struct tcp_splice_conn *move; struct tcp_splice_conn *move;
struct epoll_event ev_from; struct epoll_event ev_from;
struct epoll_event ev_to; struct epoll_event ev_to;
@ -2057,10 +2060,10 @@ static void tcp_table_splice_compact(struct ctx *c,
move->state = CLOSED; move->state = CLOSED;
move = hole; move = hole;
ref_from.s = move->from; ref_from.r.s = move->from;
ref_from.tcp.v6 = move->v6; ref_from.r.p.tcp.tcp.v6 = move->v6;
ref_to.s = move->to; ref_to.r.s = move->to;
ref_to.tcp.v6 = move->v6; ref_to.r.p.tcp.tcp.v6 = move->v6;
if (move->state == SPLICE_ACCEPTED) { if (move->state == SPLICE_ACCEPTED) {
ev_from.events = ev_to.events = 0; ev_from.events = ev_to.events = 0;
@ -2704,11 +2707,11 @@ static void tcp_connect_finish(struct ctx *c, struct tcp_tap_conn *conn,
static void tcp_splice_connect_finish(struct ctx *c, static void tcp_splice_connect_finish(struct ctx *c,
struct tcp_splice_conn *conn, int v6) struct tcp_splice_conn *conn, int v6)
{ {
union epoll_ref ref_from = { .proto = IPPROTO_TCP, .s = conn->from, union epoll_ref ref_from = { .r.proto = IPPROTO_TCP, .r.s = conn->from,
.tcp = { .splice = 1, .v6 = v6, .r.p.tcp.tcp = { .splice = 1, .v6 = v6,
.index = conn - ts } }; .index = conn - ts } };
union epoll_ref ref_to = { .proto = IPPROTO_TCP, .s = conn->to, union epoll_ref ref_to = { .r.proto = IPPROTO_TCP, .r.s = conn->to,
.tcp = { .splice = 1, .v6 = v6, .r.p.tcp.tcp = { .splice = 1, .v6 = v6,
.index = conn - ts } }; .index = conn - ts } };
struct epoll_event ev_from, ev_to; struct epoll_event ev_from, ev_to;
int i; int i;
@ -2764,11 +2767,12 @@ static int tcp_splice_connect(struct ctx *c, struct tcp_splice_conn *conn,
int sock_conn = (s >= 0) ? s : socket(v6 ? AF_INET6 : AF_INET, int sock_conn = (s >= 0) ? s : socket(v6 ? AF_INET6 : AF_INET,
SOCK_STREAM | SOCK_NONBLOCK, SOCK_STREAM | SOCK_NONBLOCK,
IPPROTO_TCP); IPPROTO_TCP);
union epoll_ref ref_accept = { .proto = IPPROTO_TCP, .s = conn->from, union epoll_ref ref_accept = { .r.proto = IPPROTO_TCP,
.tcp = { .splice = 1, .v6 = v6, .r.s = conn->from,
.r.p.tcp.tcp = { .splice = 1, .v6 = v6,
.index = conn - ts } }; .index = conn - ts } };
union epoll_ref ref_conn = { .proto = IPPROTO_TCP, .s = sock_conn, union epoll_ref ref_conn = { .r.proto = IPPROTO_TCP, .r.s = sock_conn,
.tcp = { .splice = 1, .v6 = v6, .r.p.tcp.tcp = { .splice = 1, .v6 = v6,
.index = conn - ts } }; .index = conn - ts } };
struct epoll_event ev_accept = { .data.u64 = ref_accept.u64 }; struct epoll_event ev_accept = { .data.u64 = ref_accept.u64 };
struct epoll_event ev_conn = { .data.u64 = ref_conn.u64 }; struct epoll_event ev_conn = { .data.u64 = ref_conn.u64 };
@ -2901,8 +2905,8 @@ static int tcp_splice_new(struct ctx *c, struct tcp_splice_conn *conn,
static void tcp_conn_from_sock(struct ctx *c, union epoll_ref ref, static void tcp_conn_from_sock(struct ctx *c, union epoll_ref ref,
struct timespec *now) struct timespec *now)
{ {
union epoll_ref ref_conn = { .proto = IPPROTO_TCP, union epoll_ref ref_conn = { .r.proto = IPPROTO_TCP,
.tcp.v6 = ref.tcp.v6 }; .r.p.tcp.tcp.v6 = ref.r.p.tcp.tcp.v6 };
struct sockaddr_storage sa; struct sockaddr_storage sa;
struct tcp_tap_conn *conn; struct tcp_tap_conn *conn;
struct epoll_event ev; struct epoll_event ev;
@ -2913,15 +2917,15 @@ static void tcp_conn_from_sock(struct ctx *c, union epoll_ref ref,
return; return;
sl = sizeof(sa); sl = sizeof(sa);
s = accept4(ref.s, (struct sockaddr *)&sa, &sl, SOCK_NONBLOCK); s = accept4(ref.r.s, (struct sockaddr *)&sa, &sl, SOCK_NONBLOCK);
if (s < 0) if (s < 0)
return; return;
conn = &tt[c->tcp.tap_conn_count++]; conn = &tt[c->tcp.tap_conn_count++];
ref_conn.tcp.index = conn - tt; ref_conn.r.p.tcp.tcp.index = conn - tt;
ref_conn.s = conn->sock = s; ref_conn.r.s = conn->sock = s;
if (ref.tcp.v6) { if (ref.r.p.tcp.tcp.v6) {
struct sockaddr_in6 sa6; struct sockaddr_in6 sa6;
memcpy(&sa6, &sa, sizeof(sa6)); memcpy(&sa6, &sa, sizeof(sa6));
@ -2942,7 +2946,7 @@ static void tcp_conn_from_sock(struct ctx *c, union epoll_ref ref,
memcpy(&conn->a.a6, &sa6.sin6_addr, sizeof(conn->a.a6)); memcpy(&conn->a.a6, &sa6.sin6_addr, sizeof(conn->a.a6));
conn->sock_port = ntohs(sa6.sin6_port); conn->sock_port = ntohs(sa6.sin6_port);
conn->tap_port = ref.tcp.index; conn->tap_port = ref.r.p.tcp.tcp.index;
conn->seq_to_tap = tcp_seq_init(c, AF_INET6, &sa6.sin6_addr, conn->seq_to_tap = tcp_seq_init(c, AF_INET6, &sa6.sin6_addr,
conn->sock_port, conn->sock_port,
@ -2968,7 +2972,7 @@ static void tcp_conn_from_sock(struct ctx *c, union epoll_ref ref,
memcpy(&conn->a.a4.a, &s_addr, sizeof(conn->a.a4.a)); memcpy(&conn->a.a4.a, &s_addr, sizeof(conn->a.a4.a));
conn->sock_port = ntohs(sa4.sin_port); conn->sock_port = ntohs(sa4.sin_port);
conn->tap_port = ref.tcp.index; conn->tap_port = ref.r.p.tcp.tcp.index;
conn->seq_to_tap = tcp_seq_init(c, AF_INET, &s_addr, conn->seq_to_tap = tcp_seq_init(c, AF_INET, &s_addr,
conn->sock_port, conn->sock_port,
@ -3014,13 +3018,13 @@ void tcp_sock_handler_splice(struct ctx *c, union epoll_ref ref,
struct tcp_splice_conn *conn; struct tcp_splice_conn *conn;
struct epoll_event ev; struct epoll_event ev;
if (ref.tcp.listen) { if (ref.r.p.tcp.tcp.listen) {
int s, one = 1; int s, one = 1;
if (c->tcp.splice_conn_count >= MAX_SPLICE_CONNS) if (c->tcp.splice_conn_count >= MAX_SPLICE_CONNS)
return; return;
if ((s = accept4(ref.s, NULL, NULL, SOCK_NONBLOCK)) < 0) if ((s = accept4(ref.r.s, NULL, NULL, SOCK_NONBLOCK)) < 0)
return; return;
setsockopt(s, SOL_TCP, TCP_QUICKACK, &one, sizeof(one)); setsockopt(s, SOL_TCP, TCP_QUICKACK, &one, sizeof(one));
@ -3029,13 +3033,14 @@ void tcp_sock_handler_splice(struct ctx *c, union epoll_ref ref,
conn->from = s; conn->from = s;
tcp_splice_state(conn, SPLICE_ACCEPTED); tcp_splice_state(conn, SPLICE_ACCEPTED);
if (tcp_splice_new(c, conn, ref.tcp.v6, ref.tcp.index)) if (tcp_splice_new(c, conn, ref.r.p.tcp.tcp.v6,
ref.r.p.tcp.tcp.index))
tcp_splice_destroy(c, conn); tcp_splice_destroy(c, conn);
return; return;
} }
conn = &ts[ref.tcp.index]; conn = &ts[ref.r.p.tcp.tcp.index];
if (events & EPOLLERR) if (events & EPOLLERR)
goto close; goto close;
@ -3050,12 +3055,12 @@ void tcp_sock_handler_splice(struct ctx *c, union epoll_ref ref,
}; };
if (conn->state == SPLICE_CONNECT) if (conn->state == SPLICE_CONNECT)
tcp_splice_connect_finish(c, conn, ref.tcp.v6); tcp_splice_connect_finish(c, conn, ref.r.p.tcp.tcp.v6);
else if (conn->state == SPLICE_ESTABLISHED) else if (conn->state == SPLICE_ESTABLISHED)
epoll_ctl(c->epollfd, EPOLL_CTL_MOD, ref.s, &ev); epoll_ctl(c->epollfd, EPOLL_CTL_MOD, ref.r.s, &ev);
move_to = ref.s; move_to = ref.r.s;
if (ref.s == conn->to) { if (ref.r.s == conn->to) {
move_from = conn->from; move_from = conn->from;
pipes = conn->pipe_from_to; pipes = conn->pipe_from_to;
} else { } else {
@ -3063,8 +3068,8 @@ void tcp_sock_handler_splice(struct ctx *c, union epoll_ref ref,
pipes = conn->pipe_to_from; pipes = conn->pipe_to_from;
} }
} else { } else {
move_from = ref.s; move_from = ref.r.s;
if (ref.s == conn->from) { if (ref.r.s == conn->from) {
move_to = conn->to; move_to = conn->to;
pipes = conn->pipe_from_to; pipes = conn->pipe_from_to;
} else { } else {
@ -3074,7 +3079,7 @@ void tcp_sock_handler_splice(struct ctx *c, union epoll_ref ref,
} }
if (events & EPOLLRDHUP) { if (events & EPOLLRDHUP) {
if (ref.s == conn->from) { if (ref.r.s == conn->from) {
if (conn->state == SPLICE_ESTABLISHED) if (conn->state == SPLICE_ESTABLISHED)
tcp_splice_state(conn, SPLICE_FIN_FROM); tcp_splice_state(conn, SPLICE_FIN_FROM);
else if (conn->state == SPLICE_FIN_TO) else if (conn->state == SPLICE_FIN_TO)
@ -3172,7 +3177,7 @@ eintr:
goto retry; goto retry;
ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP; ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;
ref.s = move_to; ref.r.s = move_to;
ev.data.u64 = ref.u64, ev.data.u64 = ref.u64,
epoll_ctl(c->epollfd, EPOLL_CTL_MOD, move_to, &ev); epoll_ctl(c->epollfd, EPOLL_CTL_MOD, move_to, &ev);
break; break;
@ -3199,7 +3204,7 @@ eintr:
conn->from_fin_sent = 1; conn->from_fin_sent = 1;
ev.events = 0; ev.events = 0;
ref.s = move_from; ref.r.s = move_from;
ev.data.u64 = ref.u64, ev.data.u64 = ref.u64,
epoll_ctl(c->epollfd, EPOLL_CTL_MOD, epoll_ctl(c->epollfd, EPOLL_CTL_MOD,
move_from, &ev); move_from, &ev);
@ -3215,7 +3220,7 @@ eintr:
conn->to_fin_sent = 1; conn->to_fin_sent = 1;
ev.events = 0; ev.events = 0;
ref.s = move_from; ref.r.s = move_from;
ev.data.u64 = ref.u64, ev.data.u64 = ref.u64,
epoll_ctl(c->epollfd, EPOLL_CTL_MOD, epoll_ctl(c->epollfd, EPOLL_CTL_MOD,
move_from, &ev); move_from, &ev);
@ -3258,17 +3263,17 @@ void tcp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
{ {
struct tcp_tap_conn *conn; struct tcp_tap_conn *conn;
if (ref.tcp.splice) { if (ref.r.p.tcp.tcp.splice) {
tcp_sock_handler_splice(c, ref, events); tcp_sock_handler_splice(c, ref, events);
return; return;
} }
if (ref.tcp.listen) { if (ref.r.p.tcp.tcp.listen) {
tcp_conn_from_sock(c, ref, now); tcp_conn_from_sock(c, ref, now);
return; return;
} }
conn = &tt[ref.tcp.index]; conn = &tt[ref.r.p.tcp.tcp.index];
conn->ts_sock_act = *now; conn->ts_sock_act = *now;
@ -3382,18 +3387,21 @@ smaller:
*/ */
static void tcp_sock_init_one(struct ctx *c, int ns, in_port_t port) static void tcp_sock_init_one(struct ctx *c, int ns, in_port_t port)
{ {
union tcp_epoll_ref tref = { .listen = 1 }; union tcp_epoll_ref tref = { .tcp.listen = 1 };
int s; int s;
if (ns) if (ns) {
tref.index = (in_port_t)(port + tcp_port_delta_to_init[port]); tref.tcp.index = (in_port_t)(port +
else tcp_port_delta_to_init[port]);
tref.index = (in_port_t)(port + tcp_port_delta_to_tap[port]); } else {
tref.tcp.index = (in_port_t)(port +
tcp_port_delta_to_tap[port]);
}
if (c->v4) { if (c->v4) {
tref.v6 = 0; tref.tcp.v6 = 0;
tref.splice = 0; tref.tcp.splice = 0;
if (!ns) { if (!ns) {
s = sock_l4(c, AF_INET, IPPROTO_TCP, port, s = sock_l4(c, AF_INET, IPPROTO_TCP, port,
c->mode == MODE_PASTA ? BIND_EXT : BIND_ANY, c->mode == MODE_PASTA ? BIND_EXT : BIND_ANY,
@ -3408,7 +3416,7 @@ static void tcp_sock_init_one(struct ctx *c, int ns, in_port_t port)
} }
if (c->mode == MODE_PASTA) { if (c->mode == MODE_PASTA) {
tref.splice = 1; tref.tcp.splice = 1;
s = sock_l4(c, AF_INET, IPPROTO_TCP, port, s = sock_l4(c, AF_INET, IPPROTO_TCP, port,
BIND_LOOPBACK, tref.u32); BIND_LOOPBACK, tref.u32);
if (s >= 0) if (s >= 0)
@ -3426,9 +3434,9 @@ static void tcp_sock_init_one(struct ctx *c, int ns, in_port_t port)
} }
if (c->v6) { if (c->v6) {
tref.v6 = 1; tref.tcp.v6 = 1;
tref.splice = 0; tref.tcp.splice = 0;
if (!ns) { if (!ns) {
s = sock_l4(c, AF_INET6, IPPROTO_TCP, port, s = sock_l4(c, AF_INET6, IPPROTO_TCP, port,
c->mode == MODE_PASTA ? BIND_EXT : BIND_ANY, c->mode == MODE_PASTA ? BIND_EXT : BIND_ANY,
@ -3443,7 +3451,7 @@ static void tcp_sock_init_one(struct ctx *c, int ns, in_port_t port)
} }
if (c->mode == MODE_PASTA) { if (c->mode == MODE_PASTA) {
tref.splice = 1; tref.tcp.splice = 1;
s = sock_l4(c, AF_INET6, IPPROTO_TCP, port, s = sock_l4(c, AF_INET6, IPPROTO_TCP, port,
BIND_LOOPBACK, tref.u32); BIND_LOOPBACK, tref.u32);
if (s >= 0) if (s >= 0)

2
tcp.h
View file

@ -39,7 +39,7 @@ union tcp_epoll_ref {
splice:1, splice:1,
v6:1, v6:1,
index:20; index:20;
}; } tcp;
uint32_t u32; uint32_t u32;
}; };

89
udp.c
View file

@ -91,7 +91,6 @@
* - otherwise, discard * - otherwise, discard
*/ */
#define _GNU_SOURCE
#include <sched.h> #include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
@ -99,6 +98,8 @@
#include <net/ethernet.h> #include <net/ethernet.h>
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
@ -107,11 +108,10 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <unistd.h> #include <unistd.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/udp.h>
#include <time.h> #include <time.h>
#include <linux/ipv6.h>
#include "checksum.h" #include "checksum.h"
#include "util.h" #include "util.h"
#include "passt.h" #include "passt.h"
@ -206,7 +206,7 @@ __extension__ static struct udp4_l2_buf_t {
udp4_l2_buf[UDP_TAP_FRAMES] = { udp4_l2_buf[UDP_TAP_FRAMES] = {
[ 0 ... UDP_TAP_FRAMES - 1 ] = { [ 0 ... UDP_TAP_FRAMES - 1 ] = {
{ 0 }, 0, 0, L2_BUF_ETH_IP4_INIT, L2_BUF_IP4_INIT(IPPROTO_UDP), { 0 }, 0, 0, L2_BUF_ETH_IP4_INIT, L2_BUF_IP4_INIT(IPPROTO_UDP),
{ 0 }, { 0 }, {{{ 0 }}}, { 0 },
}, },
}; };
@ -245,7 +245,7 @@ udp6_l2_buf[UDP_TAP_FRAMES] = {
{ 0 }, { 0 },
#endif #endif
0, L2_BUF_ETH_IP6_INIT, L2_BUF_IP6_INIT(IPPROTO_UDP), 0, L2_BUF_ETH_IP6_INIT, L2_BUF_IP6_INIT(IPPROTO_UDP),
{ 0 }, { 0 }, {{{ 0 }}}, { 0 },
}, },
}; };
@ -426,8 +426,8 @@ int udp_splice_connect(struct ctx *c, int v6, int bound_sock,
in_port_t src, in_port_t dst, int splice) in_port_t src, in_port_t dst, int splice)
{ {
struct epoll_event ev = { .events = EPOLLIN | EPOLLRDHUP | EPOLLHUP }; struct epoll_event ev = { .events = EPOLLIN | EPOLLRDHUP | EPOLLHUP };
union epoll_ref ref = { .proto = IPPROTO_UDP, union epoll_ref ref = { .r.proto = IPPROTO_UDP,
.udp = { .splice = splice, .v6 = v6 } .r.p.udp.udp = { .splice = splice, .v6 = v6 }
}; };
struct sockaddr_storage sa; struct sockaddr_storage sa;
struct udp_splice_port *sp; struct udp_splice_port *sp;
@ -438,7 +438,7 @@ int udp_splice_connect(struct ctx *c, int v6, int bound_sock,
IPPROTO_UDP); IPPROTO_UDP);
if (s < 0) if (s < 0)
return s; return s;
ref.s = s; ref.r.s = s;
if (v6) { if (v6) {
struct sockaddr_in6 addr6 = { struct sockaddr_in6 addr6 = {
@ -465,15 +465,15 @@ int udp_splice_connect(struct ctx *c, int v6, int bound_sock,
struct sockaddr_in6 sa6; struct sockaddr_in6 sa6;
memcpy(&sa6, &sa, sizeof(sa6)); memcpy(&sa6, &sa, sizeof(sa6));
ref.udp.port = ntohs(sa6.sin6_port); ref.r.p.udp.udp.port = ntohs(sa6.sin6_port);
} else { } else {
struct sockaddr_in sa4; struct sockaddr_in sa4;
memcpy(&sa4, &sa, sizeof(sa4)); memcpy(&sa4, &sa, sizeof(sa4));
ref.udp.port = ntohs(sa4.sin_port); ref.r.p.udp.udp.port = ntohs(sa4.sin_port);
} }
sp = &udp_splice_map[v6 ? V6 : V4][ref.udp.port]; sp = &udp_splice_map[v6 ? V6 : V4][ref.r.p.udp.udp.port];
if (splice == UDP_BACK_TO_INIT) { if (splice == UDP_BACK_TO_INIT) {
sp->init_bound_sock = bound_sock; sp->init_bound_sock = bound_sock;
sp->init_dst_port = src; sp->init_dst_port = src;
@ -542,15 +542,15 @@ static int udp_splice_connect_ns(void *arg)
static void udp_sock_handler_splice(struct ctx *c, union epoll_ref ref, static void udp_sock_handler_splice(struct ctx *c, union epoll_ref ref,
uint32_t events, struct timespec *now) uint32_t events, struct timespec *now)
{ {
in_port_t src, dst = ref.r.p.udp.udp.port, send_dst = 0;
struct msghdr *mh = &udp_splice_mmh_recv[0].msg_hdr; struct msghdr *mh = &udp_splice_mmh_recv[0].msg_hdr;
in_port_t src, dst = ref.udp.port, send_dst = 0;
struct sockaddr_storage *sa_s = mh->msg_name; struct sockaddr_storage *sa_s = mh->msg_name;
int s, v6 = ref.udp.v6, n, i; int s, v6 = ref.r.p.udp.udp.v6, n, i;
if (!(events & EPOLLIN)) if (!(events & EPOLLIN))
return; return;
n = recvmmsg(ref.s, udp_splice_mmh_recv, UDP_SPLICE_FRAMES, 0, NULL); n = recvmmsg(ref.r.s, udp_splice_mmh_recv, UDP_SPLICE_FRAMES, 0, NULL);
if (n <= 0) if (n <= 0)
return; return;
@ -565,13 +565,13 @@ static void udp_sock_handler_splice(struct ctx *c, union epoll_ref ref,
src = ntohs(sa->sin_port); src = ntohs(sa->sin_port);
} }
switch (ref.udp.splice) { switch (ref.r.p.udp.udp.splice) {
case UDP_TO_NS: case UDP_TO_NS:
src += udp_port_delta_from_init[src]; src += udp_port_delta_from_init[src];
if (!(s = udp_splice_map[v6][src].ns_conn_sock)) { if (!(s = udp_splice_map[v6][src].ns_conn_sock)) {
struct udp_splice_connect_ns_arg arg = { struct udp_splice_connect_ns_arg arg = {
c, v6, ref.s, src, dst, -1, c, v6, ref.r.s, src, dst, -1,
}; };
NS_CALL(udp_splice_connect_ns, &arg); NS_CALL(udp_splice_connect_ns, &arg);
@ -590,7 +590,7 @@ static void udp_sock_handler_splice(struct ctx *c, union epoll_ref ref,
src += udp_port_delta_from_tap[src]; src += udp_port_delta_from_tap[src];
if (!(s = udp_splice_map[v6][src].init_conn_sock)) { if (!(s = udp_splice_map[v6][src].init_conn_sock)) {
s = udp_splice_connect(c, v6, ref.s, src, dst, s = udp_splice_connect(c, v6, ref.r.s, src, dst,
UDP_BACK_TO_NS); UDP_BACK_TO_NS);
if (s < 0) if (s < 0)
return; return;
@ -607,7 +607,8 @@ static void udp_sock_handler_splice(struct ctx *c, union epoll_ref ref,
return; return;
} }
if (ref.udp.splice == UDP_TO_NS || ref.udp.splice == UDP_TO_INIT) { if (ref.r.p.udp.udp.splice == UDP_TO_NS ||
ref.r.p.udp.udp.splice == UDP_TO_INIT) {
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
struct msghdr *mh = &udp_splice_mmh_send[i].msg_hdr; struct msghdr *mh = &udp_splice_mmh_send[i].msg_hdr;
@ -665,13 +666,13 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
if (events == EPOLLERR) if (events == EPOLLERR)
return; return;
if (ref.udp.splice) { if (ref.r.p.udp.udp.splice) {
udp_sock_handler_splice(c, ref, events, now); udp_sock_handler_splice(c, ref, events, now);
return; return;
} }
if (ref.udp.v6) { if (ref.r.p.udp.udp.v6) {
n = recvmmsg(ref.s, udp6_l2_mh_sock, UDP_TAP_FRAMES, 0, NULL); n = recvmmsg(ref.r.s, udp6_l2_mh_sock, UDP_TAP_FRAMES, 0, NULL);
if (n <= 0) if (n <= 0)
return; return;
@ -719,7 +720,7 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
} }
b->uh.source = b->s_in6.sin6_port; b->uh.source = b->s_in6.sin6_port;
b->uh.dest = htons(ref.udp.port); b->uh.dest = htons(ref.r.p.udp.udp.port);
b->uh.len = b->ip6h.payload_len; b->uh.len = b->ip6h.payload_len;
b->ip6h.hop_limit = IPPROTO_UDP; b->ip6h.hop_limit = IPPROTO_UDP;
@ -759,7 +760,7 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
tap_mmh = udp6_l2_mh_tap; tap_mmh = udp6_l2_mh_tap;
} else { } else {
n = recvmmsg(ref.s, udp4_l2_mh_sock, UDP_TAP_FRAMES, 0, NULL); n = recvmmsg(ref.r.s, udp4_l2_mh_sock, UDP_TAP_FRAMES, 0, NULL);
if (n <= 0) if (n <= 0)
return; return;
@ -798,7 +799,7 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
udp_update_check4(b); udp_update_check4(b);
b->uh.source = b->s_in.sin_port; b->uh.source = b->s_in.sin_port;
b->uh.dest = htons(ref.udp.port); b->uh.dest = htons(ref.r.p.udp.udp.port);
b->uh.len = ntohs(udp4_l2_mh_sock[i].msg_len + b->uh.len = ntohs(udp4_l2_mh_sock[i].msg_len +
sizeof(b->uh)); sizeof(b->uh));
@ -934,7 +935,8 @@ int udp_tap_handler(struct ctx *c, int af, void *addr,
sl = sizeof(s_in); sl = sizeof(s_in);
if (!(s = udp_tap_map[V4][src].sock)) { if (!(s = udp_tap_map[V4][src].sock)) {
union udp_epoll_ref uref = { .bound = 1, .port = src }; union udp_epoll_ref uref = { .udp.bound = 1,
.udp.port = src };
s = sock_l4(c, AF_INET, IPPROTO_UDP, src, 0, uref.u32); s = sock_l4(c, AF_INET, IPPROTO_UDP, src, 0, uref.u32);
if (s <= 0) if (s <= 0)
@ -975,9 +977,9 @@ int udp_tap_handler(struct ctx *c, int af, void *addr,
} }
if (!(s = udp_tap_map[V6][src].sock)) { if (!(s = udp_tap_map[V6][src].sock)) {
union udp_epoll_ref uref = { .bound = 1, .v6 = 1, union udp_epoll_ref uref = { .udp.bound = 1,
.port = src .udp.v6 = 1,
}; .udp.port = src };
s = sock_l4(c, AF_INET6, IPPROTO_UDP, src, bind_to, s = sock_l4(c, AF_INET6, IPPROTO_UDP, src, bind_to,
uref.u32); uref.u32);
@ -1020,7 +1022,8 @@ int udp_tap_handler(struct ctx *c, int af, void *addr,
*/ */
int udp_sock_init_ns(void *arg) int udp_sock_init_ns(void *arg)
{ {
union udp_epoll_ref uref = { .bound = 1, .splice = UDP_TO_INIT }; union udp_epoll_ref uref = { .udp.bound = 1,
.udp.splice = UDP_TO_INIT };
struct ctx *c = (struct ctx *)arg; struct ctx *c = (struct ctx *)arg;
int dst; int dst;
@ -1030,16 +1033,16 @@ int udp_sock_init_ns(void *arg)
if (!bitmap_isset(c->udp.port_to_init, dst)) if (!bitmap_isset(c->udp.port_to_init, dst))
continue; continue;
uref.port = dst + udp_port_delta_to_init[dst]; uref.udp.port = dst + udp_port_delta_to_init[dst];
if (c->v4) { if (c->v4) {
uref.v6 = 0; uref.udp.v6 = 0;
sock_l4(c, AF_INET, IPPROTO_UDP, dst, BIND_LOOPBACK, sock_l4(c, AF_INET, IPPROTO_UDP, dst, BIND_LOOPBACK,
uref.u32); uref.u32);
} }
if (c->v6) { if (c->v6) {
uref.v6 = 1; uref.udp.v6 = 1;
sock_l4(c, AF_INET6, IPPROTO_UDP, dst, BIND_LOOPBACK, sock_l4(c, AF_INET6, IPPROTO_UDP, dst, BIND_LOOPBACK,
uref.u32); uref.u32);
} }
@ -1109,7 +1112,7 @@ static void udp_splice_iov_init(void)
*/ */
int udp_sock_init(struct ctx *c, struct timespec *now) int udp_sock_init(struct ctx *c, struct timespec *now)
{ {
union udp_epoll_ref uref = { .bound = 1 }; union udp_epoll_ref uref = { .udp.bound = 1 };
int dst, s; int dst, s;
(void)now; (void)now;
@ -1118,34 +1121,34 @@ int udp_sock_init(struct ctx *c, struct timespec *now)
if (!bitmap_isset(c->udp.port_to_tap, dst)) if (!bitmap_isset(c->udp.port_to_tap, dst))
continue; continue;
uref.port = dst + udp_port_delta_to_tap[dst]; uref.udp.port = dst + udp_port_delta_to_tap[dst];
if (c->v4) { if (c->v4) {
uref.splice = 0; uref.udp.splice = 0;
uref.v6 = 0; uref.udp.v6 = 0;
s = sock_l4(c, AF_INET, IPPROTO_UDP, dst, s = sock_l4(c, AF_INET, IPPROTO_UDP, dst,
c->mode == MODE_PASTA ? BIND_EXT : BIND_ANY, c->mode == MODE_PASTA ? BIND_EXT : BIND_ANY,
uref.u32); uref.u32);
if (s > 0) if (s > 0)
udp_tap_map[V4][uref.port].sock = s; udp_tap_map[V4][uref.udp.port].sock = s;
if (c->mode == MODE_PASTA) { if (c->mode == MODE_PASTA) {
uref.splice = UDP_TO_NS; uref.udp.splice = UDP_TO_NS;
sock_l4(c, AF_INET, IPPROTO_UDP, dst, sock_l4(c, AF_INET, IPPROTO_UDP, dst,
BIND_LOOPBACK, uref.u32); BIND_LOOPBACK, uref.u32);
} }
} }
if (c->v6) { if (c->v6) {
uref.splice = 0; uref.udp.splice = 0;
uref.v6 = 1; uref.udp.v6 = 1;
s = sock_l4(c, AF_INET6, IPPROTO_UDP, dst, s = sock_l4(c, AF_INET6, IPPROTO_UDP, dst,
c->mode == MODE_PASTA ? BIND_EXT : BIND_ANY, c->mode == MODE_PASTA ? BIND_EXT : BIND_ANY,
uref.u32); uref.u32);
if (s > 0) if (s > 0)
udp_tap_map[V6][uref.port].sock = s; udp_tap_map[V6][uref.udp.port].sock = s;
if (c->mode == MODE_PASTA) { if (c->mode == MODE_PASTA) {
uref.splice = UDP_TO_NS; uref.udp.splice = UDP_TO_NS;
sock_l4(c, AF_INET6, IPPROTO_UDP, dst, sock_l4(c, AF_INET6, IPPROTO_UDP, dst,
BIND_LOOPBACK, uref.u32); BIND_LOOPBACK, uref.u32);
} }

2
udp.h
View file

@ -38,7 +38,7 @@ union udp_epoll_ref {
v6:1, v6:1,
port:16; port:16;
}; } udp;
uint32_t u32; uint32_t u32;
}; };

10
util.c
View file

@ -12,13 +12,11 @@
* Author: Stefano Brivio <sbrivio@redhat.com> * Author: Stefano Brivio <sbrivio@redhat.com>
*/ */
#define _GNU_SOURCE
#include <sched.h> #include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <unistd.h> #include <unistd.h>
#include <linux/ipv6.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <net/ethernet.h> #include <net/ethernet.h>
#include <net/if.h> #include <net/if.h>
@ -34,6 +32,8 @@
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include <linux/ipv6.h>
#include "util.h" #include "util.h"
#include "passt.h" #include "passt.h"
@ -204,14 +204,16 @@ char *ipv6_l4hdr(struct ipv6hdr *ip6h, uint8_t *proto)
int sock_l4(struct ctx *c, int af, uint8_t proto, uint16_t port, int sock_l4(struct ctx *c, int af, uint8_t proto, uint16_t port,
enum bind_type bind_addr, uint32_t data) enum bind_type bind_addr, uint32_t data)
{ {
union epoll_ref ref = { .proto = proto, .data = data }; union epoll_ref ref = { .r.proto = proto, .r.p.data = data };
struct sockaddr_in addr4 = { struct sockaddr_in addr4 = {
.sin_family = AF_INET, .sin_family = AF_INET,
.sin_port = htons(port), .sin_port = htons(port),
{ 0 }, { 0 },
}; };
struct sockaddr_in6 addr6 = { struct sockaddr_in6 addr6 = {
.sin6_family = AF_INET6, .sin6_family = AF_INET6,
.sin6_port = htons(port), .sin6_port = htons(port),
0, IN6ADDR_ANY_INIT, 0,
}; };
const struct sockaddr *sa; const struct sockaddr *sa;
struct epoll_event ev; struct epoll_event ev;
@ -229,7 +231,7 @@ int sock_l4(struct ctx *c, int af, uint8_t proto, uint16_t port,
perror("L4 socket"); perror("L4 socket");
return -1; return -1;
} }
ref.s = fd; ref.r.s = fd;
if (af == AF_INET) { if (af == AF_INET) {
if (bind_addr == BIND_LOOPBACK) if (bind_addr == BIND_LOOPBACK)

3
util.h
View file

@ -136,9 +136,7 @@ enum {
#define SNDBUF_BIG (4 * 1024 * 1024) #define SNDBUF_BIG (4 * 1024 * 1024)
#define SNDBUF_SMALL (128 * 1024) #define SNDBUF_SMALL (128 * 1024)
#include <linux/ipv6.h>
#include <net/if.h> #include <net/if.h>
#include <linux/ip.h>
#include <limits.h> #include <limits.h>
#include <stdarg.h> #include <stdarg.h>
@ -151,6 +149,7 @@ enum bind_type {
struct ctx; struct ctx;
__attribute__ ((weak)) int ffsl(long int i) { return __builtin_ffsl(i); }
void __openlog(const char *ident, int option, int facility); void __openlog(const char *ident, int option, int facility);
void passt_vsyslog(int pri, const char *format, va_list ap); void passt_vsyslog(int pri, const char *format, va_list ap);
void __setlogmask(int mask); void __setlogmask(int mask);