summaryrefslogtreecommitdiff
path: root/zebra/rt_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r--zebra/rt_netlink.c58
1 files changed, 33 insertions, 25 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index b346247d4b..80841b6ac1 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -387,8 +387,15 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
memcpy(&p.u.prefix4, dest, 4);
p.prefixlen = rtm->rtm_dst_len;
- src_p.prefixlen =
- 0; // Forces debug below to not display anything
+ if (rtm->rtm_src_len != 0) {
+ char buf[PREFIX_STRLEN];
+ zlog_warn("unsupported IPv4 sourcedest route (dest %s vrf %u)",
+ prefix2str(&p, buf, sizeof(buf)), vrf_id);
+ return 0;
+ }
+
+ /* Force debug below to not display anything for source */
+ src_p.prefixlen = 0;
} else if (rtm->rtm_family == AF_INET6) {
p.family = AF_INET6;
memcpy(&p.u.prefix6, dest, 16);
@@ -399,14 +406,6 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
src_p.prefixlen = rtm->rtm_src_len;
}
- if (rtm->rtm_src_len != 0) {
- char buf[PREFIX_STRLEN];
- zlog_warn(
- "unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
- prefix2str(&p, buf, sizeof(buf)), vrf_id);
- return 0;
- }
-
/*
* For ZEBRA_ROUTE_KERNEL types:
*
@@ -492,7 +491,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
nh.vrf_id = nh_vrf_id;
rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
- NULL, &nh, table, metric, mtu, distance, tag);
+ &src_p, &nh, table, metric, mtu, distance, tag);
} else {
/* This is a multipath route */
@@ -581,6 +580,9 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
route_entry_nexthop_ifindex_add(
re, index, nh_vrf_id);
+ if (rtnh->rtnh_len == 0)
+ break;
+
len -= NLMSG_ALIGN(rtnh->rtnh_len);
rtnh = RTNH_NEXT(rtnh);
}
@@ -591,8 +593,8 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
if (re->nexthop_num == 0)
XFREE(MTYPE_RE, re);
else
- rib_add_multipath(afi, SAFI_UNICAST, &p, NULL,
- re);
+ rib_add_multipath(afi, SAFI_UNICAST, &p,
+ &src_p, re);
}
} else {
if (!tb[RTA_MULTIPATH]) {
@@ -624,12 +626,12 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
if (gate)
memcpy(&nh.gate, gate, sz);
rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
- &p, NULL, &nh, table, metric, true);
+ &p, &src_p, &nh, table, metric, true);
} else {
/* XXX: need to compare the entire list of nexthops
* here for NLM_F_APPEND stupidity */
rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
- &p, NULL, NULL, table, metric, true);
+ &p, &src_p, NULL, table, metric, true);
}
}
@@ -701,6 +703,9 @@ static int netlink_route_change_read_multicast(struct nlmsghdr *h,
oif[oif_count] = rtnh->rtnh_ifindex;
oif_count++;
+ if (rtnh->rtnh_len == 0)
+ break;
+
len -= NLMSG_ALIGN(rtnh->rtnh_len);
rtnh = RTNH_NEXT(rtnh);
}
@@ -2160,6 +2165,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
char buf2[INET6_ADDRSTRLEN];
int mac_present = 0;
uint8_t ext_learned;
+ uint8_t router_flag;
ndm = NLMSG_DATA(h);
@@ -2250,6 +2256,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
}
ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
+ router_flag = (ndm->ndm_flags & NTF_ROUTER) ? 1 : 0;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
@@ -2272,7 +2279,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (ndm->ndm_state & NUD_VALID)
return zebra_vxlan_handle_kernel_neigh_update(
ifp, link_if, &ip, &mac, ndm->ndm_state,
- ext_learned);
+ ext_learned, router_flag);
return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
}
@@ -2406,7 +2413,8 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
}
static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
- struct ethaddr *mac, uint32_t flags, int cmd)
+ struct ethaddr *mac, uint8_t flags,
+ uint16_t state, int cmd)
{
struct {
struct nlmsghdr n;
@@ -2429,11 +2437,10 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
- req.ndm.ndm_state = flags;
+ req.ndm.ndm_state = state;
req.ndm.ndm_ifindex = ifp->ifindex;
req.ndm.ndm_type = RTN_UNICAST;
- req.ndm.ndm_flags = NTF_EXT_LEARNED;
-
+ req.ndm.ndm_flags = flags;
ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
@@ -2441,12 +2448,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s",
+ zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x",
nl_msg_type_to_str(cmd),
nl_family_to_str(req.ndm.ndm_family), ifp->name,
ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)),
mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
- : "null");
+ : "null", flags);
return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
0);
@@ -2467,14 +2474,15 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
}
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
- struct ethaddr *mac)
+ struct ethaddr *mac, uint8_t flags)
{
- return netlink_neigh_update2(ifp, ip, mac, NUD_NOARP, RTM_NEWNEIGH);
+ return netlink_neigh_update2(ifp, ip, mac, flags,
+ NUD_NOARP, RTM_NEWNEIGH);
}
int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
{
- return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH);
+ return netlink_neigh_update2(ifp, ip, NULL, 0, 0, RTM_DELNEIGH);
}
/*