diff options
-rw-r--r-- | nest/iface.c | 28 | ||||
-rw-r--r-- | nest/iface.h | 7 | ||||
-rw-r--r-- | sysdep/unix/sync-if.c | 22 |
3 files changed, 36 insertions, 21 deletions
diff --git a/nest/iface.c b/nest/iface.c index 86f0a8a1..4d1b6856 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -31,7 +31,7 @@ static list neigh_list; static int if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */ { - if (i->flags & (IF_ADMIN_DOWN | IF_IGNORE)) + if (!(i->flags & IF_UP)) return 0; if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->opposite)) return 1; @@ -41,8 +41,6 @@ if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */ ipa_equal(*a, i->brd) || /* Broadcast */ ipa_equal(*a, i->ip)) /* Our own address */ return -1; - if (!(i->flags & IF_UP)) - return 0; return 1; } @@ -197,6 +195,10 @@ if_dump(struct iface *i) debug(" ADMIN-DOWN"); if (i->flags & IF_UP) debug(" UP"); + else + debug(" DOWN"); + if (i->flags & IF_LINK_UP) + debug(" LINK-UP"); if (i->flags & IF_MULTIACCESS) debug(" MA"); if (i->flags & IF_UNNUMBERED) @@ -229,14 +231,16 @@ if_dump_all(void) static inline int if_change_too_big_p(struct iface *i, struct iface *j) { - if (!ipa_equal(i->ip, j->ip) || + if ((i->flags ^ j->flags) & IF_UP) /* Going up/down is always OK */ + return 0; + 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; /* Changed addresses */ - if ((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED)) 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; } @@ -295,6 +299,11 @@ if_update(struct iface *new) struct iface *i; 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)) { @@ -337,8 +346,9 @@ if_end_update(void) else { memcpy(&j, i, sizeof(struct iface)); - i->flags = (i->flags & ~IF_UP) | IF_ADMIN_DOWN; - if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, &j, i); + 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); } } @@ -362,7 +372,7 @@ 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_LOOPBACK | IF_IGNORE)) && + !(i->flags & (IF_UNNUMBERED | IF_IGNORE)) && (!j || ipa_to_u32(i->ip) < ipa_to_u32(j->ip))) j = i; if (!j) diff --git a/nest/iface.h b/nest/iface.h index 378cf3d1..fcad7187 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -21,7 +21,7 @@ struct iface { unsigned flags; unsigned mtu; unsigned index; /* OS-dependent interface index */ - ip_addr ip; /* IP address of this host */ + ip_addr ip; /* IP address of this host (0=unset) */ ip_addr prefix; /* Network prefix */ unsigned pxlen; /* Prefix length */ ip_addr brd; /* Broadcast address */ @@ -29,7 +29,7 @@ struct iface { struct neighbor *neigh; /* List of neighbors on this interface */ }; -#define IF_UP 1 +#define IF_UP 1 /* IF_LINK_UP, not IF_IGNORE and IP address known */ #define IF_MULTIACCESS 2 #define IF_UNNUMBERED 4 #define IF_BROADCAST 8 @@ -38,7 +38,8 @@ struct iface { #define IF_ADMIN_DOWN 64 #define IF_LOOPBACK 128 #define IF_IGNORE 256 -#define IF_UPDATED 0x1000 /* Touched in last scan */ +#define IF_LINK_UP 512 +#define IF_UPDATED 0x40000000 /* Touched in last scan */ /* Interface change events */ diff --git a/sysdep/unix/sync-if.c b/sysdep/unix/sync-if.c index 077cb94a..ce54fc77 100644 --- a/sysdep/unix/sync-if.c +++ b/sysdep/unix/sync-if.c @@ -42,16 +42,18 @@ scan_ifs(struct ifreq *r, int cnt) bzero(&i, sizeof(i)); DBG("%s\n", r->ifr_ifrn.ifrn_name); strncpy(i.name, r->ifr_ifrn.ifrn_name, sizeof(i.name) - 1); - i.name[sizeof(i.name) - 1] = 0; get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &i.ip, NULL); - l = ipa_classify(i.ip); - if (l < 0 || !(l & IADDR_HOST)) + if (ipa_nonzero(i.ip)) { - log(L_ERR "%s: Invalid interface address", i.name); - goto bad; + l = ipa_classify(i.ip); + if (l < 0 || !(l & IADDR_HOST)) + { + log(L_ERR "%s: Invalid interface address", i.name); + i.ip = IPA_NONE; + } + else if ((l & IADDR_SCOPE_MASK) == SCOPE_HOST) + i.flags |= IF_LOOPBACK | IF_IGNORE; } - if ((l & IADDR_SCOPE_MASK) == SCOPE_HOST) - i.flags |= IF_LOOPBACK | IF_IGNORE; if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0) { @@ -59,12 +61,12 @@ scan_ifs(struct ifreq *r, int cnt) faulty: log(L_ERR "%s(%s): %m", err, i.name); bad: - i.flags = (i.flags & ~IF_UP) | IF_ADMIN_DOWN; + i.flags = (i.flags & ~IF_LINK_UP) | IF_ADMIN_DOWN; continue; } fl = r->ifr_flags; if (fl & IFF_UP) - i.flags |= IF_UP; + i.flags |= IF_LINK_UP; if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0) { err = "SIOCGIFNETMASK"; goto faulty; } @@ -120,6 +122,8 @@ scan_ifs(struct ifreq *r, int cnt) DBG("SIOCGIFINDEX failed: %m\n"); else i.index = r->ifr_ifindex; +#else + /* FIXME: What else? Guess ifindex (we need it at least for OSPF on unnumbered links)? */ #endif if_update(&i); |