return buffer;
}
+/*
+ * Parse decimal digits until we run out of decimal digits.
+ */
+static int ip_octet_from_str(char const *str, uint32_t *poctet)
+{
+ uint32_t octet;
+ char const *p = str;
+
+ if ((*p < '0') || (*p > '9')) {
+ return -1;
+ }
+
+ octet = 0;
+
+ while ((*p >= '0') && (*p <= '9')) {
+ octet *= 10;
+ octet += *p - '0';
+ p++;
+
+ if (octet > 255) return -1;
+ }
+
+
+ *poctet = octet;
+ return p - str;
+}
+
+static int ip_prefix_from_str(char const *str, uint32_t *paddr)
+{
+ int shift, length;
+ uint32_t octet;
+ uint32_t addr;
+ char const *p = str;
+
+ addr = 0;
+
+ for (shift = 24; shift >= 0; shift -= 8) {
+ length = ip_octet_from_str(p, &octet);
+ if (length <= 0) return -1;
+
+ addr |= octet << shift;
+ p += length;
+
+ /*
+ * EOS or / means we're done.
+ */
+ if (!*p || (*p == '/')) break;
+
+ /*
+ * We require dots between octets.
+ */
+ if (*p != '.') return -1;
+ p++;
+ }
+
+ *paddr = htonl(addr);
+ return p - str;
+}
+
+
/** Parse an IPv4 address or IPv4 prefix in presentation format (and others)
*
* @param out Where to write the ip address value.
int fr_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback)
{
char *p;
- unsigned int prefix;
+ unsigned int mask;
char *eptr;
/* Dotted quad + / + [0-9]{1,2} */
}
p = strchr(value, '/');
+
/*
* 192.0.2.2 is parsed as if it was /32
*/
*/
if ((value[0] == '*') && (value[1] == '\0')) {
out->ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
+
/*
* Convert things which are obviously integers to IP addresses
*
*/
} else if (is_integer(value) || ((value[0] == '0') && (value[1] == 'x'))) {
out->ipaddr.ip4addr.s_addr = htonl(strtoul(value, NULL, 0));
+
} else if (!resolve) {
if (inet_pton(AF_INET, value, &out->ipaddr.ip4addr.s_addr) <= 0) {
- fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
+ fr_strerror_printf("Failed to parse IPv4 addreess string \"%s\"", value);
return -1;
}
} else if (ip_hton(out, AF_INET, value, fallback) < 0) return -1;
return 0;
}
-
- /*
- * Otherwise parse the prefix
- */
- if ((size_t)(p - value) >= INET_ADDRSTRLEN) {
- fr_strerror_printf("Invalid IPv4 address string \"%s\"", value);
- return -1;
- }
-
+
/*
* Copy the IP portion into a temporary buffer if we haven't already.
*/
if (inlen < 0) memcpy(buffer, value, p - value);
buffer[p - value] = '\0';
- if (!resolve) {
- if (inet_pton(AF_INET, buffer, &out->ipaddr.ip4addr.s_addr) <= 0) {
- fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
- return -1;
- }
- } else if (ip_hton(out, AF_INET, buffer, fallback) < 0) return -1;
+ if (ip_prefix_from_str(buffer, &out->ipaddr.ip4addr.s_addr) <= 0) {
+ fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
+ return -1;
+ }
- prefix = strtoul(p + 1, &eptr, 10);
- if (prefix > 32) {
+ mask = strtoul(p + 1, &eptr, 10);
+ if (mask > 32) {
fr_strerror_printf("Invalid IPv4 mask length \"%s\". Should be between 0-32", p);
return -1;
}
+
if (eptr[0] != '\0') {
fr_strerror_printf("Failed to parse IPv4 address string \"%s\", "
"got garbage after mask length \"%s\"", value, eptr);
return -1;
}
- if (prefix < 32) {
- out->ipaddr.ip4addr = fr_inaddr_mask(&out->ipaddr.ip4addr, prefix);
+ if (mask < 32) {
+ out->ipaddr.ip4addr = fr_inaddr_mask(&out->ipaddr.ip4addr, mask);
}
- out->prefix = (uint8_t) prefix;
+ out->prefix = (uint8_t) mask;
out->af = AF_INET;
return 0;
attribute Framed-IP-Address = 127
data Framed-IP-Address = 0.0.0.127
+attribute Framed-IP-Address = 127.0
+data Framed-IP-Address = 127.0.0.0
+
attribute Framed-IPv6-Prefix = ::1
data Framed-IPv6-Prefix = ::1/128
attribute Framed-IPv6-Prefix = *
data Framed-IPv6-Prefix = ::/128
+attribute PMIP6-Home-IPv4-HoA = 127/8
+data PMIP6-Home-IPv4-HoA = 127.0.0.0/8
+
+attribute PMIP6-Home-IPv4-HoA = 127/8
+data PMIP6-Home-IPv4-HoA = 127.0.0.0/8
+
+#
+# Octets outside of the mask are OK, but
+# are mashed to zero.
+#
+attribute PMIP6-Home-IPv4-HoA = 127.63/8
+data PMIP6-Home-IPv4-HoA = 127.0.0.0/8
+
+#
+# Unless you give a good mask.
+#
+attribute PMIP6-Home-IPv4-HoA = 127.63/16
+data PMIP6-Home-IPv4-HoA = 127.63.0.0/16
+
+attribute PMIP6-Home-IPv4-HoA = 127.999/16
+data Failed to parse IPv4 address string "127.999/16"
+
+attribute PMIP6-Home-IPv4-HoA = 127.bob/16
+data Failed to parse IPv4 address string "127.bob/16"
+
+attribute PMIP6-Home-IPv4-HoA = 127.63/15
+data PMIP6-Home-IPv4-HoA = 127.62.0.0/15
+
+attribute PMIP6-Home-IPv4-HoA = 127.63.1/24
+data PMIP6-Home-IPv4-HoA = 127.63.1.0/24
+
+attribute PMIP6-Home-IPv4-HoA = 127.63.1.6
+data PMIP6-Home-IPv4-HoA = 127.63.1.6/32
+
+attribute PMIP6-Home-IPv4-HoA = 256/8
+data Failed to parse IPv4 address string "256/8"
+
+attribute PMIP6-Home-IPv4-HoA = bob/8
+data Failed to parse IPv4 address string "bob/8"
+
$INCLUDE tunnel.txt
$INCLUDE errors.txt
$INCLUDE extended.txt