Skip to content

Commit

Permalink
lib,zebra,bgpd: Fix for nexthop as IPv4 mapped IPv6 address
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
KaushikNiral committed Aug 4, 2020
1 parent de5f29d commit 92d6f76
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 13 deletions.
17 changes: 15 additions & 2 deletions bgpd/bgp_nht.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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:
Expand Down
12 changes: 12 additions & 0 deletions bgpd/bgp_updgrp_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions lib/ipaddr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 11 additions & 8 deletions zebra/rt_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}

Expand Down
12 changes: 10 additions & 2 deletions zebra/zebra_fpm_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
13 changes: 12 additions & 1 deletion zebra/zebra_nhg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 92d6f76

Please sign in to comment.