On 2021-07-18 01:02 +02, Bjorn Ketelaars <b...@openbsd.org> wrote: > On Sat 17/07/2021 17:12, Florian Obser wrote: >> >> >> On 17 July 2021 13:16:59 CEST, Bjorn Ketelaars <b...@openbsd.org> wrote: >> >An inconsistency exists between dhclient(8) and dhcpleased(8) when >> >receiving the Classless Static Routes option: dhcpleased creates a >> >default route, while dhclient does not. >> > >> >If I'm not mistaken, the behaviour of dhclient is correct. From >> >rfc3442: >> >"If the DHCP server returns both a Classless Static Routes option and a >> >Router option, the DHCP client MUST ignore the Router option." >> > >> >> Correct. But you are fixing it in the wrong place. It doesn't say to ignore >> a default route, which can be transmitted via classless static routes option >> (it's 0/0). > > That makes sense. New diff...
Not quite. This assumes that the router option comes first, a DHCP server could send us something like this: DHO_ROUTERS DHO_CLASSLESS_STATIC_ROUTES DHO_ROUTERS DHO_CLASSLESS_STATIC_ROUTES Which would be quite broken, but hey... How about this? Do you actually have a test case for this? dhcpd(8) correctly only hands me a routers option or classless static routes option, never both. diff --git engine.c engine.c index ad8202c9a33..700d7c5ae80 100644 --- engine.c +++ engine.c @@ -613,7 +613,7 @@ parse_dhcp(struct dhcpleased_iface *iface, struct imsg_dhcp *dhcp) uint32_t rebinding_time = 0; uint8_t *p, dho = DHO_PAD, dho_len; uint8_t dhcp_message_type = 0; - int routes_len = 0; + int routes_len = 0, routers = 0, csr = 0; char from[sizeof("xx:xx:xx:xx:xx:xx")]; char to[sizeof("xx:xx:xx:xx:xx:xx")]; char hbuf_src[INET_ADDRSTRLEN]; @@ -836,19 +836,28 @@ parse_dhcp(struct dhcpleased_iface *iface, struct imsg_dhcp *dhcp) if (dho_len % sizeof(routes[routes_len].gw) != 0) goto wrong_length; - while (routes_len < MAX_DHCP_ROUTES && dho_len > 0) { - memcpy(&routes[routes_len].gw, p, - sizeof(routes[routes_len].gw)); - if (log_getverbose() > 1) { - log_debug("DHO_ROUTER: %s", - inet_ntop(AF_INET, - &routes[routes_len].gw, hbuf, - sizeof(hbuf))); + /* + * Ignore routers option if classless static routes + * are present (RFC3442). + */ + if (!csr) { + routers = 1; + while (routes_len < MAX_DHCP_ROUTES && + dho_len > 0) { + memcpy(&routes[routes_len].gw, p, + sizeof(routes[routes_len].gw)); + if (log_getverbose() > 1) { + log_debug("DHO_ROUTER: %s", + inet_ntop(AF_INET, + &routes[routes_len].gw, + hbuf, sizeof(hbuf))); + } + p += sizeof(routes[routes_len].gw); + rem -= sizeof(routes[routes_len].gw); + dho_len -= + sizeof(routes[routes_len].gw); + routes_len++; } - p += sizeof(routes[routes_len].gw); - rem -= sizeof(routes[routes_len].gw); - dho_len -= sizeof(routes[routes_len].gw); - routes_len++; } if (dho_len != 0) { /* ignore > MAX_DHCP_ROUTES routes */ @@ -939,6 +948,15 @@ parse_dhcp(struct dhcpleased_iface *iface, struct imsg_dhcp *dhcp) case DHO_CLASSLESS_STATIC_ROUTES: { int prefixlen, compressed_prefixlen; + csr = 1; + if (routers) { + /* + * Ignore routers option if classless static + * routes are present (RFC3442). + */ + routers = 0; + routes_len = 0; + } while (routes_len < MAX_DHCP_ROUTES && dho_len > 0) { prefixlen = *p; p += 1; -- I'm not entirely sure you are real.