]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
BSD: Loop when pulling routes into our buffer if no memory
authorRoy Marples <roy@marples.name>
Thu, 20 Feb 2025 13:41:34 +0000 (13:41 +0000)
committerRoy Marples <roy@marples.name>
Thu, 20 Feb 2025 13:41:34 +0000 (13:41 +0000)
We need to make two sysctls to pull the route table from the kernel.
The first one works out the size of the buffer required and the
second one populates it.
It's possible for more routes to be added between these two calls
causing the second call to fail with ENOMEM.
If this happens, just re-query the size needed and try again.

Fixes #466.

src/if-bsd.c

index 32b51ba758d92b2c14956f4fd9281afcc80f9811..9871d78bb4d0a61b8bcad58eeb538daa6d7cb113 100644 (file)
@@ -965,19 +965,24 @@ if_initrt(struct dhcpcd_ctx *ctx, rb_tree_t *kroutes, int af)
        struct rt_msghdr *rtm;
        int mib[6] = { CTL_NET, PF_ROUTE, 0, af, NET_RT_DUMP, 0 };
        size_t bufl;
-       char *buf, *p, *end;
+       char *buf = NULL, *p, *end;
        struct rt rt, *rtn;
 
+again:
        if (if_sysctl(ctx, mib, __arraycount(mib), NULL, &bufl, NULL, 0) == -1)
-               return -1;
-       if (bufl == 0)
+               goto err;
+       if (bufl == 0) {
+               free(buf);
                return 0;
-       if ((buf = malloc(bufl)) == NULL)
-               return -1;
+       }
+       if ((p = realloc(buf, bufl)) == NULL)
+               goto err;
+       buf = p;
        if (if_sysctl(ctx, mib, __arraycount(mib), buf, &bufl, NULL, 0) == -1)
        {
-               free(buf);
-               return -1;
+               if (errno == ENOMEM)
+                       goto again;
+               goto err;
        }
 
        end = buf + bufl;
@@ -1001,6 +1006,10 @@ if_initrt(struct dhcpcd_ctx *ctx, rb_tree_t *kroutes, int af)
        }
        free(buf);
        return p == end ? 0 : -1;
+
+err:
+       free(buf);
+       return -1;
 }
 
 #ifdef INET