]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
I rewrote the interface handling code, so that it supports multiple
authorMartin Mares <mj@ucw.cz>
Thu, 6 May 1999 21:38:11 +0000 (21:38 +0000)
committerMartin Mares <mj@ucw.cz>
Thu, 6 May 1999 21:38:11 +0000 (21:38 +0000)
addresses per interface (needed for example for IPv6 support).

Visible changes:

o  struct iface now contains a list of all interface addresses (represented
   by struct ifa), iface->addr points to the primary address (if any).
o  Interface has IF_UP set iff it's up and it has a primary address.
o  IF_UP is now independent on IF_IGNORED (i.e., you need to test IF_IGNORED
   in the protocols; I've added this, but please check).
o  The if_notify_change hook has been simplified (only one interface pointer
   etc.).
o  Introduced a ifa_notify_change hook. (For now, only the Direct protocol
   does use it -- it's wise to just listen to device routes in all other
   protocols.)
o  Removed IF_CHANGE_FLAGS notifier flag (it was meaningless anyway).
o  Updated all the code except netlink (I'll look at it tomorrow) to match
   the new semantics (please look at your code to ensure I did it right).

Things to fix:

o  Netlink.
o  Make krt-iface interpret "eth0:1"-type aliases as secondary addresses.

TODO
nest/iface.c
nest/iface.h
nest/protocol.h
nest/rt-dev.c
proto/ospf/ospf.c
proto/rip/rip.c
proto/static/static.c
sysdep/linux/netlink/netlink.c
sysdep/unix/io.c
sysdep/unix/krt-iface.c

diff --git a/TODO b/TODO
index f001bd4b59ad1c112874f477af0c4668b0eae4aa..ce658851148cc0bc18ce505536791a2ebe6f8c41 100644 (file)
--- a/TODO
+++ b/TODO
@@ -27,6 +27,8 @@ Core
 - iface: we always need ifindex at least for PtP links (OSPF)
 - iface: interface filters should support filtering by IP address as well
 
+- socket: Use IP_RECVERR for BGP TCP sockets?
+
 Cleanup
 ~~~~~~~
 - right usage of DBG vs. debug
index 002646ba435b7c5ffd3d1c62f5fe0f21fa0b75db..069b740c9fabb85201af954c05eabf3adc5e5f29 100644 (file)
@@ -31,17 +31,22 @@ static list neigh_list;
 static int
 if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */
 {
+  struct ifa *b;
+
   if (!(i->flags & IF_UP))
     return 0;
-  if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->opposite))
+  if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->addr->opposite))
     return 1;
-  if (!ipa_in_net(*a, i->prefix, i->pxlen))
-    return 0;
-  if (ipa_equal(*a, i->prefix) ||      /* Network address */
-      ipa_equal(*a, i->brd) ||         /* Broadcast */
-      ipa_equal(*a, i->ip))            /* Our own address */
-    return -1;
-  return 1;
+  WALK_LIST(b, i->addrs)
+    if (ipa_in_net(*a, b->prefix, b->pxlen))
+      {
+       if (ipa_equal(*a, b->prefix) || /* Network address */
+           ipa_equal(*a, b->brd) ||    /* Broadcast */
+           ipa_equal(*a, b->ip))       /* Our own address */
+         return -1;
+       return 1;
+      }
+  return 0;
 }
 
 neighbor *
@@ -69,7 +74,7 @@ neigh_find(struct proto *p, ip_addr *a, unsigned flags)
       case -1:
        return NULL;
       case 1:
-       if (!j || j->pxlen > i->pxlen)
+       if (!j)                         /* FIXME: Search for _optimal_ iface route? */
          j = i;
        /* Fall-thru */
       }
@@ -187,9 +192,19 @@ neigh_prune(void)
 
 list iface_list;
 
+void
+ifa_dump(struct ifa *a)
+{
+  debug("\t%I, net %I/%-2d bc %I -> %I%s%s\n", a->ip, a->prefix, a->pxlen, a->brd, a->opposite,
+       (a->flags & IF_UP) ? "" : " DOWN",
+       (a->flags & IA_PRIMARY) ? "" : " SEC");
+}
+
 void
 if_dump(struct iface *i)
 {
+  struct ifa *a;
+
   debug("IF%d: %s", i->index, i->name);
   if (i->flags & IF_ADMIN_DOWN)
     debug(" ADMIN-DOWN");
@@ -213,8 +228,14 @@ if_dump(struct iface *i)
     debug(" LOOP");
   if (i->flags & IF_IGNORE)
     debug(" IGN");
+  if (i->flags & IF_TMP_DOWN)
+    debug(" TDOWN");
   debug(" MTU=%d\n", i->mtu);
-  debug("\t%I, net %I/%-2d bc %I -> %I\n", i->ip, i->prefix, i->pxlen, i->brd, i->opposite);
+  WALK_LIST(a, i->addrs)
+    {
+      ifa_dump(a);
+      ASSERT((a != i->addr) == !(a->flags & IA_PRIMARY));
+    }
 }
 
 void
