Skip to content

Commit fbe0c00

Browse files
committed
bgpd: fix IPv6 nexthop for IPv4 peers to use IPv4-mapped address
When an IPv4 BGP peer advertises IPv6 prefixes (RFC 5549), the nexthop in UPDATE messages must be an IPv4-mapped IPv6 address (::ffff:x.x.x.x). Currently, bgp_zebra_nexthop_set() calls if_get_ipv6_global() which stores the first non-link-local IPv6 address found on the interface into peer->nexthop.v6_global. In bpacket_reformat_for_peer(), this value is used as the nexthop. The existing synthesis path (ipv4_to_ipv4_mapped_ipv6) only fires when mod_v6nhg is all-zeros, and the IS_MAPPED_IPV6 override only fires when v6_global is already IPv4-mapped. Neither triggers when v6_global contains a real global IPv6 address from the interface. This causes incorrect nexthops when the outgoing interface has both a global IPv6 address and an IPv4 address (e.g., a loopback with 2001:db8::1/128 and 172.32.0.13/32). The UPDATE is sent with the global IPv6 address instead of ::ffff:172.32.0.13, causing the receiver to fail recursive nexthop resolution in the IPv4 RIB. Fix this by always synthesizing the IPv4-mapped IPv6 nexthop from peer->nexthop.v4 when the peer connection is AF_INET, regardless of what v6_global contains. The existing fallback path for IPv6 peers is preserved as an else-if branch. Signed-off-by: Jia Chen <jchen1@paloaltonetworks.com>
1 parent 616d807 commit fbe0c00

1 file changed

Lines changed: 11 additions & 1 deletion

File tree

bgpd/bgp_updgrp_packet.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,17 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
527527
gnh_modified = 1;
528528
}
529529

530-
if (IN6_IS_ADDR_UNSPECIFIED(mod_v6nhg)) {
530+
/* IPv4 peer advertising IPv6 prefixes (RFC 5549):
531+
* always synthesize IPv4-mapped IPv6 nexthop from
532+
* the IPv4 address.
533+
*/
534+
if (peer->su_local &&
535+
peer->su_local->sa.sa_family == AF_INET &&
536+
peer->nexthop.v4.s_addr != INADDR_ANY) {
537+
ipv4_to_ipv4_mapped_ipv6(mod_v6nhg,
538+
peer->nexthop.v4);
539+
gnh_modified = 1;
540+
} else if (IN6_IS_ADDR_UNSPECIFIED(mod_v6nhg)) {
531541
if (peer->nexthop.v4.s_addr != INADDR_ANY) {
532542
ipv4_to_ipv4_mapped_ipv6(mod_v6nhg,
533543
peer->nexthop.v4);

0 commit comments

Comments
 (0)