]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Fixes problems with creating/removing/renaming ifaces on BSD.
authorOndrej Zajicek <santiago@crfreenet.org>
Mon, 23 Jan 2012 00:26:40 +0000 (01:26 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Mon, 23 Jan 2012 00:26:40 +0000 (01:26 +0100)
nest/iface.c
nest/iface.h
sysdep/bsd/krt-sock.c
sysdep/linux/netlink/netlink.c

index 2b14d3f05e505afe5ae51ee52c33bac802132910..d871ff335d261da344565a8d834afb2daf48a827 100644 (file)
@@ -252,6 +252,24 @@ if_change_flags(struct iface *i, unsigned flags)
     if_notify_change((i->flags & IF_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN, i);
 }
 
+/**
+ * if_delete - remove interface 
+ * @old: interface 
+ *
+ * This function is called by the low-level platform dependent code
+ * whenever it notices an interface disappears. It is just a shorthand
+ * for if_update().
+ */
+
+void
+if_delete(struct iface *old)
+{
+  struct iface f = {};
+  strncpy(f.name, old->name, sizeof(f.name)-1);
+  f.flags = IF_SHUTDOWN;
+  if_update(&f);
+}
+
 /**
  * if_update - update interface status
  * @new: new interface status
@@ -400,7 +418,7 @@ if_find_by_index(unsigned idx)
   struct iface *i;
 
   WALK_LIST(i, iface_list)
-    if (i->index == idx)
+    if (i->index == idx && !(i->flags & IF_SHUTDOWN))
       return i;
   return NULL;
 }
index d6d58ff9c96c19531c2d997659b478f47f9000ed..2416f82f598b0debbc9d6231420d66e3dd394ff1 100644 (file)
@@ -88,6 +88,7 @@ void ifa_dump(struct ifa *);
 void if_show(void);
 void if_show_summary(void);
 struct iface *if_update(struct iface *);
+void if_delete(struct iface *old);
 struct ifa *ifa_update(struct ifa *);
 void ifa_delete(struct ifa *);
 void if_start_update(void);
index 4a91e85af6dc048b002a4dcbcd0938d7391c7d88..f831327b9597d00a12c4fafdd4326bb1be34fc28 100644 (file)
@@ -416,8 +416,9 @@ krt_read_ifinfo(struct ks_msg *msg)
   void *body = (void *)(ifm + 1);
   struct sockaddr_dl *dl = NULL;
   unsigned int i;
-  struct iface *iface = NULL, f;
+  struct iface *iface = NULL, f = {};
   int fl = ifm->ifm_flags;
+  int nlen = 0;
 
   for (i = 1; i<=RTA_IFP; i <<= 1)
   {
@@ -432,31 +433,42 @@ krt_read_ifinfo(struct ks_msg *msg)
     }
   }
 
-  if(dl && (dl->sdl_family != AF_LINK))
+  if (dl && (dl->sdl_family != AF_LINK))
   {
     log("Ignoring strange IFINFO");
     return;
   }
 
-  iface = if_find_by_index(ifm->ifm_index);
+  if (dl)
+    nlen = MIN(sizeof(f.name)-1, dl->sdl_nlen);
+
+  /* Note that asynchronous IFINFO messages do not contain iface
+     name, so we have to found an existing iface by iface index */
 
-  if(!iface)
+  iface = if_find_by_index(ifm->ifm_index);
+  if (!iface)
   {
     /* New interface */
-    if(!dl) return;    /* No interface name, ignoring */
+    if (!dl)
+      return;  /* No interface name, ignoring */
 
-    bzero(&f, sizeof(f));
-    f.index = ifm->ifm_index;
-    memcpy(f.name, dl->sdl_data, MIN(sizeof(f.name)-1, dl->sdl_nlen));
-    DBG("New interface '%s' found", f.name);
+    memcpy(f.name, dl->sdl_data, nlen);
+    DBG("New interface '%s' found\n", f.name);
+  }
+  else if (dl && memcmp(iface->name, dl->sdl_data, nlen))
+  {
+    /* Interface renamed */
+    if_delete(iface);
+    memcpy(f.name, dl->sdl_data, nlen);
   }
   else
   {
-    memcpy(&f, iface, sizeof(struct iface));
+    /* Old interface */
+    memcpy(f.name, iface->name, sizeof(f.name));
   }
 
+  f.index = ifm->ifm_index;
   f.mtu = ifm->ifm_data.ifi_mtu;
-  f.flags = 0;
 
   if (fl & IFF_UP)
     f.flags |= IF_ADMIN_UP;
index cf8082311d33e7734f817036d29a69500c550626..17c369ea8dd42360bcb7027bb76994a788c4a080 100644 (file)
@@ -386,7 +386,7 @@ nl_parse_link(struct nlmsghdr *h, int scan)
   struct ifinfomsg *i;
   struct rtattr *a[IFLA_WIRELESS+1];
   int new = h->nlmsg_type == RTM_NEWLINK;
-  struct iface f;
+  struct iface f = {};
   struct iface *ifi;
   char *name;
   u32 mtu;
@@ -408,26 +408,21 @@ nl_parse_link(struct nlmsghdr *h, int scan)
   if (!new)
     {
       DBG("KIF: IF%d(%s) goes down\n", i->ifi_index, name);
-      if (ifi && !scan)
-       {
-         memcpy(&f, ifi, sizeof(struct iface));
-         f.flags |= IF_SHUTDOWN;
-         if_update(&f);
-       }
+      if (!ifi)
+       return;
+
+      if_delete(ifi);
     }
   else
     {
       DBG("KIF: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i->ifi_index, name, mtu, i->ifi_flags);
-      if (ifi)
-       memcpy(&f, ifi, sizeof(f));
-      else
-       {
-         bzero(&f, sizeof(f));
-         f.index = i->ifi_index;
-       }
-      strncpy(f.name, RTA_DATA(a[IFLA_IFNAME]), sizeof(f.name)-1);
+      if (ifi && strncmp(ifi->name, name, sizeof(ifi->name)-1))
+       if_delete(ifi);
+
+      strncpy(f.name, name, sizeof(f.name)-1);
+      f.index = i->ifi_index;
       f.mtu = mtu;
-      f.flags = 0;
+
       fl = i->ifi_flags;
       if (fl & IFF_UP)
        f.flags |= IF_ADMIN_UP;