@@ -228,151 +249,200 @@ if_dump_all(void)
   debug("Router ID: %08x\n", config->router_id);
 }
 
-static inline int
-if_change_too_big_p(struct iface *i, struct iface *j)
+static inline unsigned
+if_what_changed(struct iface *i, struct iface *j)
 {
-  if (!ipa_equal(i->ip, j->ip) ||      /* Address change isn't */
-      !ipa_equal(i->prefix, j->prefix) ||
-      i->pxlen != j->pxlen ||
-      !ipa_equal(i->brd, j->brd) ||
-      !ipa_equal(i->opposite, j->opposite))
-    return 1;
-  if ((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED | IF_LINK_UP))
-    return 1;                          /* Interface type change isn't as well */
-  return 0;
+  unsigned c;
+
+  if (((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED | IF_LINK_UP | IF_TMP_DOWN | IF_JUST_CREATED))
+      || i->index != j->index)
+    return IF_CHANGE_TOO_MUCH;
+  c = 0;
+  if ((i->flags ^ j->flags) & IF_UP)
+    c |= (i->flags & IF_UP) ? IF_CHANGE_DOWN : IF_CHANGE_UP;
+  if (i->mtu != j->mtu)
+    c |= IF_CHANGE_MTU;
+  return c;
 }
 
 static inline void
 if_copy(struct iface *to, struct iface *from)
 {
-  to->flags = from->flags;
+  to->flags = from->flags | (to->flags & IF_TMP_DOWN);
   to->mtu = from->mtu;
-  to->index = from->index;
-  to->neigh = from->neigh;
 }
 
-static unsigned
-if_changed(struct iface *i, struct iface *j)
+static void
+ifa_notify_change(unsigned c, struct ifa *a)
 {
-  unsigned f = 0;
+  struct proto *p;
 
-  if (i->mtu != j->mtu)
-    f |= IF_CHANGE_MTU;
-  if ((i->flags ^ j->flags) & ~IF_UPDATED)
-    {
-      f |= IF_CHANGE_FLAGS;
-      if ((i->flags ^ j->flags) & IF_UP)
-       if (i->flags & IF_UP)
-         f |= IF_CHANGE_DOWN;
-       else
-         f |= IF_CHANGE_UP;
-    }
-  return f;
+  debug("IFA change notification (%x) for %s:%I\n", c, a->iface->name, a->ip);
+  WALK_LIST(p, proto_list)
+    if (p->ifa_notify)
+      p->ifa_notify(p, c, a);
 }
 
 static void
-if_notify_change(unsigned c, struct iface *old, struct iface *new, struct iface *real)
+if_notify_change(unsigned c, struct iface *i)
 {
   struct proto *p;
+  struct ifa *a;
 
-  debug("Interface change notification (%x) for %s\n", c, new->name);
-  if (old)
-    if_dump(old);
-  if (new)
-    if_dump(new);
+  if (i->flags & IF_JUST_CREATED)
+    {
+      i->flags &= ~IF_JUST_CREATED;
+      c |= IF_CHANGE_CREATE | IF_CHANGE_MTU;
+    }
+
+  debug("Interface change notification (%x) for %s\n", c, i->name);
+  if_dump(i);
 
   if (c & IF_CHANGE_UP)
-    neigh_if_up(real);
+    neigh_if_up(i);
+  if (c & IF_CHANGE_DOWN)
+    WALK_LIST(a, i->addrs)
+      {
+       a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
+       ifa_notify_change(IF_CHANGE_DOWN, a);
+      }
 
   WALK_LIST(p, proto_list)
     if (p->if_notify)
-      p->if_notify(p, c, new, old);
+      p->if_notify(p, c, i);
 
+  if (c & IF_CHANGE_UP)
+    WALK_LIST(a, i->addrs)
+      {
+       a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
+       ifa_notify_change(IF_CHANGE_UP, a);
+      }
   if (c & IF_CHANGE_DOWN)
-    neigh_if_down(real);
+    neigh_if_down(i);
 }
 
