mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
Merge e97232e85e
into 3dd4d417be
This commit is contained in:
commit
876197608f
43
lib/ipaddr.h
43
lib/ipaddr.h
|
@ -86,14 +86,6 @@ static inline int str2ipaddr(const char *str, struct ipaddr *ip)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static inline char *ipaddr2str(const struct ipaddr *ip, char *buf, int size)
|
||||
{
|
||||
buf[0] = '\0';
|
||||
if (ip)
|
||||
inet_ntop(ip->ipa_type, &ip->ip.addr, buf, size);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define IS_MAPPED_IPV6(A) \
|
||||
((A)->s6_addr32[0] == 0x00000000 \
|
||||
? ((A)->s6_addr32[1] == 0x00000000 \
|
||||
|
@ -127,6 +119,41 @@ static inline void ipv4_mapped_ipv6_to_ipv4(const struct in6_addr *in6,
|
|||
memcpy(in, (char *)in6 + 12, sizeof(struct in_addr));
|
||||
}
|
||||
|
||||
static inline char *ipaddr2str(const struct ipaddr *ip, char *buf, int size)
|
||||
{
|
||||
buf[0] = '\0';
|
||||
if (ip) {
|
||||
if (IS_IPADDR_V6(ip) && IN6_IS_ADDR_V4MAPPED(&ip->ipaddr_v6)) {
|
||||
/* Handle IPv4-mapped IPv6 addresses specially */
|
||||
struct in_addr ipv4;
|
||||
char ipv4str[INET_ADDRSTRLEN];
|
||||
|
||||
/*
|
||||
* Extract the IPv4 address from the mapped IPv6 address.
|
||||
* Per RFC 5952 section 5, it is RECOMMENDED to represent
|
||||
* IPv4-mapped IPv6 addresses using "mixed notation" with the
|
||||
* IPv4 part in dot-decimal format: ::ffff:192.0.2.1
|
||||
* instead of ::ffff:c000:0201
|
||||
*/
|
||||
ipv4_mapped_ipv6_to_ipv4(&ip->ipaddr_v6, &ipv4);
|
||||
|
||||
/* Format as IPv4-mapped IPv6 address (::ffff:a.b.c.d) */
|
||||
inet_ntop(AF_INET, &ipv4, ipv4str, sizeof(ipv4str));
|
||||
|
||||
/*
|
||||
* 1. Copy prefix (7 chars for "::ffff:")
|
||||
* 2. Append IPv4 address safely with strlcat
|
||||
*/
|
||||
snprintf(buf, size, "::ffff:");
|
||||
strlcat(buf, ipv4str, size);
|
||||
} else {
|
||||
/* Regular IP address formatting */
|
||||
inet_ntop(ipaddr_family(ip), &ip->ip.addr, buf, size);
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* generic ordering comparison between IP addresses
|
||||
*/
|
||||
|
|
107
lib/prefix.c
107
lib/prefix.c
|
@ -1075,36 +1075,81 @@ static const char *prefixevpn2str(const struct prefix_evpn *p, char *str,
|
|||
return str;
|
||||
}
|
||||
|
||||
/* Helper function to format the prefix length in the format /xx */
|
||||
static size_t format_prefixlen(char *buf, size_t l, int prefixlen, size_t buf_size)
|
||||
{
|
||||
int byte, tmp, a, b;
|
||||
bool z = false;
|
||||
|
||||
/*
|
||||
* Ensure buffer has enough space for the maximum prefix length case.
|
||||
* For IPv6 with prefix length 128, we need:
|
||||
* - 1 byte for '/'
|
||||
* - 1 byte for '1' (hundreds place)
|
||||
* - 1 byte for '2' (tens place)
|
||||
* - 1 byte for '8' (ones place)
|
||||
* - 1 byte for the null terminator
|
||||
* Total: 5 bytes from the current position
|
||||
*/
|
||||
if (l + 4 >= buf_size)
|
||||
return l;
|
||||
|
||||
buf[l++] = '/';
|
||||
byte = prefixlen;
|
||||
tmp = prefixlen - 100;
|
||||
if (tmp >= 0) {
|
||||
buf[l++] = '1';
|
||||
z = true;
|
||||
byte = tmp;
|
||||
}
|
||||
b = byte % 10;
|
||||
a = byte / 10;
|
||||
if (a || z)
|
||||
buf[l++] = '0' + a;
|
||||
buf[l++] = '0' + b;
|
||||
|
||||
buf[l] = '\0';
|
||||
return l;
|
||||
}
|
||||
|
||||
const char *prefix2str(union prefixconstptr pu, char *str, int size)
|
||||
{
|
||||
const struct prefix *p = pu.p;
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
int byte, tmp, a, b;
|
||||
bool z = false;
|
||||
size_t l;
|
||||
|
||||
switch (p->family) {
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf));
|
||||
l = strlen(buf);
|
||||
buf[l++] = '/';
|
||||
byte = p->prefixlen;
|
||||
tmp = p->prefixlen - 100;
|
||||
if (tmp >= 0) {
|
||||
buf[l++] = '1';
|
||||
z = true;
|
||||
byte = tmp;
|
||||
}
|
||||
b = byte % 10;
|
||||
a = byte / 10;
|
||||
if (a || z)
|
||||
buf[l++] = '0' + a;
|
||||
buf[l++] = '0' + b;
|
||||
buf[l] = '\0';
|
||||
format_prefixlen(buf, strlen(buf), p->prefixlen, sizeof(buf));
|
||||
strlcpy(str, buf, size);
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
/* Check if it's an IPv4-mapped IPv6 address */
|
||||
if (IN6_IS_ADDR_V4MAPPED(&p->u.prefix6)) {
|
||||
struct in_addr ipv4;
|
||||
char ipv4str[INET_ADDRSTRLEN];
|
||||
|
||||
ipv4_mapped_ipv6_to_ipv4(&p->u.prefix6, &ipv4);
|
||||
|
||||
/* Format as ::ffff:a.b.c.d/plen format */
|
||||
inet_ntop(AF_INET, &ipv4, ipv4str, sizeof(ipv4str));
|
||||
/*
|
||||
* 1. Copy prefix (7 chars for "::ffff:")
|
||||
* 2. Append IPv4 address safely with strlcat
|
||||
*/
|
||||
snprintf(buf, sizeof(buf), "::ffff:");
|
||||
strlcat(buf, ipv4str, sizeof(buf));
|
||||
format_prefixlen(buf, strlen(buf), p->prefixlen, sizeof(buf));
|
||||
strlcpy(str, buf, size);
|
||||
} else {
|
||||
/* Regular IPv6 address */
|
||||
inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf));
|
||||
format_prefixlen(buf, strlen(buf), p->prefixlen, sizeof(buf));
|
||||
strlcpy(str, buf, size);
|
||||
}
|
||||
break;
|
||||
|
||||
case AF_ETHERNET:
|
||||
snprintf(str, size, "%s/%d",
|
||||
prefix_mac2str(&p->u.prefix_eth, buf, sizeof(buf)),
|
||||
|
@ -1614,7 +1659,29 @@ static ssize_t printfrr_i6(struct fbuf *buf, struct printfrr_eargs *ea,
|
|||
if (use_star && !memcmp(ptr, &zero, sizeof(zero)))
|
||||
return bputch(buf, '*');
|
||||
|
||||
inet_ntop(AF_INET6, ptr, cbuf, sizeof(cbuf));
|
||||
/* Handle IPv4-mapped IPv6 addresses specially */
|
||||
const struct in6_addr *addr = ptr;
|
||||
|
||||
if (IN6_IS_ADDR_V4MAPPED(addr)) {
|
||||
struct in_addr ipv4;
|
||||
char ipv4str[INET_ADDRSTRLEN];
|
||||
|
||||
/* Extract the IPv4 address from the mapped IPv6 address */
|
||||
ipv4_mapped_ipv6_to_ipv4(addr, &ipv4);
|
||||
|
||||
/* Format as ::ffff:a.b.c.d */
|
||||
inet_ntop(AF_INET, &ipv4, ipv4str, sizeof(ipv4str));
|
||||
/*
|
||||
* 1. Copy prefix (7 chars for "::ffff:")
|
||||
* 2. Append IPv4 address safely with strlcat
|
||||
*/
|
||||
snprintf(cbuf, sizeof(cbuf), "::ffff:");
|
||||
strlcat(cbuf, ipv4str, sizeof(cbuf));
|
||||
} else {
|
||||
/* Regular IPv6 address formatting */
|
||||
inet_ntop(AF_INET6, ptr, cbuf, sizeof(cbuf));
|
||||
}
|
||||
|
||||
return bputs(buf, cbuf);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue