From 0dd152a83012764a77ef2a7ae7bf7c20c3d43c35 Mon Sep 17 00:00:00 2001 From: Denys Fedoryshchenko Date: Mon, 10 Aug 2026 08:43:17 +0300 Subject: ipoe: fix netmask computation for classless routes The netmask was built with a loop shifting 1 into place, which was wrong in three ways. At i == 0 it evaluated 1 << 32, undefined for a 32 bit int, and at i == 1 it shifted into the sign bit of a signed value. The shift amount was off by one, so a /24 produced 0xfffffe00 rather than 0xffffff00. And mask1 was initialized once before the loop over the routes and only ever OR'ed into, so the mask of every route accumulated into the routes that followed it. A well formed option carrying 10.0.1.0/24 via 1.1.1.1 and 172.16.0.0/12 via 2.2.2.2 printed as 10.0.0.1/24 and 172.16.2.0/12. Compute the mask directly instead, and reject a prefix length above 32 rather than shifting by a negative amount. --- accel-pppd/ctrl/ipoe/dhcpv4_options.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'accel-pppd') diff --git a/accel-pppd/ctrl/ipoe/dhcpv4_options.c b/accel-pppd/ctrl/ipoe/dhcpv4_options.c index bffcfa5c..57999995 100644 --- a/accel-pppd/ctrl/ipoe/dhcpv4_options.c +++ b/accel-pppd/ctrl/ipoe/dhcpv4_options.c @@ -265,7 +265,8 @@ static void print_classless_route(const struct dhcpv4_option *opt, int elem_size { const uint8_t *ptr = opt->data; const uint8_t *endptr = ptr + opt->len; - int mask, i, mask1 = 0; + int mask; + uint32_t mask1; uint32_t ip; uint32_t gw; @@ -274,9 +275,11 @@ static void print_classless_route(const struct dhcpv4_option *opt, int elem_size print(","); mask = *ptr++; + if (mask > 32) + return; + ip = ntohl(*(uint32_t *)ptr); - for (i = 0; i < mask; i++) - mask1 |= (1 << (32 - i)); + mask1 = mask ? UINT32_MAX << (32 - mask) : 0; ip &= mask1; if (mask <= 8) ptr++; -- cgit v1.2.3