-void
+static unsigned
+if_recalc_flags(struct iface *i, unsigned flags)
+{
+  if ((flags & (IF_ADMIN_DOWN | IF_TMP_DOWN)) ||
+      !(flags & IF_LINK_UP) ||
+      !i->addr)
+    flags &= ~IF_UP;
+  else
+    flags |= IF_UP;
+  return flags;
+}
+
+static void
+if_change_flags(struct iface *i, unsigned flags)
+{
+  unsigned of = i->flags;
+
+  i->flags = if_recalc_flags(i, flags);
+  if ((i->flags ^ of) & IF_UP)
+    if_notify_change((i->flags & IF_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN, i);
+}
+
+struct iface *
 if_update(struct iface *new)
 {
   struct iface *i;
+  struct ifa *a, *b;
   unsigned c;
 
-  if ((new->flags & IF_LINK_UP) && !(new->flags & IF_ADMIN_DOWN) && ipa_nonzero(new->ip))
-    new->flags |= IF_UP;
-  else
-    new->flags &= ~IF_UP;
-
   WALK_LIST(i, iface_list)
     if (!strcmp(new->name, i->name))
       {
-       if (if_change_too_big_p(i, new)) /* Changed a lot, convert it to down/up */
+       new->addr = i->addr;
+       new->flags = if_recalc_flags(new, new->flags);
+       c = if_what_changed(i, new);
+       if (c & IF_CHANGE_TOO_MUCH)     /* Changed a lot, convert it to down/up */
          {
            DBG("Interface %s changed too much -- forcing down/up transition\n", i->name);
-           if (i->flags & IF_UP)
-             {
-               struct iface j;
-               memcpy(&j, i, sizeof(struct iface));
-               i->flags &= ~IF_UP;
-               if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, &j, i, i);
-             }
+           if_change_flags(i, i->flags | IF_TMP_DOWN);
            rem_node(&i->n);
+           WALK_LIST_DELSAFE(a, b, i->addrs)
+             ifa_delete(a);
            goto newif;
          }
-       c = if_changed(i, new);
-       if (c)
-         if_notify_change(c, i, new, i);
-       if_copy(i, new);                /* Even if c==0 as we might need to update i->index et al. */
+       else if (c)
+         {
+           if_copy(i, new);
+           if_notify_change(c, i);
+         }
        i->flags |= IF_UPDATED;
-       return;
+       return i;
       }
-
   i = mb_alloc(if_pool, sizeof(struct iface));
 newif:
   memcpy(i, new, sizeof(*i));
-  i->flags |= IF_UPDATED;
+  init_list(&i->addrs);
+  i->flags |= IF_UPDATED | IF_TMP_DOWN;                /* Tmp down as we don't have addresses yet */
   add_tail(&iface_list, &i->n);
-  if_notify_change(IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0)
-                  | IF_CHANGE_FLAGS | IF_CHANGE_MTU, NULL, i, i);
+  return i;
 }
 
 void
 if_start_update(void)
 {
   struct iface *i;
+  struct ifa *a;
 
   WALK_LIST(i, iface_list)
-    i->flags &= ~IF_UPDATED;
+    {
+      i->flags &= ~IF_UPDATED;
+      WALK_LIST(a, i->addrs)
+       a->flags &= ~IF_UPDATED;
+    }
+}
+
+void
+if_end_partial_update(struct iface *i)
+{
+  if (i->flags & IF_TMP_DOWN)
+    if_change_flags(i, i->flags & ~IF_TMP_DOWN);
 }
 
 void
 if_end_update(void)
 {
   struct iface *i, j;
+  struct ifa *a, *b;
 
   if (!config->router_id)
     auto_router_id();
 
   WALK_LIST(i, iface_list)
-    if (!(i->flags & IF_UPDATED))
-      {
-       memcpy(&j, i, sizeof(struct iface));
-       i->flags = (i->flags & ~(IF_LINK_UP | IF_UP)) | IF_ADMIN_DOWN;
-       if (i->flags != j.flags)
-         if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, &j, i, i);
-      }
+    {
+      if (!(i->flags & IF_UPDATED))
+       if_change_flags(i, (i->flags & ~IF_LINK_UP) | IF_ADMIN_DOWN);
+      else
+       {
+         WALK_LIST_DELSAFE(a, b, i->addrs)
+           if (!(a->flags & IF_UPDATED))
+             ifa_delete(a);
+         if_end_partial_update(i);
+       }
+    }
 }
 
 void
 if_feed_baby(struct proto *p)
 {
   struct iface *i;
+  struct ifa *a;
 
-  if (!p->if_notify)
+  if (!p->if_notify && !p->ifa_notify)
     return;
   debug("Announcing interfaces to new protocol %s\n", p->name);
   WALK_LIST(i, iface_list)
-    p->if_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i, NULL);
+    {
+      if (p->if_notify)
+       p->if_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i);
+      if (p->ifa_notify && (i->flags & IF_UP))
+       WALK_LIST(a, i->addrs)
+         p->ifa_notify(p, IF_CHANGE_CREATE | IF_CHANGE_UP, a);
+    }
 }
 
 struct iface *
@@ -386,6 +456,96 @@ if_find_by_index(unsigned idx)
   return NULL;
 }
 
