Interface logic changes:
o Introduced IF_LINK_UP flag corresponding to real link state. o Allowed addressless interfaces. o IF_UP is now automatically calculated and set iff the interface is administratively up, has link up and has an IP address assigned. It may be IF_IGNORED, though (as in case of the loopback). o Any changes which include up/down transition are considered small enough to not provoke artificial upping and downing of the interface. o When an interface disappears (i.e., it wasn't seen in the last scan), we announce this change only once. o IF_LOOPBACK implies IF_IGNORE.
This commit is contained in:
parent
25287d6f7e
commit
bcbd8cc3be
3 changed files with 36 additions and 21 deletions
28
nest/iface.c
28
nest/iface.c
|
@ -31,7 +31,7 @@ static list neigh_list;
|
||||||
static int
|
static int
|
||||||
if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */
|
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;
|
return 0;
|
||||||
if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->opposite))
|
if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->opposite))
|
||||||
return 1;
|
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->brd) || /* Broadcast */
|
||||||
ipa_equal(*a, i->ip)) /* Our own address */
|
ipa_equal(*a, i->ip)) /* Our own address */
|
||||||
return -1;
|
return -1;
|
||||||
if (!(i->flags & IF_UP))
|
|
||||||
return 0;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +195,10 @@ if_dump(struct iface *i)
|
||||||
debug(" ADMIN-DOWN");
|
debug(" ADMIN-DOWN");
|
||||||
if (i->flags & IF_UP)
|
if (i->flags & IF_UP)
|
||||||
debug(" UP");
|
debug(" UP");
|
||||||
|
else
|
||||||
|
debug(" DOWN");
|
||||||
|
if (i->flags & IF_LINK_UP)
|
||||||
|
debug(" LINK-UP");
|
||||||
if (i->flags & IF_MULTIACCESS)
|
if (i->flags & IF_MULTIACCESS)
|
||||||
debug(" MA");
|
debug(" MA");
|
||||||
if (i->flags & IF_UNNUMBERED)
|
if (i->flags & IF_UNNUMBERED)
|
||||||
|
@ -229,14 +231,16 @@ if_dump_all(void)
|
||||||
static inline int
|
static inline int
|
||||||
if_change_too_big_p(struct iface *i, struct iface *j)
|
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) ||
|
!ipa_equal(i->prefix, j->prefix) ||
|
||||||
i->pxlen != j->pxlen ||
|
i->pxlen != j->pxlen ||
|
||||||
!ipa_equal(i->brd, j->brd) ||
|
!ipa_equal(i->brd, j->brd) ||
|
||||||
!ipa_equal(i->opposite, j->opposite))
|
!ipa_equal(i->opposite, j->opposite))
|
||||||
return 1; /* Changed addresses */
|
|
||||||
if ((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED))
|
|
||||||
return 1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,6 +299,11 @@ if_update(struct iface *new)
|
||||||
struct iface *i;
|
struct iface *i;
|
||||||
unsigned c;
|
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)
|
WALK_LIST(i, iface_list)
|
||||||
if (!strcmp(new->name, i->name))
|
if (!strcmp(new->name, i->name))
|
||||||
{
|
{
|
||||||
|
@ -337,8 +346,9 @@ if_end_update(void)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(&j, i, sizeof(struct iface));
|
memcpy(&j, i, sizeof(struct iface));
|
||||||
i->flags = (i->flags & ~IF_UP) | IF_ADMIN_DOWN;
|
i->flags = (i->flags & ~(IF_LINK_UP | IF_UP)) | IF_ADMIN_DOWN;
|
||||||
if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, &j, i);
|
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;
|
j = NULL;
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, iface_list)
|
||||||
if ((i->flags & IF_UP) &&
|
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 || ipa_to_u32(i->ip) < ipa_to_u32(j->ip)))
|
||||||
j = i;
|
j = i;
|
||||||
if (!j)
|
if (!j)
|
||||||
|
|
|
@ -21,7 +21,7 @@ struct iface {
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
unsigned mtu;
|
unsigned mtu;
|
||||||
unsigned index; /* OS-dependent interface index */
|
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 */
|
ip_addr prefix; /* Network prefix */
|
||||||
unsigned pxlen; /* Prefix length */
|
unsigned pxlen; /* Prefix length */
|
||||||
ip_addr brd; /* Broadcast address */
|
ip_addr brd; /* Broadcast address */
|
||||||
|
@ -29,7 +29,7 @@ struct iface {
|
||||||
struct neighbor *neigh; /* List of neighbors on this interface */
|
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_MULTIACCESS 2
|
||||||
#define IF_UNNUMBERED 4
|
#define IF_UNNUMBERED 4
|
||||||
#define IF_BROADCAST 8
|
#define IF_BROADCAST 8
|
||||||
|
@ -38,7 +38,8 @@ struct iface {
|
||||||
#define IF_ADMIN_DOWN 64
|
#define IF_ADMIN_DOWN 64
|
||||||
#define IF_LOOPBACK 128
|
#define IF_LOOPBACK 128
|
||||||
#define IF_IGNORE 256
|
#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 */
|
/* Interface change events */
|
||||||
|
|
||||||
|
|
|
@ -42,16 +42,18 @@ scan_ifs(struct ifreq *r, int cnt)
|
||||||
bzero(&i, sizeof(i));
|
bzero(&i, sizeof(i));
|
||||||
DBG("%s\n", r->ifr_ifrn.ifrn_name);
|
DBG("%s\n", r->ifr_ifrn.ifrn_name);
|
||||||
strncpy(i.name, r->ifr_ifrn.ifrn_name, sizeof(i.name) - 1);
|
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);
|
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &i.ip, NULL);
|
||||||
l = ipa_classify(i.ip);
|
if (ipa_nonzero(i.ip))
|
||||||
if (l < 0 || !(l & IADDR_HOST))
|
|
||||||
{
|
{
|
||||||
log(L_ERR "%s: Invalid interface address", i.name);
|
l = ipa_classify(i.ip);
|
||||||
goto bad;
|
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)
|
if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0)
|
||||||
{
|
{
|
||||||
|
@ -59,12 +61,12 @@ scan_ifs(struct ifreq *r, int cnt)
|
||||||
faulty:
|
faulty:
|
||||||
log(L_ERR "%s(%s): %m", err, i.name);
|
log(L_ERR "%s(%s): %m", err, i.name);
|
||||||
bad:
|
bad:
|
||||||
i.flags = (i.flags & ~IF_UP) | IF_ADMIN_DOWN;
|
i.flags = (i.flags & ~IF_LINK_UP) | IF_ADMIN_DOWN;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fl = r->ifr_flags;
|
fl = r->ifr_flags;
|
||||||
if (fl & IFF_UP)
|
if (fl & IFF_UP)
|
||||||
i.flags |= IF_UP;
|
i.flags |= IF_LINK_UP;
|
||||||
|
|
||||||
if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0)
|
if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0)
|
||||||
{ err = "SIOCGIFNETMASK"; goto faulty; }
|
{ err = "SIOCGIFNETMASK"; goto faulty; }
|
||||||
|
@ -120,6 +122,8 @@ scan_ifs(struct ifreq *r, int cnt)
|
||||||
DBG("SIOCGIFINDEX failed: %m\n");
|
DBG("SIOCGIFINDEX failed: %m\n");
|
||||||
else
|
else
|
||||||
i.index = r->ifr_ifindex;
|
i.index = r->ifr_ifindex;
|
||||||
|
#else
|
||||||
|
/* FIXME: What else? Guess ifindex (we need it at least for OSPF on unnumbered links)? */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if_update(&i);
|
if_update(&i);
|
||||||
|
|
Loading…
Reference in a new issue