summaryrefslogtreecommitdiff
path: root/sysdep
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep')
-rw-r--r--sysdep/linux/netlink.c29
-rw-r--r--sysdep/unix/io.c12
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