+struct iface *
+if_find_by_name(char *name)
+{
+  struct iface *i;
+
+  WALK_LIST(i, iface_list)
+    if (!strcmp(i->name, name))
+      return i;
+  return NULL;
+}
+
+static int
+ifa_recalc_primary(struct iface *i)
+{
+  struct ifa *a, *b = NULL;
+  int res;
+
+  WALK_LIST(a, i->addrs)
+    {
+      if (!(a->flags & IA_SECONDARY) && (!b || a->scope > b->scope))
+       b = a;
+      a->flags &= ~IA_PRIMARY;
+    }
+  res = (b != i->addr);
+  i->addr = b;
+  if (b)
+    {
+      b->flags |= IA_PRIMARY;
+      rem_node(&b->n);
+      add_head(&i->addrs, &b->n);
+    }
+  return res;
+}
+
+struct ifa *
+ifa_update(struct ifa *a)
+{
+  struct iface *i = a->iface;
+  struct ifa *b;
+
+  WALK_LIST(b, i->addrs)
+    if (ipa_equal(b->ip, a->ip))
+      {
+       if (ipa_equal(b->prefix, a->prefix) &&
+           b->pxlen == a->pxlen &&
+           ipa_equal(b->brd, a->brd) &&
+           ipa_equal(b->opposite, a->opposite) &&
+           b->scope == a->scope)
+         {
+           b->flags |= IF_UPDATED;
+           return b;
+         }
+       ifa_delete(b);
+       break;
+      }
+  b = mb_alloc(if_pool, sizeof(struct ifa));
+  memcpy(b, a, sizeof(struct ifa));
+  add_tail(&i->addrs, &b->n);
+  b->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
+  if ((!i->addr || i->addr->scope < b->scope) && ifa_recalc_primary(i))
+    if_change_flags(i, i->flags | IF_TMP_DOWN);
+  if (b->flags & IF_UP)
+    ifa_notify_change(IF_CHANGE_CREATE | IF_CHANGE_UP, b);
+  return b;
+}
+
+void
+ifa_delete(struct ifa *a)
+{
+  struct iface *i = a->iface;
+  struct ifa *b;
+
+  WALK_LIST(b, i->addrs)
+    if (ipa_equal(b->ip, a->ip))
+      {
+       rem_node(&b->n);
+       if (b->flags & IF_UP)
+         {
+           b->flags &= ~IF_UP;
+           ifa_notify_change(IF_CHANGE_DOWN, b);
+         }
+       if (b->flags & IA_PRIMARY)
+         {
+           if_change_flags(i, i->flags | IF_TMP_DOWN);
+           ifa_recalc_primary(i);
+         }
+       mb_free(b);
+      }
+}
+
 static void
 auto_router_id(void)                   /* FIXME: What if we run IPv6??? */
 {
@@ -393,14 +553,15 @@ auto_router_id(void)                      /* FIXME: What if we run IPv6??? */
 
   j = NULL;
   WALK_LIST(i, iface_list)
-    if ((i->flags & IF_UP) &&
-       !(i->flags & (IF_UNNUMBERED | IF_IGNORE)) &&
-       (!j || ipa_to_u32(i->ip) < ipa_to_u32(j->ip)))
+    if ((i->flags & IF_LINK_UP) &&
+       !(i->flags & (IF_UNNUMBERED | IF_IGNORE | IF_ADMIN_DOWN)) &&
+       i->addr &&
+       (!j || ipa_to_u32(i->addr->ip) < ipa_to_u32(j->addr->ip)))
       j = i;
   if (!j)
     die("Cannot determine router ID (no suitable network interface found), please configure it manually");
-  debug("Guessed router ID %I (%s)\n", j->ip, j->name);
-  config->router_id = ipa_to_u32(j->ip);
+  debug("Guessed router ID %I (%s)\n", j->addr->ip, j->name);
+  config->router_id = ipa_to_u32(j->addr->ip);
 }
 
 void
index 8677be0d8b5c9b92367360a7ae5872f334416adc..1d26e7b8f16fc4cbb2f1b778be1dabbc63d75866 100644 (file)
@@ -15,48 +15,69 @@ extern list iface_list;
 
 struct proto;
 
+struct ifa {                           /* Interface address */
+  node n;
+  struct iface *iface;                 /* Interface this address belongs to */
+  ip_addr ip;                          /* IP address of this host */
+  ip_addr prefix;                      /* Network prefix */
+  unsigned pxlen;                      /* Prefix length */
+  ip_addr brd;                         /* Broadcast address */
+  ip_addr opposite;                    /* Opposite end of a point-to-point link */
+  unsigned scope;                      /* Interface address scope */
+  unsigned flags;                      /* Analogous to iface->flags */
+};
+
 struct iface {
   node n;
   char name[16];
   unsigned flags;
   unsigned mtu;
   unsigned index;                      /* OS-dependent interface index */
-  ip_addr ip;                          /* IP address of this host (0=unset) */
-  ip_addr prefix;                      /* Network prefix */
-  unsigned pxlen;                      /* Prefix length */
-  ip_addr brd;                         /* Broadcast address */
-  ip_addr opposite;                    /* Opposite end of a point-to-point link */
+  list addrs;                          /* Addresses assigned to this interface */
+  struct ifa *addr;                    /* Primary address */
   struct neighbor *neigh;              /* List of neighbors on this interface */
 };
 
