conf: Adjust netmask on mismatch between IPv4 address/netmask and gateway
Seen in a Google Compute Engine environment with a machine configured via cloud-init-dhcp, while testing Podman integration for pasta: the assigned address has a /32 netmask, and there's a default route, which can be added on the host because there's another route, also /32, pointing to the default gateway. For example, on the host: ip -4 address add 10.156.0.2/32 dev eth0 ip -4 route add 10.156.0.1/32 dev eth0 ip -4 route add default via 10.156.0.1 This is not a valid configuration as far as I can tell: if the address is configured as /32, it shouldn't be used to reach a gateway outside its derived netmask. However, Linux allows that, and everything works. The problem comes when pasta --config-net sources address and default route from the host, and it can't configure the route in the target namespace because the gateway is invalid. That is, we would skip configuring the first route in the example, which results in the equivalent of doing: ip -4 address add 10.156.0.2/32 dev eth0 ip -4 route add default via 10.156.0.1 where, at this point, 10.156.0.1 is unreachable, and hence invalid as a gateway. Sourcing more routes than just the default is doable, but probably undesirable: pasta users want to provide connectivity to a container, not reflect exactly whatever trickery is configured on the host. Add a consistency check and an adjustment: if the configured default gateway is not reachable, shrink the given netmask until we can reach it. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
parent
de93acbe70
commit
7656a6f888
1 changed files with 24 additions and 1 deletions
25
conf.c
25
conf.c
|
@ -558,6 +558,9 @@ static int conf_ip4_prefix(const char *arg)
|
||||||
static unsigned int conf_ip4(unsigned int ifi,
|
static unsigned int conf_ip4(unsigned int ifi,
|
||||||
struct ip4_ctx *ip4, unsigned char *mac)
|
struct ip4_ctx *ip4, unsigned char *mac)
|
||||||
{
|
{
|
||||||
|
in_addr_t addr, gw;
|
||||||
|
int shift;
|
||||||
|
|
||||||
if (!ifi)
|
if (!ifi)
|
||||||
ifi = nl_get_ext_if(AF_INET);
|
ifi = nl_get_ext_if(AF_INET);
|
||||||
|
|
||||||
|
@ -572,8 +575,10 @@ static unsigned int conf_ip4(unsigned int ifi,
|
||||||
if (IN4_IS_ADDR_UNSPECIFIED(&ip4->addr))
|
if (IN4_IS_ADDR_UNSPECIFIED(&ip4->addr))
|
||||||
nl_addr(0, ifi, AF_INET, &ip4->addr, &ip4->prefix_len, NULL);
|
nl_addr(0, ifi, AF_INET, &ip4->addr, &ip4->prefix_len, NULL);
|
||||||
|
|
||||||
|
addr = ntohl(ip4->addr.s_addr);
|
||||||
|
gw = ntohl(ip4->gw.s_addr);
|
||||||
|
|
||||||
if (!ip4->prefix_len) {
|
if (!ip4->prefix_len) {
|
||||||
in_addr_t addr = ntohl(ip4->addr.s_addr);
|
|
||||||
if (IN_CLASSA(addr))
|
if (IN_CLASSA(addr))
|
||||||
ip4->prefix_len = (32 - IN_CLASSA_NSHIFT);
|
ip4->prefix_len = (32 - IN_CLASSA_NSHIFT);
|
||||||
else if (IN_CLASSB(addr))
|
else if (IN_CLASSB(addr))
|
||||||
|
@ -584,6 +589,24 @@ static unsigned int conf_ip4(unsigned int ifi,
|
||||||
ip4->prefix_len = 32;
|
ip4->prefix_len = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We might get an address with a netmask that makes the default
|
||||||
|
* gateway unreachable, and in that case we would fail to configure
|
||||||
|
* the default route, with --config-net, or presumably a DHCP client
|
||||||
|
* in the guest or container would face the same issue.
|
||||||
|
*
|
||||||
|
* The host might have another route, to the default gateway itself,
|
||||||
|
* fixing the situation, but we only read default routes.
|
||||||
|
*
|
||||||
|
* Fix up the mask to allow reaching the default gateway from our
|
||||||
|
* configured address, if needed, and only if we find a non-zero
|
||||||
|
* mask that makes the gateway reachable.
|
||||||
|
*/
|
||||||
|
shift = 32 - ip4->prefix_len;
|
||||||
|
while (shift < 32 && addr >> shift != gw >> shift)
|
||||||
|
shift++;
|
||||||
|
if (shift < 32)
|
||||||
|
ip4->prefix_len = 32 - shift;
|
||||||
|
|
||||||
memcpy(&ip4->addr_seen, &ip4->addr, sizeof(ip4->addr_seen));
|
memcpy(&ip4->addr_seen, &ip4->addr, sizeof(ip4->addr_seen));
|
||||||
|
|
||||||
if (MAC_IS_ZERO(mac))
|
if (MAC_IS_ZERO(mac))
|
||||||
|
|
Loading…
Reference in a new issue