Skip to content
This repository has been archived by the owner on Apr 1, 2024. It is now read-only.

Commit

Permalink
Fix for nexthop as IPv4 mapped IPv6 address
Browse files Browse the repository at this point in the history
BUG No. FRRouting#6341 and FRRouting#6382
lib : Added a macro to validate the IPv4 Mapped IPv6 address.
bgp : Modifications done for bgp receive and while sending updates
for IPv4 Mapped IPv6 address.
zebra : Modifications done for installing IPv4 Mapped IPv6 address as nexthop
in RIB. Minor correction done in fpm while sending the routes for
nexthop as IPv4 Mapped IPv6 address.

Signed-off-by: Kaushik <kaushik@niralnetworks.com>
  • Loading branch information
KaushikNiral committed May 25, 2020
1 parent 812507e commit ed741b6
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 11 deletions.
15 changes: 13 additions & 2 deletions bgpd/bgp_nht.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
if (!is_bgp_static_route)
afi = BGP_ATTR_NEXTHOP_AFI_IP6(pi->attr) ? AFI_IP6
: AFI_IP;
/* Validation for the ipv4 mapped ipv6 nexthop. */
if(VALIDATE_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
afi = AFI_IP;
}

/* This will return true if the global IPv6 NH is a link local
* addr */
Expand Down Expand Up @@ -532,6 +536,7 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
: 0;
struct bgp_node *net = pi->net;
const struct prefix *p_orig = bgp_node_get_prefix(net);
struct in_addr ipv4;

if (p_orig->family == AF_FLOWSPEC) {
if (!pi->peer)
Expand All @@ -547,8 +552,14 @@ 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 (VALIDATE_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: 11 additions & 1 deletion bgpd/bgp_updgrp_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,17 @@ 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);
}
} else {
if(peer->nexthop.v4.s_addr && (!IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local))) {
ipv4_to_ipv4_mapped_ipv6(mod_v6nhg, peer->nexthop.v4);
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 Expand Up @@ -818,7 +829,6 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
subgrp, adj);
return NULL;
}

if (BGP_DEBUG(update, UPDATE_OUT)
|| BGP_DEBUG(update, UPDATE_PREFIX)) {
memset(send_attr_str, 0, BUFSIZ);
Expand Down
5 changes: 5 additions & 0 deletions lib/ipaddr.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ static inline char *ipaddr2str(const struct ipaddr *ip, char *buf, int size)
return buf;
}

#define VALIDATE_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
16 changes: 10 additions & 6 deletions zebra/rt_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1046,12 +1046,16 @@ static void _netlink_route_nl_add_gateway_info(uint8_t route_family,
addattr_l(nlmsg, req_size, RTA_VIA, &gw_fam.family,
bytelen + 2);
} else {
if (gw_family == AF_INET)
addattr_l(nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv4, bytelen);
else
addattr_l(nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv6, bytelen);

if(nexthop->rparent && VALIDATE_MAPPED_IPV6(&nexthop->rparent->gate.ipv6)) {
} else {
if (gw_family == AF_INET)
addattr_l(nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv4, bytelen);
else
addattr_l(nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv6, bytelen);
}
}
}

Expand Down
7 changes: 6 additions & 1 deletion 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;
struct vxlan_encap_info_t *vxlan;
int nest_len;
struct in6_addr ipv6;

struct {
struct nlmsghdr n;
Expand Down Expand Up @@ -420,8 +421,12 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,

if (ri->num_nhs == 1) {
nhi = &ri->nhs[0];

if (nhi->gateway) {
if(nhi->type == NEXTHOP_TYPE_IPV4_IFINDEX && ri->af == AF_INET6) {
ipv4_to_ipv4_mapped_ipv6(&ipv6, nhi->gateway->ipv4);
addattr_l(&req->n, in_buf_len, RTA_GATEWAY,
&ipv6, bytelen);
} else
addattr_l(&req->n, in_buf_len, RTA_GATEWAY,
nhi->gateway, bytelen);
}
Expand Down
12 changes: 11 additions & 1 deletion zebra/zebra_nhg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1767,6 +1767,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 @@ -1827,13 +1828,22 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
return 0;
}

/* Validation for ipv4 mapped ipv6 nexthop. */
if (VALIDATE_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 (VALIDATE_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 ed741b6

Please sign in to comment.