Fixes problems with creating/removing/renaming ifaces on BSD.

This commit is contained in:
Ondrej Zajicek 2012-01-23 01:26:40 +01:00
parent 5c78e0e386
commit 732a0a257d
4 changed files with 54 additions and 28 deletions

View file

@ -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_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
* @new: new interface status
@ -400,7 +418,7 @@ if_find_by_index(unsigned idx)
struct iface *i;
WALK_LIST(i, iface_list)
if (i->index == idx)
if (i->index == idx && !(i->flags & IF_SHUTDOWN))
return i;
return NULL;
}

View file

@ -88,6 +88,7 @@ void ifa_dump(struct ifa *);
void if_show(void);
void if_show_summary(void);
struct iface *if_update(struct iface *);
void if_delete(struct iface *old);
struct ifa *ifa_update(struct ifa *);
void ifa_delete(struct ifa *);
void if_start_update(void);

View file

@ -416,8 +416,9 @@ krt_read_ifinfo(struct ks_msg *msg)
void *body = (void *)(ifm + 1);
struct sockaddr_dl *dl = NULL;
unsigned int i;
struct iface *iface = NULL, f;
struct iface *iface = NULL, f = {};
int fl = ifm->ifm_flags;
int nlen = 0;
for (i = 1; i<=RTA_IFP; i <<= 1)
{
@ -432,31 +433,42 @@ krt_read_ifinfo(struct ks_msg *msg)
}
}
if(dl && (dl->sdl_family != AF_LINK))
if (dl && (dl->sdl_family != AF_LINK))
{
log("Ignoring strange IFINFO");
return;
}
iface = if_find_by_index(ifm->ifm_index);
if (dl)
nlen = MIN(sizeof(f.name)-1, dl->sdl_nlen);
if(!iface)
/* 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)
{
/* New interface */
if(!dl) return; /* No interface name, ignoring */
if (!dl)
return; /* No interface name, ignoring */
bzero(&f, sizeof(f));
f.index = ifm->ifm_index;
memcpy(f.name, dl->sdl_data, MIN(sizeof(f.name)-1, dl->sdl_nlen));
DBG("New interface '%s' found", f.name);
memcpy(f.name, dl->sdl_data, nlen);
DBG("New interface '%s' found\n", 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
{
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.flags = 0;
if (fl & IFF_UP)
f.flags |= IF_ADMIN_UP;

View file

@ -386,7 +386,7 @@ nl_parse_link(struct nlmsghdr *h, int scan)
struct ifinfomsg *i;
struct rtattr *a[IFLA_WIRELESS+1];
int new = h->nlmsg_type == RTM_NEWLINK;
struct iface f;
struct iface f = {};
struct iface *ifi;
char *name;
u32 mtu;
@ -408,26 +408,21 @@ nl_parse_link(struct nlmsghdr *h, int scan)
if (!new)
{
DBG("KIF: IF%d(%s) goes down\n", i->ifi_index, name);
if (ifi && !scan)
{
memcpy(&f, ifi, sizeof(struct iface));
f.flags |= IF_SHUTDOWN;
if_update(&f);
}
if (!ifi)
return;
if_delete(ifi);
}
else
{
DBG("KIF: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i->ifi_index, name, mtu, i->ifi_flags);
if (ifi)
memcpy(&f, ifi, sizeof(f));
else
{
bzero(&f, sizeof(f));
if (ifi && strncmp(ifi->name, name, sizeof(ifi->name)-1))
if_delete(ifi);
strncpy(f.name, name, sizeof(f.name)-1);
f.index = i->ifi_index;
}
strncpy(f.name, RTA_DATA(a[IFLA_IFNAME]), sizeof(f.name)-1);
f.mtu = mtu;
f.flags = 0;
fl = i->ifi_flags;
if (fl & IFF_UP)
f.flags |= IF_ADMIN_UP;