summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2011-04-07 11:31:56 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2011-04-07 11:42:13 +0200
commit4aef102be1e29d3450e53a20a6b2f96d50527139 (patch)
treef10dac200be3b6dce21829a3d21ac0d9941584da
parent489c308a75b121f286cc8637ead8b2bf7bf896ec (diff)
downloadbird-4aef102be1e29d3450e53a20a6b2f96d50527139.tar
bird-4aef102be1e29d3450e53a20a6b2f96d50527139.zip
Fixes KRT sync in BSD.
When buffer is too small (because of change between sysctls()), needed is *not* changed.
-rw-r--r--sysdep/bsd/krt-sock.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c
index a4df52e..81f0013 100644
--- a/sysdep/bsd/krt-sock.c
+++ b/sysdep/bsd/krt-sock.c
@@ -620,9 +620,10 @@ static void
krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
{
byte *next;
- int mib[6], on;
+ int mib[6];
size_t obl, needed;
struct ks_msg *m;
+ int retries = 3;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
@@ -631,10 +632,9 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
mib[4] = cmd;
mib[5] = 0;
+ try:
if (sysctl(mib, 6 , NULL , &needed, NULL, 0) < 0)
- {
- die("RT scan...");
- }
+ die("krt_sysctl_scan 1: %m");
obl = *bl;
@@ -647,12 +647,18 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
if ((*buf = mb_alloc(pool, *bl)) == NULL) die("RT scan buf alloc");
}
- on = needed;
-
if (sysctl(mib, 6 , *buf, &needed, NULL, 0) < 0)
{
- if (on != needed) return; /* The buffer size changed since last sysctl */
- die("RT scan 2");
+ if (errno == ENOMEM)
+ {
+ /* The buffer size changed since last sysctl ('needed' is not changed) */
+ if (retries--)
+ goto try;
+
+ log(L_ERR "KRT: Route scan failed");
+ return;
+ }
+ die("krt_sysctl_scan 2: %m");
}
for (next = *buf; next < (*buf + needed); next += m->rtm.rtm_msglen)