diff options
Diffstat (limited to 'zebra/rt_netlink.c')
| -rw-r--r-- | zebra/rt_netlink.c | 90 |
1 files changed, 74 insertions, 16 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 216625e9..1bb2e476 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -737,6 +737,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) void *dest; void *gate; + void *src; rtm = NLMSG_DATA (h); @@ -776,6 +777,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) metric = 0; dest = NULL; gate = NULL; + src = NULL; if (tb[RTA_OIF]) index = *(int *) RTA_DATA (tb[RTA_OIF]); @@ -785,6 +787,9 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) else dest = anyaddr; + if (tb[RTA_PREFSRC]) + src = RTA_DATA (tb[RTA_PREFSRC]); + /* Multipath treatment is needed. */ if (tb[RTA_GATEWAY]) gate = RTA_DATA (tb[RTA_GATEWAY]); @@ -799,7 +804,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) memcpy (&p.prefix, dest, 4); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, metric, 0); + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0); } #ifdef HAVE_IPV6 if (rtm->rtm_family == AF_INET6) @@ -846,6 +851,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) int table; void *dest; void *gate; + void *src; rtm = NLMSG_DATA (h); @@ -902,6 +908,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) index = 0; dest = NULL; gate = NULL; + src = NULL; if (tb[RTA_OIF]) index = *(int *) RTA_DATA (tb[RTA_OIF]); @@ -914,6 +921,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (tb[RTA_GATEWAY]) gate = RTA_DATA (tb[RTA_GATEWAY]); + if (tb[RTA_PREFSRC]) + src = RTA_DATA (tb[RTA_PREFSRC]); + if (rtm->rtm_family == AF_INET) { struct prefix_ipv4 p; @@ -932,7 +942,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0); + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table); } @@ -1501,7 +1511,9 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, { addattr_l (&req.n, sizeof req, RTA_GATEWAY, &nexthop->rgate.ipv4, bytelen); - + if (nexthop->src.ipv4.s_addr) + addattr_l(&req.n, sizeof req, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (recursive, " "1 hop): nexthop via %s if %u", @@ -1531,6 +1543,11 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, { addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->rifindex); + if ((nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX + || nexthop->rtype == NEXTHOP_TYPE_IFINDEX) + && nexthop->src.ipv4.s_addr) + addattr_l (&req.n, sizeof req, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (recursive, " @@ -1559,6 +1576,9 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, { addattr_l (&req.n, sizeof req, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen); + if (nexthop->src.ipv4.s_addr) + addattr_l (&req.n, sizeof req, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (single hop): " @@ -1583,9 +1603,20 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, #endif /* HAVE_IPV6 */ if (nexthop->type == NEXTHOP_TYPE_IFINDEX || nexthop->type == NEXTHOP_TYPE_IFNAME - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) + { + addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex); + + if (nexthop->src.ipv4.s_addr) + addattr_l (&req.n, sizeof req, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("netlink_route_multipath() (single hop): " + "nexthop via if %u", nexthop->ifindex); + } + else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) { addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex); @@ -1608,6 +1639,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, char buf[1024]; struct rtattr *rta = (void *) buf; struct rtnexthop *rtnh; + union g_addr *src = NULL; rta->rta_type = RTA_MULTIPATH; rta->rta_len = RTA_LENGTH (0); @@ -1652,6 +1684,9 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, &nexthop->rgate.ipv4, bytelen); rtnh->rtnh_len += sizeof (struct rtattr) + 4; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (recursive, " "multihop): nexthop via %s if %u", @@ -1674,11 +1709,21 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, } #endif /* HAVE_IPV6 */ /* ifindex */ - if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX - || nexthop->rtype == NEXTHOP_TYPE_IFNAME - || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX - || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX - || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME) + if (nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX + || nexthop->rtype == NEXTHOP_TYPE_IFINDEX + || nexthop->rtype == NEXTHOP_TYPE_IFNAME) + { + rtnh->rtnh_ifindex = nexthop->rifindex; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("netlink_route_multipath() (recursive, " + "multihop): nexthop via if %u", + nexthop->rifindex); + } + else if (nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX + || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME) { rtnh->rtnh_ifindex = nexthop->rifindex; @@ -1713,6 +1758,9 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, &nexthop->gate.ipv4, bytelen); rtnh->rtnh_len += sizeof (struct rtattr) + 4; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("netlink_route_multipath() (multihop): " "nexthop via %s if %u", @@ -1735,11 +1783,19 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, } #endif /* HAVE_IPV6 */ /* ifindex */ - if (nexthop->type == NEXTHOP_TYPE_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IFNAME - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) + if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IFNAME) + { + rtnh->rtnh_ifindex = nexthop->ifindex; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("netlink_route_multipath() (multihop): " + "nexthop via if %u", nexthop->ifindex); + } + else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { rtnh->rtnh_ifindex = nexthop->ifindex; @@ -1758,6 +1814,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); } } + if (src) + addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen); if (rta->rta_len > RTA_LENGTH (0)) addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA (rta), |
