summaryrefslogtreecommitdiff
path: root/sysdep/linux/netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep/linux/netlink.c')
-rw-r--r--sysdep/linux/netlink.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 9bdcc0d2..1490213e 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -899,7 +899,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
r.r.rtm_family = BIRD_AF;
r.r.rtm_dst_len = net->n.pxlen;
r.r.rtm_protocol = RTPROT_BIRD;
- r.r.rtm_scope = RT_SCOPE_UNIVERSE;
+ r.r.rtm_scope = RT_SCOPE_NOWHERE;
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
/*
@@ -928,6 +928,12 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
if (op == NL_OP_DELETE)
goto dest;
+ /* Default scope is LINK for device routes, UNIVERSE otherwise */
+ if (ea = ea_find(eattrs, EA_KRT_SCOPE))
+ r.r.rtm_scope = ea->u.data;
+ else
+ r.r.rtm_scope = (dest == RTD_DEVICE) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
+
if (ea = ea_find(eattrs, EA_KRT_PREFSRC))
nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
@@ -1135,6 +1141,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
u32 oif = ~0;
u32 table;
u32 priority = 0;
+ u32 def_scope = RT_SCOPE_UNIVERSE;
int src;
if (!(i = nl_checkin(h, sizeof(*i))))
@@ -1157,7 +1164,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
return;
}
-
if (a[RTA_DST])
{
memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
@@ -1195,11 +1201,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
SKIP("strange class/scope\n");
- // ignore rtm_scope, it is not a real scope
- // if (i->rtm_scope != RT_SCOPE_UNIVERSE)
- // SKIP("scope %u\n", i->rtm_scope);
-
-
switch (i->rtm_protocol)
{
case RTPROT_UNSPEC:
@@ -1286,6 +1287,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
else
{
ra->dest = RTD_DEVICE;
+ def_scope = RT_SCOPE_LINK;
}
break;
@@ -1304,6 +1306,19 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
return;
}
+ if (i->rtm_scope != def_scope)
+ {
+ ea_list *ea = lp_alloc(s->pool, sizeof(ea_list) + sizeof(eattr));
+ ea->next = ra->eattrs;
+ ra->eattrs = ea;
+ ea->flags = EALF_SORTED;
+ ea->count = 1;
+ ea->attrs[0].id = EA_KRT_SCOPE;
+ ea->attrs[0].flags = 0;
+ ea->attrs[0].type = EAF_TYPE_INT;
+ ea->attrs[0].u.data = i->rtm_scope;
+ }
+
if (a[RTA_PREFSRC])
{
ip_addr ps;
@@ -1633,6 +1648,10 @@ krt_sys_get_attr(eattr *a, byte *buf, int buflen UNUSED)
bsprintf(buf, "realm");
return GA_NAME;
+ case EA_KRT_SCOPE:
+ bsprintf(buf, "scope");
+ return GA_NAME;
+
case EA_KRT_LOCK:
buf += bsprintf(buf, "lock:");
ea_format_bitfield(a, buf, buflen, krt_metrics_names, 2, KRT_METRICS_MAX);