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.

Reply via email to