diff --git a/conf.c b/conf.c index 8b1437d..8940ec4 100644 --- a/conf.c +++ b/conf.c @@ -52,15 +52,15 @@ void get_bound_ports(struct ctx *c, int ns, uint8_t proto) uint8_t *udp_map, *udp_excl, *tcp_map, *tcp_excl; if (ns) { - udp_map = c->udp.port_to_tap; - udp_excl = c->udp.port_to_init; - tcp_map = c->tcp.port_to_tap; - tcp_excl = c->tcp.port_to_init; + udp_map = c->udp.fwd_in.f.map; + udp_excl = c->udp.fwd_out.f.map; + tcp_map = c->tcp.fwd_in.map; + tcp_excl = c->tcp.fwd_out.map; } else { - udp_map = c->udp.port_to_init; - udp_excl = c->udp.port_to_tap; - tcp_map = c->tcp.port_to_init; - tcp_excl = c->tcp.port_to_tap; + udp_map = c->udp.fwd_out.f.map; + udp_excl = c->udp.fwd_in.f.map; + tcp_map = c->tcp.fwd_out.map; + tcp_excl = c->tcp.fwd_in.map; } if (proto == IPPROTO_UDP) { @@ -120,23 +120,23 @@ static int conf_ports(struct ctx *c, char optname, const char *optarg, { int start_src, end_src, start_dst, end_dst, exclude_only = 1, i, port; char addr_buf[sizeof(struct in6_addr)] = { 0 }, *addr = addr_buf; - void (*remap)(in_port_t port, in_port_t delta); + void (*remap)(struct ctx *c, in_port_t port, in_port_t delta); uint8_t exclude[PORT_BITMAP_SIZE] = { 0 }; char buf[BUFSIZ], *sep, *spec, *p; sa_family_t af = AF_UNSPEC; uint8_t *map; if (optname == 't') { - map = c->tcp.port_to_tap; + map = c->tcp.fwd_in.map; remap = tcp_remap_to_tap; } else if (optname == 'T') { - map = c->tcp.port_to_init; + map = c->tcp.fwd_out.map; remap = tcp_remap_to_init; } else if (optname == 'u') { - map = c->udp.port_to_tap; + map = c->udp.fwd_in.f.map; remap = udp_remap_to_tap; } else if (optname == 'U') { - map = c->udp.port_to_init; + map = c->udp.fwd_out.f.map; remap = udp_remap_to_init; } else { /* For gcc -O3 */ return 0; @@ -365,8 +365,8 @@ static int conf_ports(struct ctx *c, char optname, const char *optarg, if (start_dst != -1) { /* 80:8080 or 22-80:8080:8080 */ - remap(i, (in_port_t)(start_dst - - start_src)); + remap(c, i, (in_port_t)(start_dst - + start_src)); } if (optname == 't') @@ -1095,8 +1095,8 @@ void conf(struct ctx *c, int argc, char **argv) if (c->mode == MODE_PASTA) c->no_dhcp_dns = c->no_dhcp_dns_search = 1; - c->tcp.fwd_mode_in = c->tcp.fwd_mode_out = 0; - c->udp.fwd_mode_in = c->udp.fwd_mode_out = 0; + c->tcp.fwd_in.mode = c->tcp.fwd_out.mode = 0; + c->udp.fwd_in.f.mode = c->udp.fwd_out.f.mode = 0; do { const char *optstring; @@ -1563,13 +1563,13 @@ void conf(struct ctx *c, int argc, char **argv) case 'T': case 'U': if (name == 't') - fwd = &c->tcp.fwd_mode_in; + fwd = &c->tcp.fwd_in.mode; else if (name == 'T') - fwd = &c->tcp.fwd_mode_out; + fwd = &c->tcp.fwd_out.mode; else if (name == 'u') - fwd = &c->udp.fwd_mode_in; + fwd = &c->udp.fwd_in.f.mode; else if (name == 'U') - fwd = &c->udp.fwd_mode_out; + fwd = &c->udp.fwd_out.f.mode; if (!optarg || conf_ports(c, name, optarg, fwd)) usage(argv[0]); @@ -1606,33 +1606,33 @@ void conf(struct ctx *c, int argc, char **argv) c->proc_net_udp[V4][0] = c->proc_net_udp[V4][1] = -1; c->proc_net_udp[V6][0] = c->proc_net_udp[V6][1] = -1; - if (!c->tcp.fwd_mode_in || c->tcp.fwd_mode_in == FWD_AUTO) { - c->tcp.fwd_mode_in = FWD_AUTO; + if (!c->tcp.fwd_in.mode || c->tcp.fwd_in.mode == FWD_AUTO) { + c->tcp.fwd_in.mode = FWD_AUTO; ns_ports_arg.proto = IPPROTO_TCP; NS_CALL(get_bound_ports_ns, &ns_ports_arg); } - if (!c->udp.fwd_mode_in || c->udp.fwd_mode_in == FWD_AUTO) { - c->udp.fwd_mode_in = FWD_AUTO; + if (!c->udp.fwd_in.f.mode || c->udp.fwd_in.f.mode == FWD_AUTO) { + c->udp.fwd_in.f.mode = FWD_AUTO; ns_ports_arg.proto = IPPROTO_UDP; NS_CALL(get_bound_ports_ns, &ns_ports_arg); } - if (!c->tcp.fwd_mode_out || c->tcp.fwd_mode_out == FWD_AUTO) { - c->tcp.fwd_mode_out = FWD_AUTO; + if (!c->tcp.fwd_out.mode || c->tcp.fwd_out.mode == FWD_AUTO) { + c->tcp.fwd_out.mode = FWD_AUTO; get_bound_ports(c, 0, IPPROTO_TCP); } - if (!c->udp.fwd_mode_out || c->udp.fwd_mode_out == FWD_AUTO) { - c->udp.fwd_mode_out = FWD_AUTO; + if (!c->udp.fwd_out.f.mode || c->udp.fwd_out.f.mode == FWD_AUTO) { + c->udp.fwd_out.f.mode = FWD_AUTO; get_bound_ports(c, 0, IPPROTO_UDP); } } else { - if (!c->tcp.fwd_mode_in) - c->tcp.fwd_mode_in = FWD_NONE; - if (!c->tcp.fwd_mode_out) - c->tcp.fwd_mode_out= FWD_NONE; - if (!c->udp.fwd_mode_in) - c->udp.fwd_mode_in = FWD_NONE; - if (!c->udp.fwd_mode_out) - c->udp.fwd_mode_out = FWD_NONE; + if (!c->tcp.fwd_in.mode) + c->tcp.fwd_in.mode = FWD_NONE; + if (!c->tcp.fwd_out.mode) + c->tcp.fwd_out.mode = FWD_NONE; + if (!c->udp.fwd_in.f.mode) + c->udp.fwd_in.f.mode = FWD_NONE; + if (!c->udp.fwd_out.f.mode) + c->udp.fwd_out.f.mode = FWD_NONE; } if (!c->quiet) diff --git a/port_fwd.h b/port_fwd.h index b938022..7e6a7d7 100644 --- a/port_fwd.h +++ b/port_fwd.h @@ -16,4 +16,16 @@ enum port_fwd_mode { #define PORT_BITMAP_SIZE DIV_ROUND_UP(USHRT_MAX, 8) +/** + * port_fwd - Describes port forwarding for one protocol and direction + * @mode: Overall forwarding mode (all, none, auto, specific ports) + * @map: Bitmap describing which ports are forwarded + * @delta: Offset between the original destination and mapped port number + */ +struct port_fwd { + enum port_fwd_mode mode; + uint8_t map[PORT_BITMAP_SIZE]; + in_port_t delta[USHRT_MAX]; +}; + #endif /* PORT_FWD_H */ diff --git a/tcp.c b/tcp.c index 0bdef7f..e44177f 100644 --- a/tcp.c +++ b/tcp.c @@ -546,10 +546,6 @@ static const char *tcp_flag_str[] __attribute((__unused__)) = { "ACK_TO_TAP_DUE", "ACK_FROM_TAP_DUE", }; -/* Port re-mappings as delta, indexed by original destination port */ -static in_port_t tcp_port_delta_to_tap [USHRT_MAX]; -static in_port_t tcp_port_delta_to_init [USHRT_MAX]; - /* Listening sockets, used for automatic port forwarding in pasta mode only */ static int tcp_sock_init_lo [USHRT_MAX][IP_VERSIONS]; static int tcp_sock_init_ext [USHRT_MAX][IP_VERSIONS]; @@ -954,22 +950,24 @@ static void conn_event_do(const struct ctx *c, struct tcp_conn *conn, /** * tcp_remap_to_tap() - Set delta for port translation toward guest/tap + * @c: Execution context * @port: Original destination port, host order * @delta: Delta to be added to original destination port */ -void tcp_remap_to_tap(in_port_t port, in_port_t delta) +void tcp_remap_to_tap(struct ctx *c, in_port_t port, in_port_t delta) { - tcp_port_delta_to_tap[port] = delta; + c->tcp.fwd_in.delta[port] = delta; } /** * tcp_remap_to_tap() - Set delta for port translation toward init namespace + * @c: Execution context * @port: Original destination port, host order * @delta: Delta to be added to original destination port */ -void tcp_remap_to_init(in_port_t port, in_port_t delta) +void tcp_remap_to_init(struct ctx *c, in_port_t port, in_port_t delta) { - tcp_port_delta_to_init[port] = delta; + c->tcp.fwd_out.delta[port] = delta; } /** @@ -3109,11 +3107,9 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af, int s; if (ns) { - tref.tcp.index = (in_port_t)(port + - tcp_port_delta_to_init[port]); + tref.tcp.index = (in_port_t)(port + c->tcp.fwd_out.delta[port]); } else { - tref.tcp.index = (in_port_t)(port + - tcp_port_delta_to_tap[port]); + tref.tcp.index = (in_port_t)(port + c->tcp.fwd_in.delta[port]); } if (af == AF_INET || af == AF_UNSPEC) { @@ -3133,7 +3129,7 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af, else s = -1; - if (c->tcp.fwd_mode_in == FWD_AUTO) + if (c->tcp.fwd_in.mode == FWD_AUTO) tcp_sock_init_ext[port][V4] = s; } @@ -3148,7 +3144,7 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af, else s = -1; - if (c->tcp.fwd_mode_out == FWD_AUTO) { + if (c->tcp.fwd_out.mode == FWD_AUTO) { if (ns) tcp_sock_ns[port][V4] = s; else @@ -3174,7 +3170,7 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af, else s = -1; - if (c->tcp.fwd_mode_in == FWD_AUTO) + if (c->tcp.fwd_in.mode == FWD_AUTO) tcp_sock_init_ext[port][V6] = s; } @@ -3189,7 +3185,7 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af, else s = -1; - if (c->tcp.fwd_mode_out == FWD_AUTO) { + if (c->tcp.fwd_out.mode == FWD_AUTO) { if (ns) tcp_sock_ns[port][V6] = s; else @@ -3213,7 +3209,7 @@ static int tcp_sock_init_ns(void *arg) ns_enter(c); for (port = 0; port < USHRT_MAX; port++) { - if (!bitmap_isset(c->tcp.port_to_init, port)) + if (!bitmap_isset(c->tcp.fwd_out.map, port)) continue; tcp_sock_init(c, 1, AF_UNSPEC, NULL, port); @@ -3413,7 +3409,7 @@ static int tcp_port_rebind(void *arg) ns_enter(a->c); for (port = 0; port < USHRT_MAX; port++) { - if (!bitmap_isset(a->c->tcp.port_to_init, port)) { + if (!bitmap_isset(a->c->tcp.fwd_out.map, port)) { if (tcp_sock_ns[port][V4] >= 0) { close(tcp_sock_ns[port][V4]); tcp_sock_ns[port][V4] = -1; @@ -3428,7 +3424,7 @@ static int tcp_port_rebind(void *arg) } /* Don't loop back our own ports */ - if (bitmap_isset(a->c->tcp.port_to_tap, port)) + if (bitmap_isset(a->c->tcp.fwd_in.map, port)) continue; if ((a->c->ifi4 && tcp_sock_ns[port][V4] == -1) || @@ -3437,7 +3433,7 @@ static int tcp_port_rebind(void *arg) } } else { for (port = 0; port < USHRT_MAX; port++) { - if (!bitmap_isset(a->c->tcp.port_to_tap, port)) { + if (!bitmap_isset(a->c->tcp.fwd_in.map, port)) { if (tcp_sock_init_ext[port][V4] >= 0) { close(tcp_sock_init_ext[port][V4]); tcp_sock_init_ext[port][V4] = -1; @@ -3461,7 +3457,7 @@ static int tcp_port_rebind(void *arg) } /* Don't loop back our own ports */ - if (bitmap_isset(a->c->tcp.port_to_init, port)) + if (bitmap_isset(a->c->tcp.fwd_out.map, port)) continue; if ((a->c->ifi4 && tcp_sock_init_ext[port][V4] == -1) || @@ -3489,14 +3485,14 @@ void tcp_timer(struct ctx *c, const struct timespec *ts) struct tcp_port_detect_arg detect_arg = { c, 0 }; struct tcp_port_rebind_arg rebind_arg = { c, 0 }; - if (c->tcp.fwd_mode_in == FWD_AUTO) { + if (c->tcp.fwd_in.mode == FWD_AUTO) { detect_arg.detect_in_ns = 0; tcp_port_detect(&detect_arg); rebind_arg.bind_in_ns = 1; NS_CALL(tcp_port_rebind, &rebind_arg); } - if (c->tcp.fwd_mode_out == FWD_AUTO) { + if (c->tcp.fwd_out.mode == FWD_AUTO) { detect_arg.detect_in_ns = 1; NS_CALL(tcp_port_detect, &detect_arg); rebind_arg.bind_in_ns = 0; diff --git a/tcp.h b/tcp.h index ed797d9..502b096 100644 --- a/tcp.h +++ b/tcp.h @@ -29,8 +29,8 @@ void tcp_defer_handler(struct ctx *c); void tcp_sock_set_bufsize(const struct ctx *c, int s); void tcp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s, const uint32_t *ip_da); -void tcp_remap_to_tap(in_port_t port, in_port_t delta); -void tcp_remap_to_init(in_port_t port, in_port_t delta); +void tcp_remap_to_tap(struct ctx *c, in_port_t port, in_port_t delta); +void tcp_remap_to_init(struct ctx *c, in_port_t port, in_port_t delta); /** * union tcp_epoll_ref - epoll reference portion for TCP connections @@ -58,9 +58,8 @@ union tcp_epoll_ref { * @conn_count: Count of connections (not spliced) in connection table * @splice_conn_count: Count of spliced connections in connection table * @port_to_tap: Ports bound host-side, packets to tap or spliced - * @fwd_mode_in: Port forwarding mode for inbound packets - * @port_to_init: Ports bound namespace-side, spliced to init - * @fwd_mode_out: Port forwarding mode for outbound packets + * @fwd_in: Port forwarding configuration for inbound packets + * @fwd_out: Port forwarding configuration for outbound packets * @timer_run: Timestamp of most recent timer run * @kernel_snd_wnd: Kernel reports sending window (with commit 8f7baad7f035) * @pipe_size: Size of pipes for spliced connections @@ -69,10 +68,8 @@ struct tcp_ctx { uint64_t hash_secret[2]; int conn_count; int splice_conn_count; - uint8_t port_to_tap [PORT_BITMAP_SIZE]; - enum port_fwd_mode fwd_mode_in; - uint8_t port_to_init [PORT_BITMAP_SIZE]; - enum port_fwd_mode fwd_mode_out; + struct port_fwd fwd_in; + struct port_fwd fwd_out; struct timespec timer_run; #ifdef HAS_SND_WND int kernel_snd_wnd; diff --git a/tcp_splice.c b/tcp_splice.c index 61e9b23..edbcfd4 100644 --- a/tcp_splice.c +++ b/tcp_splice.c @@ -514,7 +514,7 @@ static int tcp_splice_new(const struct ctx *c, struct tcp_splice_conn *conn, struct tcp_splice_connect_ns_arg ns_arg = { c, conn, port, 0 }; int *p, i, s = -1; - if (bitmap_isset(c->tcp.port_to_tap, port)) + if (bitmap_isset(c->tcp.fwd_in.map, port)) p = CONN_V6(conn) ? ns_sock_pool6 : ns_sock_pool4; else p = CONN_V6(conn) ? init_sock_pool6 : init_sock_pool4; @@ -525,7 +525,7 @@ static int tcp_splice_new(const struct ctx *c, struct tcp_splice_conn *conn, break; } - if (s < 0 && bitmap_isset(c->tcp.port_to_tap, port)) { + if (s < 0 && bitmap_isset(c->tcp.fwd_in.map, port)) { NS_CALL(tcp_splice_connect_ns, &ns_arg); return ns_arg.ret; } diff --git a/udp.c b/udp.c index 0b4e134..38bb8d8 100644 --- a/udp.c +++ b/udp.c @@ -166,12 +166,6 @@ struct udp_splice_port { static struct udp_tap_port udp_tap_map [IP_VERSIONS][USHRT_MAX]; static struct udp_splice_port udp_splice_map [IP_VERSIONS][USHRT_MAX]; -/* Port re-mappings as delta, indexed by original destination port */ -static in_port_t udp_port_delta_to_tap [USHRT_MAX]; -static in_port_t udp_port_delta_from_tap [USHRT_MAX]; -static in_port_t udp_port_delta_to_init [USHRT_MAX]; -static in_port_t udp_port_delta_from_init[USHRT_MAX]; - enum udp_act_type { UDP_ACT_TAP, UDP_ACT_NS_CONN, @@ -265,24 +259,26 @@ static struct mmsghdr udp_mmh_sendto [UDP_SPLICE_FRAMES]; /** * udp_remap_to_tap() - Set delta for port translation to/from guest/tap + * @c: Execution context * @port: Original destination port, host order * @delta: Delta to be added to original destination port */ -void udp_remap_to_tap(in_port_t port, in_port_t delta) +void udp_remap_to_tap(struct ctx *c, in_port_t port, in_port_t delta) { - udp_port_delta_to_tap[port] = delta; - udp_port_delta_from_tap[port + delta] = USHRT_MAX - delta; + c->udp.fwd_in.f.delta[port] = delta; + c->udp.fwd_in.rdelta[port + delta] = USHRT_MAX - delta; } /** * udp_remap_to_init() - Set delta for port translation to/from init namespace + * @c: Execution context * @port: Original destination port, host order * @delta: Delta to be added to original destination port */ -void udp_remap_to_init(in_port_t port, in_port_t delta) +void udp_remap_to_init(struct ctx *c, in_port_t port, in_port_t delta) { - udp_port_delta_to_init[port] = delta; - udp_port_delta_from_init[port + delta] = USHRT_MAX - delta; + c->udp.fwd_out.f.delta[port] = delta; + c->udp.fwd_out.rdelta[port + delta] = USHRT_MAX - delta; } /** @@ -583,7 +579,7 @@ static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref, switch (ref.r.p.udp.udp.splice) { case UDP_TO_NS: - src += udp_port_delta_from_init[src]; + src += c->udp.fwd_out.rdelta[src]; if (!(s = udp_splice_map[v6][src].ns_conn_sock)) { struct udp_splice_connect_ns_arg arg = { @@ -603,7 +599,7 @@ static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref, send_dst = udp_splice_map[v6][dst].init_dst_port; break; case UDP_TO_INIT: - src += udp_port_delta_from_tap[src]; + src += c->udp.fwd_in.rdelta[src]; if (!(s = udp_splice_map[v6][src].init_conn_sock)) { s = udp_splice_connect(c, v6, ref.r.s, src, dst, @@ -1121,10 +1117,10 @@ void udp_sock_init(const struct ctx *c, int ns, sa_family_t af, if (ns) { uref.udp.port = (in_port_t)(port + - udp_port_delta_to_init[port]); + c->udp.fwd_out.f.delta[port]); } else { uref.udp.port = (in_port_t)(port + - udp_port_delta_to_tap[port]); + c->udp.fwd_in.f.delta[port]); } if (af == AF_INET || af == AF_UNSPEC) { @@ -1209,7 +1205,7 @@ int udp_sock_init_ns(void *arg) return 0; for (dst = 0; dst < USHRT_MAX; dst++) { - if (!bitmap_isset(c->udp.port_to_init, dst)) + if (!bitmap_isset(c->udp.fwd_out.f.map, dst)) continue; udp_sock_init(c, 1, AF_UNSPEC, NULL, dst); diff --git a/udp.h b/udp.h index 706306c..cfd1a97 100644 --- a/udp.h +++ b/udp.h @@ -18,8 +18,8 @@ int udp_init(const struct ctx *c); void udp_timer(struct ctx *c, const struct timespec *ts); void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s, const uint32_t *ip_da); -void udp_remap_to_tap(in_port_t port, in_port_t delta); -void udp_remap_to_init(in_port_t port, in_port_t delta); +void udp_remap_to_tap(struct ctx *c, in_port_t port, in_port_t delta); +void udp_remap_to_init(struct ctx *c, in_port_t port, in_port_t delta); /** * union udp_epoll_ref - epoll reference portion for TCP connections @@ -44,19 +44,26 @@ union udp_epoll_ref { uint32_t u32; }; + +/** + * udp_port_fwd - UDP specific port forwarding configuration + * @f: Generic forwarding configuration + * @rdelta: Reversed delta map to translate source ports on return packets + */ +struct udp_port_fwd { + struct port_fwd f; + in_port_t rdelta[USHRT_MAX]; +}; + /** * struct udp_ctx - Execution context for UDP - * @port_to_tap: Ports bound host-side, data to tap or ns L4 socket - * @fwd_mode_in: Port forwarding mode for inbound packets - * @port_to_init: Ports bound namespace-side, data to init L4 socket - * @fwd_mode_out: Port forwarding mode for outbound packets + * @fwd_in: Port forwarding configuration for inbound packets + * @fwd_out: Port forwarding configuration for outbound packets * @timer_run: Timestamp of most recent timer run */ struct udp_ctx { - uint8_t port_to_tap [PORT_BITMAP_SIZE]; - enum port_fwd_mode fwd_mode_in; - uint8_t port_to_init [PORT_BITMAP_SIZE]; - enum port_fwd_mode fwd_mode_out; + struct udp_port_fwd fwd_in; + struct udp_port_fwd fwd_out; struct timespec timer_run; };