[ovs-dev] [PATCH 03/14] packets: Add new functions for IPv4 and IPv6 address parsing.
Justin Pettit
jpettit at ovn.org
Thu Dec 10 00:05:46 UTC 2015
Acked-by: Justin Pettit <jpettit at ovn.org>
--Justin
> On Dec 8, 2015, at 5:08 PM, Ben Pfaff <blp at ovn.org> wrote:
>
> These will be used in an upcoming patch to reduce duplicated code.
>
> Signed-off-by: Ben Pfaff <blp at ovn.org>
> ---
> lib/packets.c | 132 ++++++++++++++++++++++++++++++++++++++++++----------------
> lib/packets.h | 7 ++++
> 2 files changed, 102 insertions(+), 37 deletions(-)
>
> diff --git a/lib/packets.c b/lib/packets.c
> index 0ad5073..309ec0c 100644
> --- a/lib/packets.c
> +++ b/lib/packets.c
> @@ -416,6 +416,14 @@ ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *s)
> }
> }
>
> +/* Parses string 's', which must be an IP address. Stores the IP address into
> + * '*ip'. Returns true if successful, otherwise false. */
> +bool
> +ip_parse(const char *s, ovs_be32 *ip)
> +{
> + return inet_pton(AF_INET, s, ip) == 1;
> +}
> +
> /* Parses string 's', which must be an IP address with an optional netmask or
> * CIDR prefix length. Stores the IP address into '*ip' and the netmask into
> * '*mask'. (If 's' does not contain a netmask, 255.255.255.255 is
> @@ -447,6 +455,93 @@ ip_parse_masked(const char *s, ovs_be32 *ip, ovs_be32 *mask)
> return NULL;
> }
>
> +/* Similar to ip_parse_masked(), but the mask, if present, must be a CIDR mask
> + * and is returned as a prefix length in '*plen'. */
> +char * OVS_WARN_UNUSED_RESULT
> +ip_parse_cidr(const char *s, ovs_be32 *ip, unsigned int *plen)
> +{
> + ovs_be32 mask;
> + char *error;
> +
> + error = ip_parse_masked(s, ip, &mask);
> + if (error) {
> + return error;
> + }
> +
> + if (!ip_is_cidr(mask)) {
> + return xasprintf("%s: CIDR network required", s);
> + }
> + *plen = ip_count_cidr_bits(mask);
> + return NULL;
> +}
> +
> +/* Parses string 's', which must be an IPv6 address. Stores the IPv6 address
> + * into '*ip'. Returns true if successful, otherwise false. */
> +bool
> +ipv6_parse(const char *s, struct in6_addr *ip)
> +{
> + return inet_pton(AF_INET6, s, ip) == 1;
> +}
> +
> +/* Parses string 's', which must be an IPv6 address with an optional netmask or
> + * CIDR prefix length. Stores the IPv6 address into '*ip' and the netmask into
> + * '*mask'. (If 's' does not contain a netmask, all-one-bits 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 *ip, struct in6_addr *mask)
> +{
> + char ipv6_s[IPV6_SCAN_LEN + 1];
> + int prefix;
> + int n;
> +
> + if (ovs_scan(s, IPV6_SCAN_FMT"%n", ipv6_s, &n) && ipv6_parse(ipv6_s, ip)) {
> + s += n;
> + if (!*s) {
> + *mask = in6addr_exact;
> + } else if (ovs_scan(s, "/%d%n", &prefix, &n) && !s[n]) {
> + if (prefix <= 0 || prefix > 128) {
> + return xasprintf("%s: IPv6 network 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)
> + && !s[n]
> + && ipv6_parse(ipv6_s, mask)) {
> + /* OK. */
> + } else {
> + return xasprintf("%s: syntax error expecting IPv6 prefix length "
> + "or mask", s);
> + }
> + return NULL;
> + }
> + return xasprintf("%s: invalid IPv6 address", s);
> +}
> +
> +/* Similar to ipv6_parse_masked(), but the mask, if present, must be a CIDR
> + * mask and is returned as a prefix length in '*plen'. */
> +char * OVS_WARN_UNUSED_RESULT
> +ipv6_parse_cidr(const char *s, struct in6_addr *ip, unsigned int *plen)
> +{
> + struct in6_addr mask;
> + char *error;
> +
> + error = ipv6_parse_masked(s, ip, &mask);
> + if (error) {
> + return error;
> + }
> +
> + if (!ipv6_is_cidr(&mask)) {
> + return xasprintf("%s: IPv6 CIDR network required", s);
> + }
> + *plen = ipv6_count_cidr_bits(&mask);
> + return NULL;
> +}
> +
> +/* Stores the string representation of the IPv6 address 'addr' into the
> + * character array 'addr_str', which must be at least INET6_ADDRSTRLEN
> + * bytes long. */
> void
> ipv6_format_addr(const struct in6_addr *addr, struct ds *s)
> {
> @@ -612,43 +707,6 @@ ipv6_is_cidr(const struct in6_addr *netmask)
> 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',
> * 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated
> * in 'b' and returned. This payload may be populated with appropriate
> diff --git a/lib/packets.h b/lib/packets.h
> index 1e0417a..eaa329f 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -581,8 +581,11 @@ ip_is_local_multicast(ovs_be32 ip)
> }
> int ip_count_cidr_bits(ovs_be32 netmask);
> void ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *);
> +bool ip_parse(const char *s, ovs_be32 *ip);
> char *ip_parse_masked(const char *s, ovs_be32 *ip, ovs_be32 *mask)
> OVS_WARN_UNUSED_RESULT;
> +char *ip_parse_cidr(const char *s, ovs_be32 *ip, unsigned int *plen)
> + OVS_WARN_UNUSED_RESULT;
>
> #define IP_VER(ip_ihl_ver) ((ip_ihl_ver) >> 4)
> #define IP_IHL(ip_ihl_ver) ((ip_ihl_ver) & 15)
> @@ -1011,8 +1014,12 @@ struct in6_addr ipv6_addr_bitand(const struct in6_addr *src,
> struct in6_addr ipv6_create_mask(int mask);
> int ipv6_count_cidr_bits(const struct in6_addr *netmask);
> bool ipv6_is_cidr(const struct in6_addr *netmask);
> +
> +bool ipv6_parse(const char *s, struct in6_addr *ip);
> char *ipv6_parse_masked(const char *s, struct in6_addr *ipv6,
> struct in6_addr *mask);
> +char *ipv6_parse_cidr(const char *s, struct in6_addr *ip, unsigned int *plen)
> + OVS_WARN_UNUSED_RESULT;
>
> void *eth_compose(struct dp_packet *, const struct eth_addr eth_dst,
> const struct eth_addr eth_src, uint16_t eth_type,
> --
> 2.1.3
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
More information about the dev
mailing list