diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2013-02-28 21:00:54 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2013-02-28 21:00:54 +0000 |
commit | 847c6d482703c5b5a4f654d6e43b92bf5bb60117 (patch) | |
tree | e0400fbb1d6238a6790114871ba61386b521b803 /sbin/dhclient | |
parent | 43178276e8bb5a0f544ff3d34bb6c3cffea4c09b (diff) |
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@
Diffstat (limited to 'sbin/dhclient')
-rw-r--r-- | sbin/dhclient/kroute.c | 41 |
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)); |