After recent changes, conf_ip() now has essentially entirely disjoint paths for IPv4 and IPv6 configuration. So, it's cleaner to split them out into different functions conf_ip4() and conf_ip6(). Splitting these out also lets us make the interface a bit nicer, having them return success or failure directly, rather than manipulating c->v4 and c->v6 to indicate success/failure of the two versions. Since these functions may also initialize the interface index for each protocol, it turns out we can then drop c->v4 and c->v6 entirely, replacing tests on those with tests on whether c->ifi4 or c->ifi6 is non-zero (since a 0 interface index is never valid). Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au> --- conf.c | 150 ++++++++++++++++++++++++++++++-------------------------- passt.c | 4 +- passt.h | 8 +-- pasta.c | 4 +- tap.c | 4 +- tcp.c | 20 ++++---- udp.c | 8 +-- 7 files changed, 103 insertions(+), 95 deletions(-) diff --git a/conf.c b/conf.c index 63f0f3d..2a4ef23 100644 --- a/conf.c +++ b/conf.c @@ -411,8 +411,8 @@ static void get_dns(struct ctx *c) int line_len; char *line, *p, *end; - dns4_set = !c->v4 || !!*dns4; - dns6_set = !c->v6 || !IN6_IS_ADDR_UNSPECIFIED(dns6); + dns4_set = !c->ifi4 || !!*dns4; + dns6_set = !c->ifi6 || !IN6_IS_ADDR_UNSPECIFIED(dns6); dnss_set = !!*s->n || c->no_dns_search; dns_set = (dns4_set && dns6_set) || c->no_dns; @@ -611,87 +611,93 @@ static int conf_ns_opt(struct ctx *c, } /** - * conf_ip() - Verify or detect IPv4/IPv6 support, get relevant addresses + * conf_ip4() - Verify or detect IPv4 support, get relevant addresses * @c: Execution context + * @ifi: Host interface to attempt (0 to determine one) + * + * Return: Interface index for IPv4, or 0 on failure. */ -static void conf_ip(struct ctx *c) +static unsigned int conf_ip4(struct ctx *c, unsigned int ifi) { - if (c->v4) { - if (!c->ifi4) - c->ifi4 = nl_get_ext_if(AF_INET); - if (!c->ifi4) { - warn("No external routable interface for IPv4"); - c->v4 = 0; - } - } + if (!ifi) + ifi = nl_get_ext_if(AF_INET); - if (c->v6) { - if (!c->ifi6) - c->ifi6 = nl_get_ext_if(AF_INET6); - if (!c->ifi6) { - warn("No external routable interface for IPv6"); - c->v6 = 0; - } + if (!ifi) { + warn("No external routable interface for IPv4"); + return 0; } - if (c->v4) { - if (!c->gw4) - nl_route(0, c->ifi4, AF_INET, &c->gw4); + if (!c->gw4) + nl_route(0, ifi, AF_INET, &c->gw4); - if (!c->addr4) { - int mask_len = 0; + if (!c->addr4) { + int mask_len = 0; - nl_addr(0, c->ifi4, AF_INET, &c->addr4, &mask_len, NULL); - c->mask4 = htonl(0xffffffff << (32 - mask_len)); - } + nl_addr(0, ifi, AF_INET, &c->addr4, &mask_len, NULL); + c->mask4 = htonl(0xffffffff << (32 - mask_len)); + } - if (!c->mask4) { - if (IN_CLASSA(ntohl(c->addr4))) - c->mask4 = htonl(IN_CLASSA_NET); - else if (IN_CLASSB(ntohl(c->addr4))) - c->mask4 = htonl(IN_CLASSB_NET); - else if (IN_CLASSC(ntohl(c->addr4))) - c->mask4 = htonl(IN_CLASSC_NET); - else - c->mask4 = 0xffffffff; - } + if (!c->mask4) { + if (IN_CLASSA(ntohl(c->addr4))) + c->mask4 = htonl(IN_CLASSA_NET); + else if (IN_CLASSB(ntohl(c->addr4))) + c->mask4 = htonl(IN_CLASSB_NET); + else if (IN_CLASSC(ntohl(c->addr4))) + c->mask4 = htonl(IN_CLASSC_NET); + else + c->mask4 = 0xffffffff; + } - memcpy(&c->addr4_seen, &c->addr4, sizeof(c->addr4_seen)); + memcpy(&c->addr4_seen, &c->addr4, sizeof(c->addr4_seen)); - if (MAC_IS_ZERO(c->mac)) - nl_link(0, c->ifi4, c->mac, 0, 0); - } + if (MAC_IS_ZERO(c->mac)) + nl_link(0, ifi, c->mac, 0, 0); - if (c->v6) { - int prefix_len = 0; + if (!c->gw4 || !c->addr4 || MAC_IS_ZERO(c->mac)) + return 0; - if (IN6_IS_ADDR_UNSPECIFIED(&c->gw6)) - nl_route(0, c->ifi6, AF_INET6, &c->gw6); + return ifi; +} - nl_addr(0, c->ifi6, AF_INET6, - IN6_IS_ADDR_UNSPECIFIED(&c->addr6) ? &c->addr6 : NULL, - &prefix_len, &c->addr6_ll); +/** + * conf_ip6() - Verify or detect IPv6 support, get relevant addresses + * @c: Execution context + * @ifi: Host interface to attempt (0 to determine one) + * + * Return: Interface index for IPv6, or 0 on failure. + */ +static unsigned int conf_ip6(struct ctx *c, unsigned int ifi) +{ + int prefix_len = 0; - memcpy(&c->addr6_seen, &c->addr6, sizeof(c->addr6)); - memcpy(&c->addr6_ll_seen, &c->addr6_ll, sizeof(c->addr6_ll)); + if (!ifi) + ifi = nl_get_ext_if(AF_INET6); - if (MAC_IS_ZERO(c->mac)) - nl_link(0, c->ifi6, c->mac, 0, 0); + if (!ifi) { + warn("No external routable interface for IPv6"); + return 0; } - if (!c->gw4 || !c->addr4 || MAC_IS_ZERO(c->mac)) - c->v4 = 0; + if (IN6_IS_ADDR_UNSPECIFIED(&c->gw6)) + nl_route(0, ifi, AF_INET6, &c->gw6); + + nl_addr(0, ifi, AF_INET6, + IN6_IS_ADDR_UNSPECIFIED(&c->addr6) ? &c->addr6 : NULL, + &prefix_len, &c->addr6_ll); + + memcpy(&c->addr6_seen, &c->addr6, sizeof(c->addr6)); + memcpy(&c->addr6_ll_seen, &c->addr6_ll, sizeof(c->addr6_ll)); + + if (MAC_IS_ZERO(c->mac)) + nl_link(0, ifi, c->mac, 0, 0); if (IN6_IS_ADDR_UNSPECIFIED(&c->gw6) || IN6_IS_ADDR_UNSPECIFIED(&c->addr6) || IN6_IS_ADDR_UNSPECIFIED(&c->addr6_ll) || MAC_IS_ZERO(c->mac)) - c->v6 = 0; + return 0; - if (!c->v4 && !c->v6) { - err("External interface not usable"); - exit(EXIT_FAILURE); - } + return ifi; } /** @@ -889,7 +895,7 @@ static void conf_print(const struct ctx *c) c->mac[0], c->mac[1], c->mac[2], c->mac[3], c->mac[4], c->mac[5]); - if (c->v4) { + if (c->ifi4) { if (!c->no_dhcp) { info("DHCP:"); info(" assign: %s", @@ -914,7 +920,7 @@ static void conf_print(const struct ctx *c) } } - if (c->v6) { + if (c->ifi6) { char buf6[INET6_ADDRSTRLEN]; if (!c->no_ndp && !c->no_dhcpv6) @@ -1063,6 +1069,7 @@ void conf(struct ctx *c, int argc, char **argv) int name, ret, mask, b, i; uint32_t *dns4 = c->dns4; bool v4_only = false, v6_only = false; + unsigned int ifi = 0; if (c->mode == MODE_PASTA) c->no_dhcp_dns = c->no_dhcp_dns_search = 1; @@ -1390,12 +1397,12 @@ void conf(struct ctx *c, int argc, char **argv) usage(argv[0]); break; case 'i': - if (c->ifi4 || c->ifi6) { + if (ifi) { err("Redundant interface: %s", optarg); usage(argv[0]); } - if (!(c->ifi4 = c->ifi6 = if_nametoindex(optarg))) { + if (!(ifi = if_nametoindex(optarg))) { err("Invalid interface name %s: %s", optarg, strerror(errno)); usage(argv[0]); @@ -1503,10 +1510,15 @@ void conf(struct ctx *c, int argc, char **argv) err("Options ipv4-only and ipv6-only are mutually exclusive"); usage(argv[0]); } - c->v4 = !v6_only; - c->v6 = !v4_only; - conf_ip(c); - + if (!v6_only) + c->ifi4 = conf_ip4(c, ifi); + if (!v4_only) + c->ifi6 = conf_ip6(c, ifi); + if (!c->ifi4 && !c->ifi6) { + err("External interface not usable"); + exit(EXIT_FAILURE); + } + /* Now we can process port configuration options */ optind = 1; do { @@ -1542,10 +1554,10 @@ void conf(struct ctx *c, int argc, char **argv) } } while (name != -1); - if (!c->v4) + if (!c->ifi4) c->no_dhcp = 1; - if (!c->v6) { + if (!c->ifi6) { c->no_ndp = 1; c->no_dhcpv6 = 1; } diff --git a/passt.c b/passt.c index a8d94b4..18c3512 100644 --- a/passt.c +++ b/passt.c @@ -365,10 +365,10 @@ int main(int argc, char **argv) proto_update_l2_buf(c.mac_guest, c.mac, &c.addr4); - if (c.v4 && !c.no_dhcp) + if (c.ifi4 && !c.no_dhcp) dhcp_init(); - if (c.v6 && !c.no_dhcpv6) + if (c.ifi6 && !c.no_dhcpv6) dhcpv6_init(&c); if (c.debug) diff --git a/passt.h b/passt.h index 23145c6..a8d5992 100644 --- a/passt.h +++ b/passt.h @@ -121,8 +121,7 @@ enum passt_modes { * @fd_tap: File descriptor for AF_UNIX socket or tuntap device * @mac: Host MAC address * @mac_guest: MAC address of guest or namespace, seen or configured - * @v4: Enable IPv4 transport - * @ifi4: Index of routable interface for IPv4 + * @ifi4: Index of routable interface for IPv4, 0 if IPv4 disabled * @addr4: IPv4 address for external, routable interface * @addr4_seen: Latest IPv4 address seen as source from tap * @mask4: IPv4 netmask, network order @@ -130,8 +129,7 @@ enum passt_modes { * @dns4: IPv4 DNS addresses, zero-terminated, network order * @dns4_fwd: Address forwarded (UDP) to first IPv4 DNS, network order * @dns_search: DNS search list - * @v6: Enable IPv6 transport - * @ifi6: Index of routable interface for IPv6 + * @ifi6: Index of routable interface for IPv6, 0 if IPv6 disabled * @addr6: IPv6 address for external, routable interface * @addr6_ll: Link-local IPv6 address on external, routable interface * @addr6_seen: Latest IPv6 global/site address seen as source from tap @@ -193,7 +191,6 @@ struct ctx { unsigned char mac[ETH_ALEN]; unsigned char mac_guest[ETH_ALEN]; - int v4; unsigned int ifi4; uint32_t addr4; uint32_t addr4_seen; @@ -204,7 +201,6 @@ struct ctx { struct fqdn dns_search[MAXDNSRCH]; - int v6; unsigned int ifi6; struct in6_addr addr6; struct in6_addr addr6_ll; diff --git a/pasta.c b/pasta.c index cd37d16..2d7b5a1 100644 --- a/pasta.c +++ b/pasta.c @@ -195,14 +195,14 @@ void pasta_ns_conf(struct ctx *c) nl_link(1, c->pasta_ifi, c->mac_guest, 1, c->mtu); - if (c->v4) { + if (c->ifi4) { prefix_len = __builtin_popcount(c->mask4); nl_addr(1, c->pasta_ifi, AF_INET, &c->addr4, &prefix_len, NULL); nl_route(1, c->pasta_ifi, AF_INET, &c->gw4); } - if (c->v6) { + if (c->ifi6) { prefix_len = 64; nl_addr(1, c->pasta_ifi, AF_INET6, &c->addr6, &prefix_len, NULL); diff --git a/tap.c b/tap.c index 43a7372..8d552e9 100644 --- a/tap.c +++ b/tap.c @@ -318,7 +318,7 @@ static int tap4_handler(struct ctx *c, const struct pool *in, unsigned int i, j, seq_count; struct tap4_l4_t *seq; - if (!c->v4 || !in->count) + if (!c->ifi4 || !in->count) return in->count; i = 0; @@ -471,7 +471,7 @@ static int tap6_handler(struct ctx *c, const struct pool *in, unsigned int i, j, seq_count = 0; struct tap6_l4_t *seq; - if (!c->v6 || !in->count) + if (!c->ifi6 || !in->count) return in->count; i = 0; diff --git a/tcp.c b/tcp.c index 3b27f11..3382dfd 100644 --- a/tcp.c +++ b/tcp.c @@ -3252,7 +3252,7 @@ static int tcp_sock_refill(void *arg) p6 = init_sock_pool6; } - for (i = 0; a->c->v4 && i < TCP_SOCK_POOL_SIZE; i++, p4++) { + for (i = 0; a->c->ifi4 && i < TCP_SOCK_POOL_SIZE; i++, p4++) { if (*p4 >= 0) break; @@ -3267,7 +3267,7 @@ static int tcp_sock_refill(void *arg) tcp_sock_set_bufsize(a->c, *p4); } - for (i = 0; a->c->v6 && i < TCP_SOCK_POOL_SIZE; i++, p6++) { + for (i = 0; a->c->ifi6 && i < TCP_SOCK_POOL_SIZE; i++, p6++) { if (*p6 >= 0) break; @@ -3327,10 +3327,10 @@ int tcp_init(struct ctx *c) for (i = 0; i < ARRAY_SIZE(tcp_l2_mh); i++) tcp_l2_mh[i] = (struct mmsghdr) { .msg_hdr.msg_iovlen = 1 }; - if (c->v4) + if (c->ifi4) tcp_sock4_iov_init(); - if (c->v6) + if (c->ifi6) tcp_sock6_iov_init(); memset(init_sock_pool4, 0xff, sizeof(init_sock_pool4)); @@ -3431,8 +3431,8 @@ static int tcp_port_rebind(void *arg) if (bitmap_isset(a->c->tcp.port_to_tap, port)) continue; - if ((a->c->v4 && tcp_sock_ns[port][V4] == -1) || - (a->c->v6 && tcp_sock_ns[port][V6] == -1)) + if ((a->c->ifi4 && tcp_sock_ns[port][V4] == -1) || + (a->c->ifi6 && tcp_sock_ns[port][V6] == -1)) tcp_sock_init(a->c, 1, AF_UNSPEC, NULL, port); } } else { @@ -3464,8 +3464,8 @@ static int tcp_port_rebind(void *arg) if (bitmap_isset(a->c->tcp.port_to_init, port)) continue; - if ((a->c->v4 && tcp_sock_init_ext[port][V4] == -1) || - (a->c->v6 && tcp_sock_init_ext[port][V6] == -1)) + if ((a->c->ifi4 && tcp_sock_init_ext[port][V4] == -1) || + (a->c->ifi6 && tcp_sock_init_ext[port][V6] == -1)) tcp_sock_init(a->c, 0, AF_UNSPEC, NULL, port); } } @@ -3512,8 +3512,8 @@ void tcp_timer(struct ctx *c, const struct timespec *ts) tcp_sock_refill(&refill_arg); if (c->mode == MODE_PASTA) { refill_arg.ns = 1; - if ((c->v4 && ns_sock_pool4[TCP_SOCK_POOL_TSH] < 0) || - (c->v6 && ns_sock_pool6[TCP_SOCK_POOL_TSH] < 0)) + if ((c->ifi4 && ns_sock_pool4[TCP_SOCK_POOL_TSH] < 0) || + (c->ifi6 && ns_sock_pool6[TCP_SOCK_POOL_TSH] < 0)) NS_CALL(tcp_sock_refill, &refill_arg); tcp_splice_timer(c); diff --git a/udp.c b/udp.c index 98e3eaa..856429f 100644 --- a/udp.c +++ b/udp.c @@ -1266,10 +1266,10 @@ static void udp_splice_iov_init(void) */ int udp_init(const struct ctx *c) { - if (c->v4) + if (c->ifi4) udp_sock4_iov_init(); - if (c->v6) + if (c->ifi6) udp_sock6_iov_init(); if (c->mode == MODE_PASTA) { @@ -1341,7 +1341,7 @@ void udp_timer(struct ctx *c, const struct timespec *ts) unsigned int i; long *word, tmp; - if (!c->v4) + if (!c->ifi4) v6 = 1; v6: for (t = 0; t < UDP_ACT_TYPE_MAX; t++) { @@ -1356,7 +1356,7 @@ v6: } } - if (!v6 && c->v6) { + if (!v6 && c->ifi6) { v6 = 1; goto v6; } -- 2.37.1