diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 4e5c16a338..0c3d17dbda 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -241,92 +241,8 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, p.family = AF_INET; memcpy (&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; - - if (rtm->rtm_src_len != 0) - { - zlog_warn ("unsupported IPv4 sourcedest route (dest %s/%d)", - inet_ntoa (p.u.prefix4), p.prefixlen); - return 0; - } - - if (IS_ZEBRA_DEBUG_KERNEL) - { - char buf[PREFIX_STRLEN]; - zlog_debug ("%s %s vrf %u", - nl_msg_type_to_str (h->nlmsg_type), - prefix2str (&p, buf, sizeof(buf)), vrf_id); - } - - if (h->nlmsg_type == RTM_NEWROUTE) - { - if (!tb[RTA_MULTIPATH]) - rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, NULL, gate, prefsrc, index, - table, metric, mtu, 0); - else - { - /* This is a multipath route */ - - struct rib *rib; - struct rtnexthop *rtnh = - (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]); - - len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); - - rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); - rib->type = ZEBRA_ROUTE_KERNEL; - rib->distance = 0; - rib->flags = flags; - rib->metric = metric; - rib->mtu = mtu; - rib->vrf_id = vrf_id; - rib->table = table; - rib->nexthop_num = 0; - rib->uptime = time (NULL); - - for (;;) - { - if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) - break; - - index = rtnh->rtnh_ifindex; - gate = 0; - if (rtnh->rtnh_len > sizeof (*rtnh)) - { - memset (tb, 0, sizeof (tb)); - netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh), - rtnh->rtnh_len - sizeof (*rtnh)); - if (tb[RTA_GATEWAY]) - gate = RTA_DATA (tb[RTA_GATEWAY]); - } - - if (gate) - { - if (index) - rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index); - else - rib_nexthop_ipv4_add (rib, gate, prefsrc); - } - else - rib_nexthop_ifindex_add (rib, index); - - len -= NLMSG_ALIGN(rtnh->rtnh_len); - rtnh = RTNH_NEXT(rtnh); - } - - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, - rib->nexthop_num); - if (rib->nexthop_num == 0) - XFREE (MTYPE_RIB, rib); - else - rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib); - } - } - else - rib_delete (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, - &p, NULL, gate, index, table); } - if (rtm->rtm_family == AF_INET6) + else if (rtm->rtm_family == AF_INET6) { p.family = AF_INET6; memcpy (&p.u.prefix6, dest, 16); @@ -335,27 +251,110 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, src_p.family = AF_INET6; memcpy (&src_p.prefix, src, 16); src_p.prefixlen = rtm->rtm_src_len; + } - if (IS_ZEBRA_DEBUG_KERNEL) - { - char buf[PREFIX_STRLEN]; - char buf2[PREFIX_STRLEN]; - zlog_debug ("%s %s%s%s vrf %u", - nl_msg_type_to_str (h->nlmsg_type), - prefix2str (&p, buf, sizeof(buf)), - src_p.prefixlen ? " from " : "", - src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "", - vrf_id); - } + 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; + } - if (h->nlmsg_type == RTM_NEWROUTE) - rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, &src_p, gate, prefsrc, index, + if (IS_ZEBRA_DEBUG_KERNEL) + { + char buf[PREFIX_STRLEN]; + char buf2[PREFIX_STRLEN]; + zlog_debug ("%s %s%s%s vrf %u", + nl_msg_type_to_str (h->nlmsg_type), + prefix2str (&p, buf, sizeof(buf)), + src_p.prefixlen ? " from " : "", + src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "", + vrf_id); + } + + afi_t afi = AFI_IP; + if (rtm->rtm_family == AF_INET6) + afi = AFI_IP6; + + if (h->nlmsg_type == RTM_NEWROUTE) + { + if (!tb[RTA_MULTIPATH]) + rib_add (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, flags, &p, NULL, gate, prefsrc, index, table, metric, mtu, 0); else - rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, &src_p, gate, index, table); + { + /* This is a multipath route */ + + struct rib *rib; + struct rtnexthop *rtnh = + (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]); + + len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); + + rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); + rib->type = ZEBRA_ROUTE_KERNEL; + rib->distance = 0; + rib->flags = flags; + rib->metric = metric; + rib->mtu = mtu; + rib->vrf_id = vrf_id; + rib->table = table; + rib->nexthop_num = 0; + rib->uptime = time (NULL); + + for (;;) + { + if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) + break; + + index = rtnh->rtnh_ifindex; + gate = 0; + if (rtnh->rtnh_len > sizeof (*rtnh)) + { + memset (tb, 0, sizeof (tb)); + netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh), + rtnh->rtnh_len - sizeof (*rtnh)); + if (tb[RTA_GATEWAY]) + gate = RTA_DATA (tb[RTA_GATEWAY]); + } + + if (gate) + { + if (rtm->rtm_family == AF_INET) + { + if (index) + rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index); + else + rib_nexthop_ipv4_add (rib, gate, prefsrc); + } + else if (rtm->rtm_family == AF_INET6) + { + if (index) + rib_nexthop_ipv6_ifindex_add (rib, gate, index); + else + rib_nexthop_ipv6_add (rib,gate); + } + } + else + rib_nexthop_ifindex_add (rib, index); + + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + + zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, + rib->nexthop_num); + if (rib->nexthop_num == 0) + XFREE (MTYPE_RIB, rib); + else + rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib); + } } + else + rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, + &p, NULL, gate, index, table); return 0; }