summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkrw <krw@openbsd.org>2013-02-28 21:00:53 +0000
committerkrw <krw@openbsd.org>2013-02-28 21:00:53 +0000
commitcfa6b83122298a465a777f63c4ac277467d6c51c (patch)
tree28a56ccdb85c9cf33e7a7be3880cfcd9793180c5
parentsets size updates; ok deraadt@ (diff)
downloadwireguard-openbsd-cfa6b83122298a465a777f63c4ac277467d6c51c.tar.xz
wireguard-openbsd-cfa6b83122298a465a777f63c4ac277467d6c51c.zip
Try 10 times to obtain the routing table via sysctl(), and if it
can't be done just abandon attempt to clean up the routing and arp tables and carry on. Code adapted from itojun's route6d.c. May address problem reported on misc@ by Marc Peters. Best we can do for now. ok claudio@
-rw-r--r--sbin/dhclient/kroute.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/sbin/dhclient/kroute.c b/sbin/dhclient/kroute.c
index 8737e010e29..9f636df340a 100644
--- a/sbin/dhclient/kroute.c
+++ b/sbin/dhclient/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.39 2013/02/24 01:23:19 krw Exp $ */
+/* $OpenBSD: kroute.c,v 1.40 2013/02/28 21:00:53 krw Exp $ */
/*
* Copyright 2012 Kenneth R Westerback <krw@openbsd.org>
@@ -66,14 +66,14 @@ priv_flush_routes_and_arp_cache(struct imsg_flush_routes *imsg)
struct sockaddr *rti_info[RTAX_MAX];
int mib[7];
size_t needed;
- char *lim, *buf, *next, *routelabel;
+ char *lim, *buf, *next, *routelabel, *errmsg;
struct rt_msghdr *rtm;
struct sockaddr *sa;
struct sockaddr_dl *sdl;
struct sockaddr_in *sa_in;
struct sockaddr_inarp *sin;
struct sockaddr_rtlabel *sa_rl;
- int s, seqno = 0, rlen, i;
+ int s, seqno = 0, rlen, retry, i;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
@@ -83,20 +83,33 @@ priv_flush_routes_and_arp_cache(struct imsg_flush_routes *imsg)
mib[5] = 0;
mib[6] = imsg->rdomain;
- if (sysctl(mib, 7, NULL, &needed, NULL, 0) == -1) {
- if (imsg->rdomain != 0 && errno == EINVAL)
+ buf = NULL;
+ retry = 0;
+ do {
+ retry++;
+ errmsg = NULL;
+ if (buf)
+ free(buf);
+ if (sysctl(mib, 7, NULL, &needed, NULL, 0) == -1) {
+ errmsg = "sysctl size of routes:";
+ continue;
+ }
+ if (needed == 0)
return;
- error("sysctl size of routes: %s", strerror(errno));
- }
+ if ((buf = malloc(needed)) == NULL) {
+ errmsg = "routes buf malloc:";
+ continue;
+ }
+ if (sysctl(mib, 7, buf, &needed, NULL, 0) == -1) {
+ errmsg = "sysctl retrieval of routes:";
+ }
+ } while (retry < 10 && errmsg != NULL);
- if (needed == 0)
+ if (errmsg) {
+ warning("route cleanup failed - %s %s (%d retries, msize=%zu)",
+ errmsg, strerror(errno), retry, needed);
return;
-
- if ((buf = malloc(needed)) == NULL)
- error("no memory for sysctl routes");
-
- if (sysctl(mib, 7, buf, &needed, NULL, 0) == -1)
- error("sysctl retrieval of routes: %s", strerror(errno));
+ }
if ((s = socket(AF_ROUTE, SOCK_RAW, 0)) == -1)
error("opening socket to flush routes: %s", strerror(errno));