summaryrefslogtreecommitdiff
path: root/sysdep
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2017-12-07 18:35:46 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2017-12-07 18:35:46 +0100
commit46434a3cad99260b5a659e5df874eab4615bcb36 (patch)
treee5f4842fbdcc2ee0c66d6fdb437cb401a7234fb1 /sysdep
parent4ff15a75c56531fa2d3858d8250dcef1af4e75b6 (diff)
parent7b2c5f3d2826e3175bf31b1c36056c9efc587a2b (diff)
Merge commit '7b2c5f3d2826e3175bf31b1c36056c9efc587a2b' into int-new
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 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