Fixes problems with creating/removing/renaming ifaces on BSD.
This commit is contained in:
parent
5c78e0e386
commit
732a0a257d
4 changed files with 54 additions and 28 deletions
20
nest/iface.c
20
nest/iface.c
|
@ -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_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
|
* if_update - update interface status
|
||||||
* @new: new interface status
|
* @new: new interface status
|
||||||
|
@ -400,7 +418,7 @@ if_find_by_index(unsigned idx)
|
||||||
struct iface *i;
|
struct iface *i;
|
||||||
|
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, iface_list)
|
||||||
if (i->index == idx)
|
if (i->index == idx && !(i->flags & IF_SHUTDOWN))
|
||||||
return i;
|
return i;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,7 @@ void ifa_dump(struct ifa *);
|
||||||
void if_show(void);
|
void if_show(void);
|
||||||
void if_show_summary(void);
|
void if_show_summary(void);
|
||||||
struct iface *if_update(struct iface *);
|
struct iface *if_update(struct iface *);
|
||||||
|
void if_delete(struct iface *old);
|
||||||
struct ifa *ifa_update(struct ifa *);
|
struct ifa *ifa_update(struct ifa *);
|
||||||
void ifa_delete(struct ifa *);
|
void ifa_delete(struct ifa *);
|
||||||
void if_start_update(void);
|
void if_start_update(void);
|
||||||
|
|
|
@ -416,8 +416,9 @@ krt_read_ifinfo(struct ks_msg *msg)
|
||||||
void *body = (void *)(ifm + 1);
|
void *body = (void *)(ifm + 1);
|
||||||
struct sockaddr_dl *dl = NULL;
|
struct sockaddr_dl *dl = NULL;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct iface *iface = NULL, f;
|
struct iface *iface = NULL, f = {};
|
||||||
int fl = ifm->ifm_flags;
|
int fl = ifm->ifm_flags;
|
||||||
|
int nlen = 0;
|
||||||
|
|
||||||
for (i = 1; i<=RTA_IFP; i <<= 1)
|
for (i = 1; i<=RTA_IFP; i <<= 1)
|
||||||
{
|
{
|
||||||
|
@ -438,25 +439,36 @@ krt_read_ifinfo(struct ks_msg *msg)
|
||||||
return;
|
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 */
|
||||||
|
|
||||||
|
iface = if_find_by_index(ifm->ifm_index);
|
||||||
if (!iface)
|
if (!iface)
|
||||||
{
|
{
|
||||||
/* New interface */
|
/* New interface */
|
||||||
if(!dl) return; /* No interface name, ignoring */
|
if (!dl)
|
||||||
|
return; /* No interface name, ignoring */
|
||||||
|
|
||||||
bzero(&f, sizeof(f));
|
memcpy(f.name, dl->sdl_data, nlen);
|
||||||
f.index = ifm->ifm_index;
|
DBG("New interface '%s' found\n", f.name);
|
||||||
memcpy(f.name, dl->sdl_data, MIN(sizeof(f.name)-1, dl->sdl_nlen));
|
}
|
||||||
DBG("New interface '%s' found", 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
|
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.mtu = ifm->ifm_data.ifi_mtu;
|
||||||
f.flags = 0;
|
|
||||||
|
|
||||||
if (fl & IFF_UP)
|
if (fl & IFF_UP)
|
||||||
f.flags |= IF_ADMIN_UP;
|
f.flags |= IF_ADMIN_UP;
|
||||||
|
|
|
@ -386,7 +386,7 @@ nl_parse_link(struct nlmsghdr *h, int scan)
|
||||||
struct ifinfomsg *i;
|
struct ifinfomsg *i;
|
||||||
struct rtattr *a[IFLA_WIRELESS+1];
|
struct rtattr *a[IFLA_WIRELESS+1];
|
||||||
int new = h->nlmsg_type == RTM_NEWLINK;
|
int new = h->nlmsg_type == RTM_NEWLINK;
|
||||||
struct iface f;
|
struct iface f = {};
|
||||||
struct iface *ifi;
|
struct iface *ifi;
|
||||||
char *name;
|
char *name;
|
||||||
u32 mtu;
|
u32 mtu;
|
||||||
|
@ -408,26 +408,21 @@ nl_parse_link(struct nlmsghdr *h, int scan)
|
||||||
if (!new)
|
if (!new)
|
||||||
{
|
{
|
||||||
DBG("KIF: IF%d(%s) goes down\n", i->ifi_index, name);
|
DBG("KIF: IF%d(%s) goes down\n", i->ifi_index, name);
|
||||||
if (ifi && !scan)
|
if (!ifi)
|
||||||
{
|
return;
|
||||||
memcpy(&f, ifi, sizeof(struct iface));
|
|
||||||
f.flags |= IF_SHUTDOWN;
|
if_delete(ifi);
|
||||||
if_update(&f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBG("KIF: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i->ifi_index, name, mtu, i->ifi_flags);
|
DBG("KIF: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i->ifi_index, name, mtu, i->ifi_flags);
|
||||||
if (ifi)
|
if (ifi && strncmp(ifi->name, name, sizeof(ifi->name)-1))
|
||||||
memcpy(&f, ifi, sizeof(f));
|
if_delete(ifi);
|
||||||
else
|
|
||||||
{
|
strncpy(f.name, name, sizeof(f.name)-1);
|
||||||
bzero(&f, sizeof(f));
|
|
||||||
f.index = i->ifi_index;
|
f.index = i->ifi_index;
|
||||||
}
|
|
||||||
strncpy(f.name, RTA_DATA(a[IFLA_IFNAME]), sizeof(f.name)-1);
|
|
||||||
f.mtu = mtu;
|
f.mtu = mtu;
|
||||||
f.flags = 0;
|
|
||||||
fl = i->ifi_flags;
|
fl = i->ifi_flags;
|
||||||
if (fl & IFF_UP)
|
if (fl & IFF_UP)
|
||||||
f.flags |= IF_ADMIN_UP;
|
f.flags |= IF_ADMIN_UP;
|
||||||
|
|
Loading…
Reference in a new issue