-#define IF_UP 1                                /* IF_LINK_UP, not IF_IGNORE and IP address known */
+#define IF_UP 1                                /* IF_LINK_UP and IP address known */
 #define IF_MULTIACCESS 2
 #define IF_UNNUMBERED 4
 #define IF_BROADCAST 8
-#define IF_MULTICAST 16
-#define IF_TUNNEL 32
-#define IF_ADMIN_DOWN 64
-#define IF_LOOPBACK 128
-#define IF_IGNORE 256
-#define IF_LINK_UP 512
+#define IF_MULTICAST 0x10
+#define IF_TUNNEL 0x20
+#define IF_ADMIN_DOWN 0x40
+#define IF_LOOPBACK 0x80
+#define IF_IGNORE 0x100                        /* Not to be used by routing protocols (loopbacks etc.) */
+#define IF_LINK_UP 0x200
+
+#define IA_PRIMARY 0x10000             /* This address is primary */
+#define IA_SECONDARY 0x20000           /* This address has been reported as secondary by the kernel */
+#define IA_FLAGS 0xff0000
+
+#define IF_JUST_CREATED 0x10000000     /* Send creation event as soon as possible */
+#define IF_TMP_DOWN 0x20000000         /* Temporary shutdown due to interface reconfiguration */
 #define IF_UPDATED 0x40000000          /* Touched in last scan */
 
 /* Interface change events */
 
 #define IF_CHANGE_UP 1
 #define IF_CHANGE_DOWN 2
-#define IF_CHANGE_FLAGS 4              /* Can be converted to down/up internally */
-#define IF_CHANGE_MTU 8
-#define IF_CHANGE_CREATE 16            /* Seen this interface for the first time */
+#define IF_CHANGE_MTU 4
+#define IF_CHANGE_CREATE 8             /* Seen this interface for the first time */
+#define IF_CHANGE_TOO_MUCH 0x40000000  /* Used internally */
 
 void if_init(void);
 void if_dump(struct iface *);
 void if_dump_all(void);
-void if_update(struct iface *);
+void ifa_dump(struct ifa *);
+struct iface *if_update(struct iface *);
+struct ifa *ifa_update(struct ifa *);
+void ifa_delete(struct ifa *);
 void if_start_update(void);
 void if_end_update(void);
+void if_end_partial_update(struct iface *);
 void if_feed_baby(struct proto *);
 struct iface *if_find_by_index(unsigned);
+struct iface *if_find_by_name(char *);
 
 /*
  *     Neighbor Cache. We hold (direct neighbor, protocol) pairs we've seen
index c203f2529a66a1cf35adafabb9e620f9e08f527e..5e1e2ce9bf760db29313967fcfb53ae047b34d01 100644 (file)
@@ -13,6 +13,7 @@
 #include "lib/resource.h"
 
 struct iface;
+struct ifa;
 struct rte;
 struct neighbor;
 struct rta;
@@ -96,6 +97,7 @@ struct proto {
    *   General protocol hooks:
    *
    *      if_notify    Notify protocol about interface state changes.
+   *      ifa_notify   Notify protocol about interface address changes.
    *      rt_notify    Notify protocol about routing table updates.
    *      neigh_notify Notify protocol about neighbor cache events.
    *      make_tmp_attrs  Construct ea_list from private attrs stored in rte.
@@ -106,7 +108,8 @@ struct proto {
    *                   0=process it through the import filter set by the user.
    */
 
-  void (*if_notify)(struct proto *, unsigned flags, struct iface *new, struct iface *old);
+  void (*if_notify)(struct proto *, unsigned flags, struct iface *i);
+  void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a);
   void (*rt_notify)(struct proto *, struct network *net, struct rte *new, struct rte *old);
   void (*neigh_notify)(struct neighbor *neigh);
   struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool);
index d6035f566d8a2b591905e6856febe7366545e6ae..1225f1d7203c1d5d4cd9eeb18107c38f3ba9f109 100644 (file)
 #include "lib/resource.h"
 
 static void
