diff options
Diffstat (limited to 'inany.c')
| -rw-r--r-- | inany.c | 50 |
1 files changed, 50 insertions, 0 deletions
@@ -11,6 +11,7 @@ #include <assert.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <errno.h> #include "util.h" #include "ip.h" @@ -79,3 +80,52 @@ int inany_pton(const char *src, union inany_addr *dst) return 0; } + +/** + * inany_prefix_pton() - Parse an IPv[46] address with prefix length + * @src: IPv[46] address and prefix length string in CIDR format + * @dst: Output buffer, filled with parsed address + * @prefix_len: Prefix length, to be filled in IPv6 format + * + * Return: 1 on success, 0 if no parseable address or prefix is found + */ +int inany_prefix_pton(const char *src, union inany_addr *dst, + uint8_t *prefix_len) +{ + char astr[INANY_ADDRSTRLEN] = { 0 }; + size_t alen = strcspn(src, "/"); + const char *pstr = &src[alen + 1]; + unsigned long plen; + char *end; + + if (alen >= INANY_ADDRSTRLEN) + return 0; + + if (src[alen] != '/') + return 0; + + strncpy(astr, src, alen); + + /* Read prefix length */ + errno = 0; + plen = strtoul(pstr, &end, 10); + if (errno || *end || plen > 128) + return 0; + + /* Read address */ + if (inet_pton(AF_INET6, astr, dst)) { + if (inany_v4(dst) && plen < 96) + return 0; + *prefix_len = plen; + return 1; + } + + if (inany_pton(astr, dst)) { + if (plen > 32) + return 0; + *prefix_len = plen + 96; + return 1; + } + + return 0; +} |
