]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib,zebra,bgpd: Fix for nexthop as IPv4 mapped IPv6 address 6821/head
authorKaushik <kaushik@niralnetworks.com>
Wed, 29 Jul 2020 15:48:57 +0000 (08:48 -0700)
committerKaushik <kaushik@niralnetworks.com>
Tue, 4 Aug 2020 06:24:04 +0000 (23:24 -0700)
Added a macro to validate the v4 mapped v6 address.
Modified bgp receive & send updates for v4 mapped v6 address as
nexthop and installing it as recursive nexthop in RIB.
Minor change in fpm while sending the routes for nexthop as
v4 mapped v6 address.

Signed-off-by: Kaushik <kaushik@niralnetworks.com>
bgpd/bgp_nht.c
bgpd/bgp_updgrp_packet.c
lib/ipaddr.h
zebra/rt_netlink.c
zebra/zebra_fpm_netlink.c
zebra/zebra_nhg.c

index aefcaeff3a2030c4eb7b52494f30642f3bcb9371..a74b5f91ac0800d31fdaf58721b896f2b4fc7c0e 100644 (file)
@@ -146,6 +146,11 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
                        afi = BGP_ATTR_NEXTHOP_AFI_IP6(pi->attr) ? AFI_IP6
                                                                 : AFI_IP;
 
+               /* Validation for the ipv4 mapped ipv6 nexthop. */
+               if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
+                       afi = AFI_IP;
+               }
+
                /* This will return true if the global IPv6 NH is a link local
                 * addr */
                if (make_prefix(afi, pi, &p) < 0)
@@ -533,6 +538,7 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
                                    : 0;
        struct bgp_dest *net = pi->net;
        const struct prefix *p_orig = bgp_dest_get_prefix(net);
+       struct in_addr ipv4;
 
        if (p_orig->family == AF_FLOWSPEC) {
                if (!pi->peer)
@@ -548,8 +554,15 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
                        p->u.prefix4 = p_orig->u.prefix4;
                        p->prefixlen = p_orig->prefixlen;
                } else {
-                       p->u.prefix4 = pi->attr->nexthop;
-                       p->prefixlen = IPV4_MAX_BITLEN;
+                       if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
+                               ipv4_mapped_ipv6_to_ipv4(
+                                       &pi->attr->mp_nexthop_global, &ipv4);
+                               p->u.prefix4 = ipv4;
+                               p->prefixlen = IPV4_MAX_BITLEN;
+                       } else {
+                               p->u.prefix4 = pi->attr->nexthop;
+                               p->prefixlen = IPV4_MAX_BITLEN;
+                       }
                }
                break;
        case AFI_IP6:
index 4de5ec3b04ffcfc60de9d71d4c4fe2c6e3a0f4c9..5df9e3f23f43e03cc0e505c9514797bfeef9d025 100644 (file)
@@ -574,6 +574,18 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
                        gnh_modified = 1;
                }
 
+               if (IN6_IS_ADDR_UNSPECIFIED(mod_v6nhg)) {
+                       if (peer->nexthop.v4.s_addr) {
+                               ipv4_to_ipv4_mapped_ipv6(mod_v6nhg,
+                                                        peer->nexthop.v4);
+                       }
+               }
+
+               if (IS_MAPPED_IPV6(&peer->nexthop.v6_global)) {
+                       mod_v6nhg = &peer->nexthop.v6_global;
+                       gnh_modified = 1;
+               }
+
                if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
                    || nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
                        stream_get_from(&v6nhlocal, s, offset_nhlocal,
index a96c9788bc375f6445c7dc240fd65e523e156c60..f2b75c1306d82a70fe9da572d3a70d69e04066f1 100644 (file)
@@ -89,6 +89,13 @@ static inline char *ipaddr2str(const struct ipaddr *ip, char *buf, int size)
        return buf;
 }
 
