On 2021-07-18 01:02 +02, Bjorn Ketelaars <[email protected]> wrote:
> On Sat 17/07/2021 17:12, Florian Obser wrote:
>>
>>
>> On 17 July 2021 13:16:59 CEST, Bjorn Ketelaars <[email protected]> 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.