From f7a6397be0051dce246f1caee908e873e0853633 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 20 Feb 2025 13:41:34 +0000 Subject: [PATCH] BSD: Loop when pulling routes into our buffer if no memory 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 | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/if-bsd.c b/src/if-bsd.c index 32b51ba7..9871d78b 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -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 -- 2.47.2