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_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;
} }

View file

@ -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);

View file

@ -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)
{ {
@ -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"); log("Ignoring strange IFINFO");
return; 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 */ /* 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;

View file

@ -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;