diff options
Diffstat (limited to 'conf.c')
| -rw-r--r-- | conf.c | 157 |
1 files changed, 95 insertions, 62 deletions
@@ -373,13 +373,19 @@ static uint8_t conf_ip4_prefix(const char *arg) /** * conf_ip4() - Verify or detect IPv4 support, get relevant addresses + * @c: Execution context * @ifi: Host interface to attempt (0 to determine one) - * @ip4: IPv4 context (will be written) * * Return: interface index for IPv4, or 0 on failure. */ -static unsigned int conf_ip4(unsigned int ifi, struct ip4_ctx *ip4) +static unsigned int conf_ip4(struct ctx *c, unsigned int ifi) { + struct ip4_ctx *ip4 = &c->ip4; + const struct guest_addr *a; + const struct in_addr *a4; + + a = fwd_get_addr(c, AF_INET, true, CONF_ADDR_ANY); + if (!ifi) ifi = nl_get_ext_if(nl_sock, AF_INET); @@ -398,67 +404,75 @@ static unsigned int conf_ip4(unsigned int ifi, struct ip4_ctx *ip4) } } - if (IN4_IS_ADDR_UNSPECIFIED(&ip4->addr)) { + if (!a) { + struct in_addr addr = { 0 }; + int prefix_len = 0; int rc = nl_addr_get(nl_sock, ifi, AF_INET, - &ip4->addr, &ip4->prefix_len, NULL); + &addr, &prefix_len, NULL); if (rc < 0) { debug("Couldn't discover IPv4 address: %s", strerror_(-rc)); return 0; } + if (IN4_IS_ADDR_UNSPECIFIED(&addr)) { + warn("Host returned address 0.0.0.0"); + return 0; + } + fwd_set_addr(c, &inany_from_v4(addr), CONF_ADDR_HOST, + prefix_len + 96); } - if (!ip4->prefix_len) { - in_addr_t addr = ntohl(ip4->addr.s_addr); - if (IN_CLASSA(addr)) - ip4->prefix_len = (32 - IN_CLASSA_NSHIFT); - else if (IN_CLASSB(addr)) - ip4->prefix_len = (32 - IN_CLASSB_NSHIFT); - else if (IN_CLASSC(addr)) - ip4->prefix_len = (32 - IN_CLASSC_NSHIFT); - else - ip4->prefix_len = 32; - } - - ip4->addr_seen = ip4->addr; - + a = fwd_get_addr(c, AF_INET, true, CONF_ADDR_ANY); + assert(a); + a4 = inany_v4(&a->addr); + assert(a4); + ip4->addr_seen = *a4; ip4->our_tap_addr = ip4->guest_gw; - if (IN4_IS_ADDR_UNSPECIFIED(&ip4->addr)) - return 0; - return ifi; } /** * conf_ip4_local() - Configure IPv4 addresses and attributes for local mode - * @ip4: IPv4 context (will be written) + * @c: Execution context (will be written) */ -static void conf_ip4_local(struct ip4_ctx *ip4) +static void conf_ip4_local(struct ctx *c) { - if (IN4_IS_ADDR_UNSPECIFIED(&ip4->addr)) - ip4->addr = IP4_LL_GUEST_ADDR; - ip4->addr_seen = ip4->addr; + struct ip4_ctx *ip4 = &c->ip4; + const struct guest_addr *a; + + a = fwd_get_addr(c, AF_INET, true, CONF_ADDR_ANY); + + if (!a) { + fwd_set_addr(c, &inany_from_v4(IP4_LL_GUEST_ADDR), + CONF_ADDR_GEN, IP4_LL_PREFIX_LEN + 96); + ip4->addr_seen = IP4_LL_GUEST_ADDR; + } else { + const struct in_addr *a4 = inany_v4(&a->addr); + + assert(a4); + ip4->addr_seen = *a4; + } if (IN4_IS_ADDR_UNSPECIFIED(&ip4->guest_gw)) ip4->guest_gw = IP4_LL_GUEST_GW; ip4->our_tap_addr = ip4->guest_gw; - if (!ip4->prefix_len) - ip4->prefix_len = IP4_LL_PREFIX_LEN; - ip4->no_copy_addrs = ip4->no_copy_routes = true; } /** * conf_ip6() - Verify or detect IPv6 support, get relevant addresses + * @c: Execution context * @ifi: Host interface to attempt (0 to determine one) - * @ip6: IPv6 context (will be written) * * Return: interface index for IPv6, or 0 on failure. */ -static unsigned int conf_ip6(unsigned int ifi, struct ip6_ctx *ip6) +static unsigned int conf_ip6(struct ctx *c, unsigned int ifi) { + struct ip6_ctx *ip6 = &c->ip6; + const struct guest_addr *a; + union inany_addr addr; int prefix_len = 0; int rc; @@ -479,23 +493,30 @@ static unsigned int conf_ip6(unsigned int ifi, struct ip6_ctx *ip6) } } - rc = nl_addr_get(nl_sock, ifi, AF_INET6, - IN6_IS_ADDR_UNSPECIFIED(&ip6->addr) ? &ip6->addr : NULL, + rc = nl_addr_get(nl_sock, ifi, AF_INET6, &addr.a6, &prefix_len, &ip6->our_tap_ll); if (rc < 0) { debug("Couldn't discover IPv6 address: %s", strerror_(-rc)); return 0; } - ip6->addr_seen = ip6->addr; + a = fwd_get_addr(c, AF_INET6, true, CONF_ADDR_ANY); + if (!a) { + if (IN6_IS_ADDR_UNSPECIFIED(&addr)) + return 0; + + fwd_set_addr(c, &addr, CONF_ADDR_HOST, prefix_len); + ip6->addr_seen = addr.a6; + } else { + ip6->addr_seen = a->addr.a6; + } if (IN6_IS_ADDR_LINKLOCAL(&ip6->guest_gw)) ip6->our_tap_ll = ip6->guest_gw; else ip6->our_tap_addr = ip6->guest_gw; - if (IN6_IS_ADDR_UNSPECIFIED(&ip6->addr) || - IN6_IS_ADDR_UNSPECIFIED(&ip6->our_tap_ll)) + if (IN6_IS_ADDR_UNSPECIFIED(&ip6->our_tap_ll)) return 0; return ifi; @@ -503,10 +524,12 @@ static unsigned int conf_ip6(unsigned int ifi, struct ip6_ctx *ip6) /** * conf_ip6_local() - Configure IPv6 addresses and attributes for local mode - * @ip6: IPv6 context (will be written) + * @c: Execution context (will be written) */ -static void conf_ip6_local(struct ip6_ctx *ip6) +static void conf_ip6_local(struct ctx *c) { + struct ip6_ctx *ip6 = &c->ip6; + if (IN6_IS_ADDR_UNSPECIFIED(&ip6->guest_gw)) ip6->guest_gw = IP6_LL_GUEST_GW; @@ -805,6 +828,7 @@ enum passt_modes conf_mode(int argc, char *argv[]) static void conf_print(const struct ctx *c) { char buf[INANY_ADDRSTRLEN]; + const struct guest_addr *a; int i; if (c->fd_control_listen >= 0) @@ -852,16 +876,19 @@ static void conf_print(const struct ctx *c) inet_ntop(AF_INET, &c->ip4.map_host_loopback, buf, sizeof(buf))); - if (!c->no_dhcp) { + a = fwd_get_addr(c, AF_INET, true, CONF_ADDR_ANY); + if (a && !c->no_dhcp) { uint32_t mask; + int plen = 0; - mask = htonl(0xffffffff << (32 - c->ip4.prefix_len)); + inany_prefix_v4(&a->addr, a->prefix_len, &plen); + mask = IN4_MASK(plen); info("DHCP:"); info(" assign: %s", - inet_ntop(AF_INET, &c->ip4.addr, buf, sizeof(buf))); + inany_ntop(&a->addr, buf, sizeof(buf))); info(" mask: %s", - inet_ntop(AF_INET, &mask, buf, sizeof(buf))); + inet_ntop(AF_INET, &mask, buf, sizeof(buf))); info(" router: %s", inet_ntop(AF_INET, &c->ip4.guest_gw, buf, sizeof(buf))); @@ -876,8 +903,8 @@ static void conf_print(const struct ctx *c) break; if (!i) info("DNS:"); - inet_ntop(AF_INET, &c->ip4.dns[i], buf, sizeof(buf)); - info(" %s", buf); + info(" %s", inet_ntop(AF_INET, &c->ip4.dns[i], + buf, sizeof(buf))); } for (i = 0; *c->dns_search[i].n; i++) { @@ -902,13 +929,14 @@ static void conf_print(const struct ctx *c) else goto dns6; - info(" assign: %s", - inet_ntop(AF_INET6, &c->ip6.addr, buf, sizeof(buf))); + a = fwd_get_addr(c, AF_INET6, true, CONF_ADDR_ANY); + if (a) + info(" assign: %s", + inany_ntop(&a->addr, buf, sizeof(buf))); info(" router: %s", inet_ntop(AF_INET6, &c->ip6.guest_gw, buf, sizeof(buf))); info(" our link-local: %s", - inet_ntop(AF_INET6, &c->ip6.our_tap_ll, - buf, sizeof(buf))); + inet_ntop(AF_INET6, &c->ip6.our_tap_ll, buf, sizeof(buf))); dns6: for (i = 0; i < ARRAY_SIZE(c->ip6.dns); i++) { @@ -916,8 +944,10 @@ dns6: break; if (!i) info("DNS:"); - inet_ntop(AF_INET6, &c->ip6.dns[i], buf, sizeof(buf)); - info(" %s", buf); + info(" %s", + inet_ntop(AF_INET6, &c->ip6.dns[i], + buf, sizeof(buf))); + } for (i = 0; *c->dns_search[i].n; i++) { @@ -1224,15 +1254,13 @@ static bool conf_addr(struct ctx *c, char *arg, uint8_t opt_n) inany_is_loopback(&addr)) goto bad; + fwd_set_addr(c, &addr, CONF_ADDR_USER, prefix_len); if (a4) { - c->ip4.addr = *a4; - c->ip4.prefix_len = prefix_len - 96; - c->ip4.addr_fixed = true; c->ip4.no_copy_addrs = true; + c->ip4.addr_fixed = true; } else { - c->ip6.addr = addr.a6; - c->ip6.addr_fixed = true; c->ip6.no_copy_addrs = true; + c->ip6.addr_fixed = true; } return is_prefix; @@ -1346,6 +1374,7 @@ void conf(struct ctx *c, int argc, char **argv) bool opt_a_is_prefix = false; const char *logfile = NULL; unsigned long optcode; + struct guest_addr *a; char *runas = NULL; size_t logsize = 0; uint8_t opt_n = 0; @@ -1690,8 +1719,12 @@ void conf(struct ctx *c, int argc, char **argv) if (opt_a_is_prefix) die("Redundant prefix length specification"); - c->ip4.prefix_len = conf_ip4_prefix(optarg); - opt_n = c->ip4.prefix_len + 96; + opt_n = conf_ip4_prefix(optarg) + 96; + + for_each_addr(a, c->addrs, c->addr_count, AF_INET) { + a->prefix_len = opt_n; + break; + } break; case 'M': p = optarg; @@ -1891,9 +1924,9 @@ void conf(struct ctx *c, int argc, char **argv) nl_sock_init(c, false); if (!v6_only && !c->splice_only) - c->ifi4 = conf_ip4(ifi4, &c->ip4); + c->ifi4 = conf_ip4(c, ifi4); if (!v4_only && !c->splice_only) - c->ifi6 = conf_ip6(ifi6, &c->ip6); + c->ifi6 = conf_ip6(c, ifi6); if (c->ifi4 && c->mtu < IPV4_MIN_MTU) { warn("MTU %"PRIu16" is too small for IPv4 (minimum %u)", @@ -1916,7 +1949,7 @@ void conf(struct ctx *c, int argc, char **argv) if (!c->ifi4 && !v6_only) { if (!c->splice_only) { info("IPv4: no external interface as template, use local mode"); - conf_ip4_local(&c->ip4); + conf_ip4_local(c); } c->ifi4 = -1; } @@ -1924,7 +1957,7 @@ void conf(struct ctx *c, int argc, char **argv) if (!c->ifi6 && !v4_only) { if (!c->splice_only) { info("IPv6: no external interface as template, use local mode"); - conf_ip6_local(&c->ip6); + conf_ip6_local(c); } c->ifi6 = -1; } @@ -2000,7 +2033,7 @@ void conf(struct ctx *c, int argc, char **argv) if (!c->ifi6) { c->no_ndp = 1; c->no_dhcpv6 = 1; - } else if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addr)) { + } else if (!fwd_get_addr(c, AF_INET6, true, CONF_ADDR_ANY)) { c->no_dhcpv6 = 1; } |
