diff options
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | nest/iface.c | 8 | ||||
-rw-r--r-- | sysdep/linux/netlink/netlink.c | 58 |
3 files changed, 33 insertions, 34 deletions
@@ -26,6 +26,7 @@ Core - iface: when seen an invalid broadcast, fix it up or at least report - iface: we always need ifindex at least for PtP links (OSPF) - iface: interface filters should support filtering by IP address as well +- iface: SIOCGIFINDEX exists on glibc systems, but it doesn't work on 2.0.x kernels! - socket: Use IP_RECVERR for BGP TCP sockets? diff --git a/nest/iface.c b/nest/iface.c index 069b740..19ed7fb 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -361,8 +361,9 @@ if_update(struct iface *new) DBG("Interface %s changed too much -- forcing down/up transition\n", i->name); if_change_flags(i, i->flags | IF_TMP_DOWN); rem_node(&i->n); - WALK_LIST_DELSAFE(a, b, i->addrs) - ifa_delete(a); + new->addr = i->addr; + memcpy(&new->addrs, &i->addrs, sizeof(i->addrs)); + memcpy(i, new, sizeof(*i)); goto newif; } else if (c) @@ -374,9 +375,9 @@ if_update(struct iface *new) return i; } i = mb_alloc(if_pool, sizeof(struct iface)); -newif: memcpy(i, new, sizeof(*i)); init_list(&i->addrs); +newif: i->flags |= IF_UPDATED | IF_TMP_DOWN; /* Tmp down as we don't have addresses yet */ add_tail(&iface_list, &i->n); return i; @@ -543,6 +544,7 @@ ifa_delete(struct ifa *a) ifa_recalc_primary(i); } mb_free(b); + return; } } diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c index 5a15607..10eb27a 100644 --- a/sysdep/linux/netlink/netlink.c +++ b/sysdep/linux/netlink/netlink.c @@ -316,7 +316,7 @@ nl_parse_addr(struct nlmsghdr *h) struct ifaddrmsg *i; struct rtattr *a[IFA_ANYCAST+1]; int new = h->nlmsg_type == RTM_NEWADDR; - struct iface f; + struct ifa ifa; struct iface *ifi; if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFA_RTA(i), a, sizeof(a))) @@ -330,11 +330,6 @@ nl_parse_addr(struct nlmsghdr *h) log(L_ERR "nl_parse_addr: Malformed message received"); return; } - if (i->ifa_flags & IFA_F_SECONDARY) - { - DBG("KIF: Received address message for secondary address which is not supported.\n"); /* FIXME */ - return; - } ifi = if_find_by_index(i->ifa_index); if (!ifi) @@ -342,41 +337,42 @@ nl_parse_addr(struct nlmsghdr *h) log(L_ERR "KIF: Received address message for unknown interface %d\n", i->ifa_index); return; } - memcpy(&f, ifi, sizeof(f)); if (i->ifa_prefixlen > 32 || i->ifa_prefixlen == 31 || - (f.flags & IF_UNNUMBERED) && i->ifa_prefixlen != 32) + (ifi->flags & IF_UNNUMBERED) && i->ifa_prefixlen != 32) { - log(L_ERR "KIF: Invalid prefix length for interface %s: %d\n", f.name, i->ifa_prefixlen); + log(L_ERR "KIF: Invalid prefix length for interface %s: %d\n", ifi->name, i->ifa_prefixlen); new = 0; } - f.ip = f.brd = f.opposite = IPA_NONE; - if (!new) + bzero(&ifa, sizeof(ifa)); + ifa.iface = ifi; + if (i->ifa_flags & IFA_F_SECONDARY) + ifa.flags |= IA_SECONDARY; + memcpy(&ifa.ip, RTA_DATA(a[IFA_LOCAL]), sizeof(ifa.ip)); + ifa.ip = ipa_ntoh(ifa.ip); + ifa.pxlen = i->ifa_prefixlen; + if (ifi->flags & IF_UNNUMBERED) { - DBG("KIF: IF%d IP address deleted\n"); - f.pxlen = 0; + memcpy(&ifa.opposite, RTA_DATA(a[IFA_ADDRESS]), sizeof(ifa.opposite)); + ifa.opposite = ifa.brd = ipa_ntoh(ifa.opposite); } - else + else if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST]) { - memcpy(&f.ip, RTA_DATA(a[IFA_LOCAL]), sizeof(f.ip)); - f.ip = ipa_ntoh(f.ip); - f.pxlen = i->ifa_prefixlen; - if (f.flags & IF_UNNUMBERED) - { - memcpy(&f.opposite, RTA_DATA(a[IFA_ADDRESS]), sizeof(f.opposite)); - f.opposite = f.brd = ipa_ntoh(f.opposite); - } - else if ((f.flags & IF_BROADCAST) && a[IFA_BROADCAST]) - { - memcpy(&f.brd, RTA_DATA(a[IFA_BROADCAST]), sizeof(f.brd)); - f.brd = ipa_ntoh(f.brd); - } - /* else a NBMA link */ - f.prefix = ipa_and(f.ip, ipa_mkmask(f.pxlen)); - DBG("KIF: IF%d IP address set to %I, net %I/%d, brd %I, opp %I\n", f.index, f.ip, f.prefix, f.pxlen, f.brd, f.opposite); + memcpy(&ifa.brd, RTA_DATA(a[IFA_BROADCAST]), sizeof(ifa.brd)); + ifa.brd = ipa_ntoh(ifa.brd); } - if_update(&f); + /* else a NBMA link */ + ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(ifa.pxlen)); + + DBG("KIF: IF%d(%s): %s IPA %I, net %I/%d, brd %I, opp %I\n", + ifi->index, ifi->name, + new ? "added" : "removed", + ifa.ip, ifa.prefix, ifa.pxlen, ifa.brd, ifa.opposite); + if (new) + ifa_update(&ifa); + else + ifa_delete(&ifa); } void |