diff options
| author | Renato Westphal <renato@opensourcerouting.org> | 2023-10-13 10:55:39 -0300 |
|---|---|---|
| committer | Renato Westphal <renato@opensourcerouting.org> | 2023-10-13 12:32:40 -0300 |
| commit | 331ae6accc9737324e7a050033971c2f402c8933 (patch) | |
| tree | 2081b0247a6dbe1675598a51c4df79762d6b075b /ospf6d | |
| parent | df03bf95eb111c4c59ac6bddab38372b0c22748a (diff) | |
ospf6d: fix setting of the forwarding address in AS-External LSAs
When redistributing a local route, ensure the forwarding address field
of AS-External LSAs is only set when the associated nexthop interface
is OSPF-enabled. This is necessary because the OSPF RFC requires that
the AS-External LSA forwarding address should be resolvable using an
intra-area or inter-area path.
Fixes #14462.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'ospf6d')
| -rw-r--r-- | ospf6d/ospf6_asbr.c | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 713dd82075..99c3e16263 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -1376,6 +1376,56 @@ ospf6_external_aggr_match(struct ospf6 *ospf6, struct prefix *p) return node->info; } +static void ospf6_external_lsa_fwd_addr_set(struct ospf6 *ospf6, + const struct in6_addr *nexthop, + struct in6_addr *fwd_addr) +{ + struct vrf *vrf; + struct interface *ifp; + struct prefix nh; + + /* Initialize forwarding address to zero. */ + memset(fwd_addr, 0, sizeof(*fwd_addr)); + + vrf = vrf_lookup_by_id(ospf6->vrf_id); + if (!vrf) + return; + + nh.family = AF_INET6; + nh.u.prefix6 = *nexthop; + nh.prefixlen = IPV6_MAX_BITLEN; + + /* + * Use the route's nexthop as the forwarding address if it meets the + * following conditions: + * - It's a global address. + * - The associated nexthop interface is OSPF-enabled. + */ + if (IN6_IS_ADDR_UNSPECIFIED(nexthop) || IN6_IS_ADDR_LINKLOCAL(nexthop)) + return; + + FOR_ALL_INTERFACES (vrf, ifp) { + struct ospf6_interface *oi = ifp->info; + struct connected *connected; + struct listnode *node; + + if (!oi || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) + continue; + + FOR_ALL_INTERFACES_ADDRESSES (ifp, connected, node) { + if (connected->address->family != AF_INET6) + continue; + if (IN6_IS_ADDR_LINKLOCAL(&connected->address->u.prefix6)) + continue; + if (!prefix_match(connected->address, &nh)) + continue; + + *fwd_addr = *nexthop; + return; + } + } +} + void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, struct prefix *prefix, unsigned int nexthop_num, @@ -1470,10 +1520,8 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, if (nexthop_num && nexthop) { ospf6_route_add_nexthop(match, ifindex, nexthop); - if (!IN6_IS_ADDR_UNSPECIFIED(nexthop) - && !IN6_IS_ADDR_LINKLOCAL(nexthop)) - memcpy(&info->forwarding, nexthop, - sizeof(struct in6_addr)); + ospf6_external_lsa_fwd_addr_set(ospf6, nexthop, + &info->forwarding); } else ospf6_route_add_nexthop(match, ifindex, NULL); @@ -1520,10 +1568,8 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, info->type = type; if (nexthop_num && nexthop) { ospf6_route_add_nexthop(route, ifindex, nexthop); - if (!IN6_IS_ADDR_UNSPECIFIED(nexthop) - && !IN6_IS_ADDR_LINKLOCAL(nexthop)) - memcpy(&info->forwarding, nexthop, - sizeof(struct in6_addr)); + ospf6_external_lsa_fwd_addr_set(ospf6, nexthop, + &info->forwarding); } else ospf6_route_add_nexthop(route, ifindex, NULL); |