+#define IS_MAPPED_IPV6(A)                                                      \
+       ((A)->s6_addr32[0] == 0x00000000                                       \
+                ? ((A)->s6_addr32[1] == 0x00000000                            \
+                           ? (ntohl((A)->s6_addr32[2]) == 0xFFFF ? 1 : 0)     \
+                           : 0)                                               \
+                : 0)
+
 /*
  * Convert IPv4 address to IPv4-mapped IPv6 address which is of the
  * form ::FFFF:<IPv4 address> (RFC 4291). This IPv6 address can then
index 07e8e37b8232beeb39cfe9861c5ce676649a7a44..8d38b6defe1f5fd0e8f0428fe8c08ac516056a2b 100644 (file)
@@ -1051,14 +1051,17 @@ static bool _netlink_route_add_gateway_info(uint8_t route_family,
                                 bytelen + 2))
                        return false;
        } else {
-               if (gw_family == AF_INET) {
-                       if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY,
-                                        &nexthop->gate.ipv4, bytelen))
-                               return false;
-               } else {
-                       if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY,
-                                        &nexthop->gate.ipv6, bytelen))
-                               return false;
+               if (!(nexthop->rparent
+                     && IS_MAPPED_IPV6(&nexthop->rparent->gate.ipv6))) {
+                       if (gw_family == AF_INET) {
+                               if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY,
+                                                &nexthop->gate.ipv4, bytelen))
+                                       return false;
+                       } else {
+                               if (!nl_attr_put(nlmsg, req_size, RTA_GATEWAY,
+                                                &nexthop->gate.ipv6, bytelen))
+                                       return false;
+                       }
                }
        }
 
index a18885ddb74e3f1b17ab41b431e6fbacaa1d4e3e..5831093b5053c6cc389d4fe4e35a24c7a2b268c2 100644 (file)
@@ -364,6 +364,7 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
        struct rtattr *nest, *inner_nest;
        struct rtnexthop *rtnh;
        struct vxlan_encap_info_t *vxlan;
+       struct in6_addr ipv6;
 
        struct {
                struct nlmsghdr n;
@@ -423,8 +424,15 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
                nhi = &ri->nhs[0];
 
                if (nhi->gateway) {
-                       nl_attr_put(&req->n, in_buf_len, RTA_GATEWAY,
-                                   nhi->gateway, bytelen);
+                       if (nhi->type == NEXTHOP_TYPE_IPV4_IFINDEX
+                           && ri->af == AF_INET6) {
+                               ipv4_to_ipv4_mapped_ipv6(&ipv6,
+                                                        nhi->gateway->ipv4);
+                               nl_attr_put(&req->n, in_buf_len, RTA_GATEWAY,
+                                           &ipv6, bytelen);
+                       } else
+                               nl_attr_put(&req->n, in_buf_len, RTA_GATEWAY,
+                                           nhi->gateway, bytelen);
                }
 
                if (nhi->if_index) {
index c0580908444c7f38a83aba733e17620f9339f3fb..43bf7458965151c606685c4e9922aca3004d56da 100644 (file)
@@ -1775,6 +1775,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
        struct interface *ifp;
        rib_dest_t *dest;
        struct zebra_vrf *zvrf;
+       struct in_addr ipv4;
 
        if ((nexthop->type == NEXTHOP_TYPE_IPV4)
            || nexthop->type == NEXTHOP_TYPE_IPV6)
@@ -1835,13 +1836,23 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
                return 0;
        }
 
+       /* Validation for ipv4 mapped ipv6 nexthop. */
+       if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) {
+               afi = AFI_IP;
+       }
+
        /* Make lookup prefix. */
        memset(&p, 0, sizeof(struct prefix));
        switch (afi) {
        case AFI_IP:
                p.family = AF_INET;
                p.prefixlen = IPV4_MAX_PREFIXLEN;
-               p.u.prefix4 = nexthop->gate.ipv4;
+               if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) {
+                       ipv4_mapped_ipv6_to_ipv4(&nexthop->gate.ipv6, &ipv4);
+                       p.u.prefix4 = ipv4;
+               } else {
+                       p.u.prefix4 = nexthop->gate.ipv4;
+               }
                break;
        case AFI_IP6:
                p.family = AF_INET6;