mirror of
https://github.com/openvswitch/ovs
synced 2025-10-27 15:18:06 +00:00
packets: Add ipv6_parse_masked() function.
Signed-off-by: Justin Pettit <jpettit@ovn.org> Acked-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
@@ -570,6 +570,43 @@ ipv6_is_cidr(const struct in6_addr *netmask)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parses string 's', which must be an IPv6 address with an optional
|
||||||
|
* CIDR prefix length. Stores the IP address into '*ipv6' and the CIDR
|
||||||
|
* prefix in '*prefix'. (If 's' does not contain a CIDR length, all-ones
|
||||||
|
* is assumed.)
|
||||||
|
*
|
||||||
|
* Returns NULL if successful, otherwise an error message that the caller must
|
||||||
|
* free(). */
|
||||||
|
char * OVS_WARN_UNUSED_RESULT
|
||||||
|
ipv6_parse_masked(const char *s, struct in6_addr *ipv6, struct in6_addr *mask)
|
||||||
|
{
|
||||||
|
char ipv6_s[IPV6_SCAN_LEN + 1];
|
||||||
|
char mask_s[IPV6_SCAN_LEN + 1];
|
||||||
|
int prefix;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (ovs_scan(s, IPV6_SCAN_FMT"/"IPV6_SCAN_FMT"%n", ipv6_s, mask_s, &n)
|
||||||
|
&& inet_pton(AF_INET6, ipv6_s, ipv6) == 1
|
||||||
|
&& inet_pton(AF_INET6, mask_s, mask) == 1
|
||||||
|
&& !s[n]) {
|
||||||
|
/* OK. */
|
||||||
|
} else if (ovs_scan(s, IPV6_SCAN_FMT"/%d%n", ipv6_s, &prefix, &n)
|
||||||
|
&& inet_pton(AF_INET6, ipv6_s, ipv6) == 1
|
||||||
|
&& !s[n]) {
|
||||||
|
if (prefix <= 0 || prefix > 128) {
|
||||||
|
return xasprintf("%s: prefix bits not between 0 and 128", s);
|
||||||
|
}
|
||||||
|
*mask = ipv6_create_mask(prefix);
|
||||||
|
} else if (ovs_scan(s, IPV6_SCAN_FMT"%n", ipv6_s, &n)
|
||||||
|
&& inet_pton(AF_INET6, ipv6_s, ipv6) == 1
|
||||||
|
&& !s[n]) {
|
||||||
|
*mask = in6addr_exact;
|
||||||
|
} else {
|
||||||
|
return xasprintf("%s: invalid IP address", s);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst',
|
/* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst',
|
||||||
* 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated
|
* 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated
|
||||||
* in 'b' and returned. This payload may be populated with appropriate
|
* in 'b' and returned. This payload may be populated with appropriate
|
||||||
|
|||||||
@@ -959,6 +959,8 @@ struct in6_addr ipv6_addr_bitand(const struct in6_addr *src,
|
|||||||
struct in6_addr ipv6_create_mask(int mask);
|
struct in6_addr ipv6_create_mask(int mask);
|
||||||
int ipv6_count_cidr_bits(const struct in6_addr *netmask);
|
int ipv6_count_cidr_bits(const struct in6_addr *netmask);
|
||||||
bool ipv6_is_cidr(const struct in6_addr *netmask);
|
bool ipv6_is_cidr(const struct in6_addr *netmask);
|
||||||
|
char *ipv6_parse_masked(const char *s, struct in6_addr *ipv6,
|
||||||
|
struct in6_addr *mask);
|
||||||
|
|
||||||
void *eth_compose(struct dp_packet *, const struct eth_addr eth_dst,
|
void *eth_compose(struct dp_packet *, const struct eth_addr eth_dst,
|
||||||
const struct eth_addr eth_src, uint16_t eth_type,
|
const struct eth_addr eth_src, uint16_t eth_type,
|
||||||
|
|||||||
@@ -151,6 +151,28 @@ test_ipv6_masking(void)
|
|||||||
assert(ipv6_count_cidr_bits(&dest) == 128);
|
assert(ipv6_count_cidr_bits(&dest) == 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_ipv6_parsing(void)
|
||||||
|
{
|
||||||
|
struct in6_addr o_ipv6, p_ipv6;
|
||||||
|
struct in6_addr mask;
|
||||||
|
|
||||||
|
inet_pton(AF_INET6, "2001:db8:0:0:0:0:2:1", &o_ipv6);
|
||||||
|
|
||||||
|
ipv6_parse_masked("2001:db8:0:0:0:0:2:1/64", &p_ipv6, &mask);
|
||||||
|
assert(ipv6_addr_equals(&o_ipv6, &p_ipv6));
|
||||||
|
assert(ipv6_count_cidr_bits(&mask) == 64);
|
||||||
|
|
||||||
|
ipv6_parse_masked("2001:db8:0:0:0:0:2:1/ffff:ffff:ffff:ffff::",
|
||||||
|
&p_ipv6, &mask);
|
||||||
|
assert(ipv6_addr_equals(&o_ipv6, &p_ipv6));
|
||||||
|
assert(ipv6_count_cidr_bits(&mask) == 64);
|
||||||
|
|
||||||
|
ipv6_parse_masked("2001:db8:0:0:0:0:2:1", &p_ipv6, &mask);
|
||||||
|
assert(ipv6_addr_equals(&o_ipv6, &p_ipv6));
|
||||||
|
assert(ipv6_count_cidr_bits(&mask) == 128);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_packets_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
test_packets_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
||||||
{
|
{
|
||||||
@@ -158,6 +180,7 @@ test_packets_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
|||||||
test_ipv6_static_masks();
|
test_ipv6_static_masks();
|
||||||
test_ipv6_cidr();
|
test_ipv6_cidr();
|
||||||
test_ipv6_masking();
|
test_ipv6_masking();
|
||||||
|
test_ipv6_parsing();
|
||||||
}
|
}
|
||||||
|
|
||||||
OVSTEST_REGISTER("test-packets", test_packets_main);
|
OVSTEST_REGISTER("test-packets", test_packets_main);
|
||||||
|
|||||||
Reference in New Issue
Block a user