-dev_if_notify(struct proto *p, unsigned c, struct iface *new, struct iface *old)
+dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
 {
   struct rt_dev_config *P = (void *) p->cf;
 
-  if (old && !iface_patt_match(&P->iface_list, old) ||
-      new && !iface_patt_match(&P->iface_list, new))
+  if (!iface_patt_match(&P->iface_list, ad->iface))
     return;
   if (c & IF_CHANGE_DOWN)
     {
       net *n;
 
-      debug("dev_if_notify: %s going down\n", old->name);
-      n = net_find(p->table, old->prefix, old->pxlen);
+      DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip);
+      n = net_find(p->table, ad->prefix, ad->pxlen);
       if (!n)
        {
          debug("dev_if_notify: device shutdown: prefix not found\n");
@@ -45,20 +44,20 @@ dev_if_notify(struct proto *p, unsigned c, struct iface *new, struct iface *old)
       net *n;
       rte *e;
 
-      debug("dev_if_notify: %s going up\n", new->name);
+      debug("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);
       bzero(&A, sizeof(A));
       A.proto = p;
       A.source = RTS_DEVICE;
-      A.scope = (new->flags & IF_LOOPBACK) ? SCOPE_HOST : SCOPE_UNIVERSE;
+      A.scope = ad->scope;
       A.cast = RTC_UNICAST;
       A.dest = RTD_DEVICE;
-      A.iface = new;
+      A.iface = ad->iface;
       A.attrs = NULL;
       a = rta_lookup(&A);
-      if (new->flags & IF_UNNUMBERED)
-       n = net_get(p->table, new->opposite, new->pxlen);
+      if (ad->flags & IF_UNNUMBERED)
+       n = net_get(p->table, ad->opposite, ad->pxlen);
       else
-       n = net_get(p->table, new->prefix, new->pxlen);
+       n = net_get(p->table, ad->prefix, ad->pxlen);
       e = rte_get_temp(a);
       e->net = n;
       e->pflags = 0;
@@ -71,7 +70,7 @@ dev_init(struct proto_config *c)
 {
   struct proto *p = proto_new(c, sizeof(struct proto));
 
-  p->if_notify = dev_if_notify;
+  p->ifa_notify = dev_ifa_notify;
   return p;
 }
 
index 6aedb2ae28d5d213e83243660216c6488c2dfb91..486ddbfa01e02369e940dfc67ddc7b934a7068fe 100644 (file)
@@ -155,7 +155,7 @@ wait_timer_hook(timer *timer)
     {
       debug(" OSPF: Changing state into DR.\n");
       ifa->state=OSPF_IS_DR;
-      ifa->drip=ifa->iface->ip;
+      ifa->drip=ifa->iface->addr->ip;
       /* FIXME: Set ifa->drid */
     }
     else
@@ -221,7 +221,7 @@ find_iface(struct proto_ospf *p, struct iface *what)
 }
 
 void
-ospf_if_notify(struct proto *p, unsigned flags, struct iface *new, struct iface *old)
+ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
 {
   struct ospf_iface *ifa;
   sock *mcsk, *newsk;
@@ -231,13 +231,15 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *new, struct iface
   c=(struct ospf_config *)(p->cf);
 
   DBG(" OSPF: If notify called\n");
+  if (iface->flags & IF_IGNORE)
+    return;
 
-  if((flags & IF_CHANGE_UP) && is_good_iface(p, new))
+  if((flags & IF_CHANGE_UP) && is_good_iface(p, iface))
   {
-    debug(" OSPF: using interface %s.\n", new->name);
+    debug(" OSPF: using interface %s.\n", iface->name);
     /* FIXME: Latter I'll use config - this is incorrect */
     ifa=mb_alloc(p->pool, sizeof(struct ospf_iface));
-    ifa->iface=new;
+    ifa->iface=iface;
     add_tail(&((struct proto_ospf *)p)->iface_list, NODE ifa);
     ospf_iface_default(ifa);
     /* FIXME: This should read config */
@@ -253,17 +255,17 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *new, struct iface
 
   if(flags & IF_CHANGE_DOWN)
   {
-    if((ifa=find_iface((struct proto_ospf *)p, old))!=NULL)
+    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
     {
-      debug(" OSPF: killing interface %s.\n", old->name);
+      debug(" OSPF: killing interface %s.\n", iface->name);
     }
   }
 
   if(flags & IF_CHANGE_MTU)
   {
-    if((ifa=find_iface((struct proto_ospf *)p, old))!=NULL)
+    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
     {
-      debug(" OSPF: changing MTU on interface %s.\n", old->name);
+      debug(" OSPF: changing MTU on interface %s.\n", iface->name);
     }
   }
 }
@@ -321,6 +323,4 @@ struct protocol proto_ospf = {
   start:       ospf_start,
   preconfig:   ospf_preconfig,
   postconfig:  ospf_postconfig,
-
 };
-
index 24d2e82baf72c128a6d81c57bfa41c18ce7a14ef..f7978ce2496c81f45f017ecc0301482c7f57daac 100644 (file)
@@ -491,9 +491,9 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags)
   if (want_multicast)
     rif->sock->daddr = ipa_from_u32(0x7f000001); /* FIXME: must lookup address in rfc's */
   if (flags & IF_BROADCAST)
-    rif->sock->daddr = new->brd;
+    rif->sock->daddr = new->addr->brd;
   if (flags & IF_UNNUMBERED)
-    rif->sock->daddr = new->opposite;
+    rif->sock->daddr = new->addr->opposite;
 
   if (!ipa_nonzero(rif->sock->daddr))
     log( L_WARN "RIP: interface %s is too strange for me", rif->iface ? rif->iface->name : "(dummy)" );
@@ -507,24 +507,26 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags)
 }
 
 static void
