On merge: On Fri, 22 Jul 2022 15:31:17 +1000 David Gibson wrote: > [...] > > 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); I dropped the extra whitespace here (the original purpose was to align things), and... > 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); > + } > + I dropped this tab. -- Stefano