}
/* 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
- * assumed.)
+ * CIDR prefix length. Stores the IP address into '*ip', netmask into '*mask',
+ * (255.255.255.255, if 's' lacks a netmask), and number of scanned characters
+ * into '*n'.
*
* Returns NULL if successful, otherwise an error message that the caller must
* free(). */
char * OVS_WARN_UNUSED_RESULT
-ip_parse_masked(const char *s, ovs_be32 *ip, ovs_be32 *mask)
+ip_parse_masked_len(const char *s, int *n, ovs_be32 *ip,
+ ovs_be32 *mask)
{
int prefix;
- int n;
- if (ovs_scan(s, IP_SCAN_FMT"/"IP_SCAN_FMT"%n",
- IP_SCAN_ARGS(ip), IP_SCAN_ARGS(mask), &n) && !s[n]) {
+ if (ovs_scan_len(s, n, IP_SCAN_FMT"/"IP_SCAN_FMT,
+ IP_SCAN_ARGS(ip), IP_SCAN_ARGS(mask))) {
/* OK. */
- } else if (ovs_scan(s, IP_SCAN_FMT"/%d%n", IP_SCAN_ARGS(ip), &prefix, &n)
- && !s[n]) {
+ } else if (ovs_scan_len(s, n, IP_SCAN_FMT"/%d",
+ IP_SCAN_ARGS(ip), &prefix)) {
if (prefix <= 0 || prefix > 32) {
return xasprintf("%s: network prefix bits not between 0 and "
"32", s);
}
*mask = be32_prefix_mask(prefix);
- } else if (ip_parse(s, ip)) {
+ } else if (ovs_scan_len(s, n, IP_SCAN_FMT, IP_SCAN_ARGS(ip))) {
*mask = OVS_BE32_MAX;
} else {
return xasprintf("%s: invalid IP address", s);
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'. */
+/* This function is similar to ip_parse_masked_len(), but doesn't return the
+ * number of scanned characters and expects 's' to end after the ip/(optional)
+ * mask.
+ *
+ * Returns NULL if successful, otherwise an error message that the caller must
+ * free(). */
char * OVS_WARN_UNUSED_RESULT
-ip_parse_cidr(const char *s, ovs_be32 *ip, unsigned int *plen)
+ip_parse_masked(const char *s, ovs_be32 *ip, ovs_be32 *mask)
+{
+ int n = 0;
+
+ char *error = ip_parse_masked_len(s, &n, ip, mask);
+ if (!error && s[n]) {
+ return xasprintf("%s: invalid IP address", s);
+ }
+ return error;
+}
+
+/* Similar to ip_parse_masked_len(), but the mask, if present, must be a CIDR
+ * mask and is returned as a prefix len in '*plen'. */
+char * OVS_WARN_UNUSED_RESULT
+ip_parse_cidr_len(const char *s, int *n, ovs_be32 *ip, unsigned int *plen)
{
ovs_be32 mask;
char *error;
- error = ip_parse_masked(s, ip, &mask);
+ error = ip_parse_masked_len(s, n, ip, &mask);
if (error) {
return error;
}
return NULL;
}
+/* Similar to ip_parse_cidr_len(), but doesn't return the number of scanned
+ * characters and expects 's' to be NULL terminated at the end of the
+ * ip/(optional) cidr. */
+char * OVS_WARN_UNUSED_RESULT
+ip_parse_cidr(const char *s, ovs_be32 *ip, unsigned int *plen)
+{
+ int n = 0;
+
+ char *error = ip_parse_cidr_len(s, &n, ip, plen);
+ if (!error && s[n]) {
+ return xasprintf("%s: invalid IP address", s);
+ }
+ return error;
+}
+
/* Parses string 's', which must be an IPv6 address. Stores the IPv6 address
* into '*ip'. Returns true if successful, otherwise false. */
bool
/* 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.)
+ * '*mask' (if 's' does not contain a netmask, all-one-bits is assumed), and
+ * number of scanned characters into '*n'.
*
* 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)
+ipv6_parse_masked_len(const char *s, int *n, 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 (ovs_scan_len(s, n, " "IPV6_SCAN_FMT, ipv6_s)
+ && ipv6_parse(ipv6_s, ip)) {
+ if (ovs_scan_len(s, n, "/%d", &prefix)) {
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)) {
+ } else if (ovs_scan_len(s, n, "/"IPV6_SCAN_FMT, ipv6_s)) {
+ if (!ipv6_parse(ipv6_s, mask)) {
+ return xasprintf("%s: Invalid IPv6 mask", s);
+ }
/* OK. */
} else {
- return xasprintf("%s: syntax error expecting IPv6 prefix length "
- "or mask", s);
+ /* OK. No mask. */
+ *mask = in6addr_exact;
}
return NULL;
}
return xasprintf("%s: invalid IPv6 address", s);
}
-/* Similar to ipv6_parse_masked(), but the mask, if present, must be a CIDR
+/* This function is similar to ipv6_parse_masked_len(), but doesn't return the
+ * number of scanned characters and expects 's' to end following the
+ * ipv6/(optional) mask. */
+char * OVS_WARN_UNUSED_RESULT
+ipv6_parse_masked(const char *s, struct in6_addr *ip, struct in6_addr *mask)
+{
+ int n = 0;
+
+ char *error = ipv6_parse_masked_len(s, &n, ip, mask);
+ if (!error && s[n]) {
+ return xasprintf("%s: invalid IPv6 address", s);
+ }
+ return error;
+}
+
+/* Similar to ipv6_parse_masked_len(), 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)
+ipv6_parse_cidr_len(const char *s, int *n, struct in6_addr *ip,
+ unsigned int *plen)
{
struct in6_addr mask;
char *error;
- error = ipv6_parse_masked(s, ip, &mask);
+ error = ipv6_parse_masked_len(s, n, ip, &mask);
if (error) {
return error;
}
return NULL;
}
+/* Similar to ipv6_parse_cidr_len(), but doesn't return the number of scanned
+ * characters and expects 's' to end after the ipv6/(optional) cidr. */
+char * OVS_WARN_UNUSED_RESULT
+ipv6_parse_cidr(const char *s, struct in6_addr *ip, unsigned int *plen)
+{
+ int n = 0;
+
+ char *error = ipv6_parse_cidr_len(s, &n, ip, plen);
+ if (!error && s[n]) {
+ return xasprintf("%s: invalid IPv6 address", s);
+ }
+ return error;
+}
+
/* Stores the string representation of the IPv6 address 'addr' into the
* character array 'addr_str', which must be at least INET6_ADDRSTRLEN
* bytes long. */