diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2017-12-07 18:35:46 +0100 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2017-12-07 18:35:46 +0100 |
commit | 46434a3cad99260b5a659e5df874eab4615bcb36 (patch) | |
tree | e5f4842fbdcc2ee0c66d6fdb437cb401a7234fb1 /sysdep | |
parent | 4ff15a75c56531fa2d3858d8250dcef1af4e75b6 (diff) | |
parent | 7b2c5f3d2826e3175bf31b1c36056c9efc587a2b (diff) |
Merge commit '7b2c5f3d2826e3175bf31b1c36056c9efc587a2b' into int-new
Diffstat (limited to 'sysdep')
-rw-r--r-- | sysdep/linux/netlink.c | 29 | ||||
-rw-r--r-- | sysdep/unix/io.c | 12 |
2 files changed, 40 insertions, 1 deletions
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 279f3c9c..05c1fa8c 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -324,6 +324,7 @@ struct nl_want_attrs { static struct nl_want_attrs ifla_attr_want[BIRD_IFLA_MAX] = { [IFLA_IFNAME] = { 1, 0, 0 }, [IFLA_MTU] = { 1, 1, sizeof(u32) }, + [IFLA_MASTER] = { 1, 1, sizeof(u32) }, [IFLA_WIRELESS] = { 1, 0, 0 }, }; @@ -790,7 +791,7 @@ nl_parse_link(struct nlmsghdr *h, int scan) struct iface f = {}; struct iface *ifi; char *name; - u32 mtu; + u32 mtu, master = 0; uint fl; if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFLA_RTA(i), ifla_attr_want, a, sizeof(a))) @@ -813,6 +814,9 @@ nl_parse_link(struct nlmsghdr *h, int scan) name = RTA_DATA(a[IFLA_IFNAME]); mtu = rta_get_u32(a[IFLA_MTU]); + if (a[IFLA_MASTER]) + master = rta_get_u32(a[IFLA_MASTER]); + ifi = if_find_by_index(i->ifi_index); if (!new) { @@ -832,6 +836,9 @@ nl_parse_link(struct nlmsghdr *h, int scan) f.index = i->ifi_index; f.mtu = mtu; + f.master_index = master; + f.master = if_find_by_index(master); + fl = i->ifi_flags; if (fl & IFF_UP) f.flags |= IF_ADMIN_UP; @@ -1091,6 +1098,26 @@ kif_do_scan(struct kif_proto *p UNUSED) else log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type); + /* Re-resolve master interface for slaves */ + struct iface *i; + WALK_LIST(i, iface_list) + if (i->master_index) + { + struct iface f = { + .flags = i->flags, + .mtu = i->mtu, + .index = i->index, + .master_index = i->master_index, + .master = if_find_by_index(i->master_index) + }; + + if (f.master != i->master) + { + memcpy(f.name, i->name, sizeof(f.name)); + if_update(&f); + } + } + nl_request_dump(AF_INET, RTM_GETADDR); while (h = nl_get_scan()) if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR) diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 7492e031..cd2558b2 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -931,6 +931,18 @@ sk_setup(sock *s) } #endif + if (s->vrf && !s->iface) + { + /* Bind socket to associated VRF interface. + This is Linux-specific, but so is SO_BINDTODEVICE. */ +#ifdef SO_BINDTODEVICE + struct ifreq ifr = {}; + strcpy(ifr.ifr_name, s->vrf->name); + if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) + ERR("SO_BINDTODEVICE"); +#endif + } + if (s->iface) { #ifdef SO_BINDTODEVICE |