From 09686693d35bd71187847c95c0967d4125215b97 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Mon, 23 Jan 2012 03:15:12 +0100 Subject: [PATCH] Implements handling of BSD iface arrival/departure notifications. Thanks to Alexander V. Chernikov for original patch. --- nest/iface.c | 1 + sysdep/bsd/krt-sock.c | 32 +++++++++++++++++++++++++++++++- sysdep/unix/krt.c | 7 +++++++ sysdep/unix/krt.h | 1 + 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/nest/iface.c b/nest/iface.c index d871ff33..eea3d3b1 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -306,6 +306,7 @@ if_update(struct iface *new) new->addr = i->addr; memcpy(&new->addrs, &i->addrs, sizeof(i->addrs)); memcpy(i, new, sizeof(*i)); + i->flags &= ~IF_UP; /* IF_TMP_DOWN will be added later */ goto newif; } diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index f831327b..4ee5495f 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -409,6 +409,33 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) krt_got_route_async(p, e, new); } +static void +krt_read_ifannounce(struct ks_msg *msg) +{ + struct if_announcemsghdr *ifam = (struct if_announcemsghdr *)&msg->rtm; + + if (ifam->ifan_what == IFAN_ARRIVAL) + { + /* Not enough info to create the iface, so we just trigger iface scan */ + kif_request_scan(); + } + else if (ifam->ifan_what == IFAN_DEPARTURE) + { + struct iface *iface = if_find_by_index(ifam->ifan_index); + + /* Interface is destroyed */ + if (!iface) + { + DBG("KRT: unknown interface (%s, #%d) going down. Ignoring\n", ifam->ifan_name, ifam->ifan_index); + return; + } + + if_delete(iface); + } + + DBG("KRT: IFANNOUNCE what: %d index %d name %s\n", ifam->ifan_what, ifam->ifan_index, ifam->ifan_name); +} + static void krt_read_ifinfo(struct ks_msg *msg) { @@ -435,7 +462,7 @@ krt_read_ifinfo(struct ks_msg *msg) if (dl && (dl->sdl_family != AF_LINK)) { - log("Ignoring strange IFINFO"); + log(L_WARN "Ignoring strange IFINFO"); return; } @@ -599,6 +626,9 @@ krt_read_msg(struct proto *p, struct ks_msg *msg, int scan) case RTM_DELETE: krt_read_rt(msg, (struct krt_proto *)p, scan); break; + case RTM_IFANNOUNCE: + krt_read_ifannounce(msg); + break; case RTM_IFINFO: krt_read_ifinfo(msg); break; diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index e5a8ce17..ad8ea6b6 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -104,6 +104,13 @@ kif_force_scan(void) } } +void +kif_request_scan(void) +{ + if (kif_proto && kif_scan_timer->expires > now) + tm_start(kif_scan_timer, 1); +} + static struct proto * kif_init(struct proto_config *c) { diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 7bb4fe70..b0c4dc5e 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -77,6 +77,7 @@ extern pool *krt_pool; if (pr->p.debug & fl) \ { log(L_TRACE "%s: " msg, pr->p.name , ## args); } } while(0) +void kif_request_scan(void); void krt_got_route(struct krt_proto *p, struct rte *e); void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);