From dd09cceaee216afc90101ee5c3a2d57b1ca1a042 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 4 Nov 2022 14:10:33 +1100 Subject: Minor improvements to IPv4 netmask handling There are several minor problems with our parsing of IPv4 netmasks (-n). First, we don't reject nonsensical netmasks like 0.255.0.255. Address this structurally by using prefix length instead of netmask as the primary variable, only converting (and validating) when we need to. This has the added benefit of making some things more uniform with the IPv6 path. Second, when the user specifies a prefix length, we truncate the output from strtol() to an integer, which means we would treat -n 4294967320 as valid (equivalent to 24). Fix types to check for this. Signed-off-by: David Gibson Signed-off-by: Stefano Brivio --- dhcp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'dhcp.c') diff --git a/dhcp.c b/dhcp.c index d22698a..076e9b6 100644 --- a/dhcp.c +++ b/dhcp.c @@ -268,6 +268,7 @@ static void opt_set_dns_search(const struct ctx *c, size_t max_len) int dhcp(const struct ctx *c, const struct pool *p) { size_t mlen, len, offset = 0, opt_len, opt_off = 0; + struct in_addr mask; struct ethhdr *eh; struct iphdr *iph; struct udphdr *uh; @@ -334,14 +335,15 @@ int dhcp(const struct ctx *c, const struct pool *p) m->chaddr[3], m->chaddr[4], m->chaddr[5]); m->yiaddr = c->ip4.addr; - memcpy(opts[1].s, &c->ip4.mask, sizeof(c->ip4.mask)); + mask.s_addr = htonl(0xffffffff << c->ip4.prefix_len); + memcpy(opts[1].s, &mask, sizeof(mask)); memcpy(opts[3].s, &c->ip4.gw, sizeof(c->ip4.gw)); memcpy(opts[54].s, &c->ip4.gw, sizeof(c->ip4.gw)); /* If the gateway is not on the assigned subnet, send an option 121 * (Classless Static Routing) adding a dummy route to it. */ - if ((c->ip4.addr & c->ip4.mask) != (c->ip4.gw & c->ip4.mask)) { + if ((c->ip4.addr & mask.s_addr) != (c->ip4.gw & mask.s_addr)) { /* a.b.c.d/32:0.0.0.0, 0:a.b.c.d */ opts[121].slen = 14; opts[121].s[0] = 32; -- cgit v1.2.3