summaryrefslogtreecommitdiff
path: root/sysdep
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep')
-rw-r--r--sysdep/bsd/krt-sock.c86
-rw-r--r--sysdep/linux/netlink.c52
-rw-r--r--sysdep/unix/krt.c13
3 files changed, 74 insertions, 77 deletions
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c
index 2e0f194b..c65cba65 100644
--- a/sysdep/bsd/krt-sock.c
+++ b/sysdep/bsd/krt-sock.c
@@ -193,7 +193,6 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
struct ks_msg msg;
char *body = (char *)msg.buf;
sockaddr gate, mask, dst;
- ip_addr gw;
DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw);
@@ -223,14 +222,12 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
msg.rtm.rtm_flags |= RTF_BLACKHOLE;
#endif
- /* This is really very nasty, but I'm not able
- * to add "(reject|blackhole)" route without
- * gateway set
+ /*
+ * This is really very nasty, but I'm not able to add reject/blackhole route
+ * without gateway address.
*/
- if(!i)
+ if (!i)
{
- i = HEAD(iface_list);
-
WALK_LIST(j, iface_list)
{
if (j->flags & IF_LOOPBACK)
@@ -239,13 +236,13 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
break;
}
}
- }
- gw = a->nh.gw;
-
- /* Embed interface ID to link-local address */
- if (ipa_is_link_local(gw))
- _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
+ if (!i)
+ {
+ log(L_ERR "KRT: Cannot find loopback iface");
+ return -1;
+ }
+ }
int af = AF_UNSPEC;
@@ -261,45 +258,51 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
return -1;
}
-
sockaddr_fill(&dst, af, net_prefix(net->n.addr), NULL, 0);
sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0);
- sockaddr_fill(&gate, af, gw, NULL, 0);
switch (a->dest)
{
- case RTD_UNICAST:
- if (ipa_zero(gw))
- {
- if(i)
- {
-#ifdef RTF_CLONING
- if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */
- msg.rtm.rtm_flags |= RTF_CLONING;
-#endif
+ case RTD_UNICAST:
+ if (ipa_nonzero(a->nh.gw))
+ {
+ ip_addr gw = a->nh.gw;
- if(!i->addr) {
- log(L_ERR "KRT: interface %s has no IP addess", i->name);
- return -1;
- }
-
- sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0);
- msg.rtm.rtm_addrs |= RTA_GATEWAY;
- }
- } else {
- msg.rtm.rtm_flags |= RTF_GATEWAY;
- msg.rtm.rtm_addrs |= RTA_GATEWAY;
- }
+ /* Embed interface ID to link-local address */
+ if (ipa_is_link_local(gw))
+ _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
+
+ sockaddr_fill(&gate, af, gw, NULL, 0);
+ msg.rtm.rtm_flags |= RTF_GATEWAY;
+ msg.rtm.rtm_addrs |= RTA_GATEWAY;
break;
+ }
#ifdef RTF_REJECT
- case RTD_UNREACHABLE:
+ case RTD_UNREACHABLE:
#endif
#ifdef RTF_BLACKHOLE
- case RTD_BLACKHOLE:
+ case RTD_BLACKHOLE:
#endif
- default:
- bug("krt-sock: unknown flags, but not filtered");
+ {
+ /* Fallback for all other valid cases */
+ if (!i->addr)
+ {
+ log(L_ERR "KRT: interface %s has no IP addess", i->name);
+ return -1;
+ }
+
+#ifdef RTF_CLONING
+ if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */
+ msg.rtm.rtm_flags |= RTF_CLONING;
+#endif
+
+ sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0);
+ msg.rtm.rtm_addrs |= RTA_GATEWAY;
+ }
+
+ default:
+ bug("krt-sock: unknown flags, but not filtered");
}
msg.rtm.rtm_index = i->index;
@@ -497,7 +500,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
}
a.dest = RTD_UNICAST;
- a.nh.next = NULL;
if (flags & RTF_GATEWAY)
{
neighbor *ng;
@@ -520,8 +522,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
return;
}
}
- else
- a.nh.gw = IPA_NONE;
done:
e = rte_get_temp(&a);
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 23431172..80439c47 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -320,6 +320,7 @@ static struct nl_want_attrs ifa_attr_want4[BIRD_IFA_MAX] = {
[IFA_ADDRESS] = { 1, 1, sizeof(ip4_addr) },
[IFA_LOCAL] = { 1, 1, sizeof(ip4_addr) },
[IFA_BROADCAST] = { 1, 1, sizeof(ip4_addr) },
+ [IFA_FLAGS] = { 1, 1, sizeof(u32) },
};
static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = {
@@ -543,18 +544,17 @@ nl_add_attr_via(struct nlmsghdr *h, uint bufsize, ip_addr ipa)
h->nlmsg_len += sizeof(*via);
- if (ipa_is_ip4(ipa)) {
- ip4_addr ip4 = ipa_to_ip4(ipa);
- ip4 = ip4_hton(ip4);
+ if (ipa_is_ip4(ipa))
+ {
via->rtvia_family = AF_INET;
- memcpy(via->rtvia_addr, &ip4, sizeof(ip4));
- h->nlmsg_len += sizeof(ip4);
- } else {
- ip6_addr ip6 = ipa_to_ip6(ipa);
- ip6 = ip6_hton(ip6);
+ put_ip4(via->rtvia_addr, ipa_to_ip4(ipa));
+ h->nlmsg_len += sizeof(ip4_addr);
+ }
+ else
+ {
via->rtvia_family = AF_INET6;
- memcpy(via->rtvia_addr, &ip6, sizeof(ip6));
- h->nlmsg_len += sizeof(ip6);
+ put_ip6(via->rtvia_addr, ipa_to_ip6(ipa));
+ h->nlmsg_len += sizeof(ip6_addr);
}
nl_close_attr(h, nest);
@@ -669,6 +669,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
}
else
rv->gw = IPA_NONE;
+
if (a[RTA_ENCAP_TYPE])
{
if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) {
@@ -1092,20 +1093,16 @@ krt_capable(rte *e)
rta *a = e->attrs;
switch (a->dest)
- {
+ {
case RTD_UNICAST:
- for (struct nexthop *nh = &(a->nh); nh; nh = nh->next)
- if (nh->iface)
- return 1;
- return 0;
case RTD_BLACKHOLE:
case RTD_UNREACHABLE:
case RTD_PROHIBIT:
- break;
+ return 1;
+
default:
return 0;
- }
- return 1;
+ }
}
static inline int
@@ -1210,7 +1207,6 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
dest:
- /* a->iface != NULL checked in krt_capable() for router and device routes */
switch (dest)
{
case RTD_UNICAST:
@@ -1502,6 +1498,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
switch (i->rtm_type)
{
case RTN_UNICAST:
+ ra->dest = RTD_UNICAST;
if (a[RTA_MULTIPATH] && (i->rtm_family == AF_INET))
{
@@ -1512,7 +1509,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
return;
}
- nexthop_link(ra, nh);
+ ra->nh = *nh;
break;
}
@@ -1698,9 +1695,20 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
else
{
/* Merge next hops with the stored route */
- rta *a = s->attrs;
+ rta *oa = s->attrs;
- nexthop_insert(&a->nh, &ra->nh);
+ struct nexthop *nhs = &oa->nh;
+ nexthop_insert(&nhs, &ra->nh);
+
+ /* Perhaps new nexthop is inserted at the first position */
+ if (nhs == &ra->nh)
+ {
+ /* Swap rtas */
+ s->attrs = ra;
+
+ /* Keep old eattrs */
+ ra->eattrs = oa->eattrs;
+ }
}
}
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index c273cb10..c6ff6275 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -984,7 +984,7 @@ krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
static int
krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
{
- struct krt_proto *p = (struct krt_proto *) P;
+ // struct krt_proto *p = (struct krt_proto *) P;
rte *e = *new;
if (e->attrs->src->proto == P)
@@ -1005,17 +1005,6 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li
return -1;
}
- if (!KRT_CF->devroutes && (e->attrs->source != RTS_STATIC_DEVICE))
- {
- struct nexthop *nh = &(e->attrs->nh);
- for (; nh; nh = nh->next)
- if (ipa_nonzero(nh->gw))
- break;
-
- if (!nh) /* Gone through all the nexthops and no explicit GW found */
- return -1;
- }
-
if (!krt_capable(e))
return -1;