summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2013-02-28 21:00:54 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2013-02-28 21:00:54 +0000
commit847c6d482703c5b5a4f654d6e43b92bf5bb60117 (patch)
treee0400fbb1d6238a6790114871ba61386b521b803
parent43178276e8bb5a0f544ff3d34bb6c3cffea4c09b (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@
-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));