diff options
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 3658c46b..4802897b 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -300,6 +300,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 }, }; @@ -618,7 +619,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))) @@ -641,6 +642,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) { @@ -660,6 +664,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; @@ -835,6 +842,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(BIRD_AF, 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 561d4dea..6d6a0990 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -1211,6 +1211,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 |