-rip_if_notify(struct proto *p, unsigned c, struct iface *new, struct iface *old)
+rip_if_notify(struct proto *p, unsigned c, struct iface *iface)
 {
   DBG( "RIP: if notify\n" );
-  if (old) {
+  if (iface->flags & IF_IGNORE)
+    return;
+  if (c & IF_CHANGE_DOWN) {
     struct rip_interface *i;
-    i = find_interface(p, old);
+    i = find_interface(p, iface);
     if (i) {
       rem_node(NODE i);
       kill_iface(p, i);
     }
   }
-  if (new) {
+  if (c & IF_CHANGE_UP) {
     struct rip_interface *rif;
-    struct iface_patt *k = iface_patt_match(&P_CF->iface_list, new);
+    struct iface_patt *k = iface_patt_match(&P_CF->iface_list, iface);
 
     if (!k) return; /* We are not interested in this interface */
-    DBG("adding interface %s\n", new->name );
-    rif = new_iface(p, new, new->flags);
+    DBG("adding interface %s\n", iface->name );
+    rif = new_iface(p, iface, iface->flags);
     rif->patt = (void *) k;
     add_head( &P->interfaces, NODE rif );
   }
index 871438a6e44252150741f81509e435c813077a88..b136b3143d8f6ab6ed4df4d89dec5f843e6edb8b 100644 (file)
@@ -134,7 +134,7 @@ static_dump(struct proto *p)
 }
 
 static void
-static_if_notify(struct proto *p, unsigned flags, struct iface *new, struct iface *old)
+static_if_notify(struct proto *p, unsigned flags, struct iface *i)
 {
   struct static_route *r;
   struct static_config *c = (void *) p->cf;
@@ -142,13 +142,13 @@ static_if_notify(struct proto *p, unsigned flags, struct iface *new, struct ifac
   if (flags & IF_CHANGE_UP)
     {
       WALK_LIST(r, c->iface_routes)
-       if (!strcmp(r->if_name, new->name))
-         static_install(p, r, new);
+       if (!strcmp(r->if_name, i->name))
+         static_install(p, r, i);
     }
   else if (flags & IF_CHANGE_DOWN)
     {
       WALK_LIST(r, c->iface_routes)
-       if (!strcmp(r->if_name, old->name))
+       if (!strcmp(r->if_name, i->name))
          static_remove(p, r);
     }
 }
index 31dd608de0638d3040bbc413dbc8c916534041be..5a15607a1ecfe17bdf7b9b4a7a54ab4f100a1558 100644 (file)
@@ -407,12 +407,16 @@ krt_if_scan(struct kif_proto *p)
  *     Routes
  */
 
-int                                    /* FIXME: Check use of this function in krt.c */
+int
 krt_capable(rte *e)
 {
   rta *a = e->attrs;
 
-  if (a->cast != RTC_UNICAST)  /* FIXME: For IPv6, we might support anycasts as well */
+  if (a->cast != RTC_UNICAST
+#ifdef IPV6
+      && a->cast != RTC_ANYCAST
+#endif
+      )
     return 0;
   if (a->source == RTS_DEVICE) /* Kernel takes care of device routes itself */
     return 0;
@@ -597,7 +601,7 @@ nl_parse_route(struct krt_proto *p, struct nlmsghdr *h, int scan)
   net = net_get(&master_table, dst, i->rtm_dst_len);
   ra.proto = &p->p;
   ra.source = RTS_INHERIT;
-  ra.scope = SCOPE_UNIVERSE;   /* FIXME: Use kernel scope? */
+  ra.scope = SCOPE_UNIVERSE;
   ra.cast = RTC_UNICAST;
   ra.flags = ra.aflags = 0;
   ra.from = IPA_NONE;
index 7764d3dfee29dd68a29534b060b286336b6e0107..6d44f809619e43bf516ab6d173500fabd086ec05 100644 (file)
@@ -414,14 +414,14 @@ sk_open(sock *s)
 #ifdef HAVE_STRUCT_IP_MREQN
        struct ip_mreqn mreq;
 #define mreq_add mreq
-       ASSERT(s->iface);
+       ASSERT(s->iface && s->iface->addr);
        mreq.imr_ifindex = s->iface->index;
-       set_inaddr(&mreq.imr_address, s->iface->ip);
+       set_inaddr(&mreq.imr_address, s->iface->addr->ip);
 #else
        struct in_addr mreq;
        struct ip_mreq mreq_add;
-       ASSERT(s->iface);
-       set_inaddr(&mreq, s->iface->ip);
+       ASSERT(s->iface && s->iface->addr);
+       set_inaddr(&mreq, s->iface->addr->ip);
 #ifdef SO_BINDTODEVICE
        {
          struct ifreq ifr;
index bca70cca0f542fa93fbd0328e5a1bf2023f2d36d..57692ebc9f1e6f537730b22ed381de82fa1bfa13 100644 (file)
@@ -30,7 +30,8 @@ int if_scan_sock = -1;
 static void
 scan_ifs(struct ifreq *r, int cnt)
 {
-  struct iface i;
+  struct iface i, *pi;
+  struct ifa a;
   char *err;
   unsigned fl;
   ip_addr netmask;
@@ -40,6 +41,7 @@ scan_ifs(struct ifreq *r, int cnt)
   for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
     {
       bzero(&i, sizeof(i));
+      bzero(&a, sizeof(a));
       DBG("%s\n", r->ifr_name);
       if (strchr(r->ifr_name, ':'))
        {
@@ -48,17 +50,21 @@ scan_ifs(struct ifreq *r, int cnt)
          continue;
        }
       strncpy(i.name, r->ifr_name, sizeof(i.name) - 1);
-      get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &i.ip, NULL);
-      if (ipa_nonzero(i.ip))
+      get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.ip, NULL);
+      if (ipa_nonzero(a.ip))
        {
-         l = ipa_classify(i.ip);
+         l = ipa_classify(a.ip);
          if (l < 0 || !(l & IADDR_HOST))
            {
              log(L_ERR "%s: Invalid interface address", i.name);
-             i.ip = IPA_NONE;
+             a.ip = IPA_NONE;
+           }
+         else
+           {
+             a.scope = l & IADDR_SCOPE_MASK;
+             if (a.scope == SCOPE_HOST)
+               i.flags |= IF_LOOPBACK | IF_IGNORE;
            }
-         else if ((l & IADDR_SCOPE_MASK) == SCOPE_HOST)
-           i.flags |= IF_LOOPBACK | IF_IGNORE;
        }
 
       if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0)
@@ -83,15 +89,15 @@ scan_ifs(struct ifreq *r, int cnt)
          log(L_ERR "%s: Invalid netmask", i.name);
          goto bad;
        }
-      i.pxlen = l;
+      a.pxlen = l;
 
       if (fl & IFF_POINTOPOINT)
        {
          i.flags |= IF_UNNUMBERED;
-         i.pxlen = BITS_PER_IP_ADDRESS;
+         a.pxlen = BITS_PER_IP_ADDRESS;
          if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
            { err = "SIOCGIFDSTADDR"; goto faulty; }
-         get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &i.opposite, NULL);
+         get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL);
        }
       if (fl & IFF_LOOPBACK)
        i.flags |= IF_LOOPBACK | IF_IGNORE;
@@ -100,24 +106,24 @@ scan_ifs(struct ifreq *r, int cnt)
 #endif
        i.flags |= IF_MULTICAST;
 
-      i.prefix = ipa_and(i.ip, ipa_mkmask(i.pxlen));
-      if (i.pxlen < 32)
+      a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen));
+      if (a.pxlen < 32)
        {
-         i.brd = ipa_or(i.prefix, ipa_not(ipa_mkmask(i.pxlen)));
-         if (ipa_equal(i.ip, i.prefix) || ipa_equal(i.ip, i.brd))
+         a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen)));
+         if (ipa_equal(a.ip, a.prefix) || ipa_equal(a.ip, a.brd))
            {
              log(L_ERR "%s: Using network or broadcast address for interface", i.name);
              goto bad;
            }
          if (fl & IFF_BROADCAST)
            i.flags |= IF_BROADCAST;
-         if (i.pxlen < 30)
+         if (a.pxlen < 30)
            i.flags |= IF_MULTIACCESS;
          else
-           i.opposite = ipa_opposite(i.ip);
+           a.opposite = ipa_opposite(a.ip);
        }
       else
-       i.brd = i.opposite;
+       a.brd = a.opposite;
 
       if (ioctl(if_scan_sock, SIOCGIFMTU, r) < 0)
        { err = "SIOCGIFMTU"; goto faulty; }
@@ -132,7 +138,9 @@ scan_ifs(struct ifreq *r, int cnt)
       /* FIXME: What else? Guess ifindex (we need it at least for OSPF on unnumbered links)? */
 #endif
 
-      if_update(&i);
+      pi = if_update(&i);
+      a.iface = pi;
+      ifa_update(&a);
     }
   if_end_update();
 }