diff options
Diffstat (limited to 'parse.c')
| -rw-r--r-- | parse.c | 91 |
1 files changed, 91 insertions, 0 deletions
@@ -16,9 +16,12 @@ #include <stddef.h> #include <stdlib.h> #include <string.h> +#include <limits.h> +#include <arpa/inet.h> #include "common.h" #include "parse.h" +#include "inany.h" /** * DOC: Theory of Operation @@ -111,3 +114,91 @@ bool parse_port_range(const char **cursor, struct port_range *range) *cursor = p; return true; } + +/** + * parse_ipv4() - Parse an IPv4 address from a string + * @abuf: On success, updated with parsed address + */ +bool parse_ipv4(const char **cursor, struct in_addr *abuf) +{ + /* Brackets are not typical on IPv4, but allow for consistency */ + const char *p = *cursor; + bool bracket = parse_literal(&p, "["); + char buf[INET_ADDRSTRLEN]; + struct in_addr addr; + size_t len; + + if (bracket) + len = strcspn(p, "]"); + else + len = strspn(p, "0123456789."); + + if (len >= sizeof(buf)) + return false; + memcpy(buf, p, len); + buf[len] = '\0'; + p += len; + + if (!inet_pton(AF_INET, buf, &addr)) + return false; + + if (bracket && !parse_literal(&p, "]")) + return false; + + *cursor = p; + *abuf = addr; + return true; +} + +/** + * parse_ipv6() - Parse an IPv6 address from a string + * @abuf: On success, updated with parsed address + */ +static bool parse_ipv6(const char **cursor, struct in6_addr *abuf) +{ + const char *p = *cursor; + bool bracket = parse_literal(&p, "["); + char buf[INET6_ADDRSTRLEN]; + struct in6_addr addr; + size_t len; + + if (bracket) + len = strcspn(p, "]"); + else + len = strspn(p, "0123456789aAbBcCdDeEfF:."); + + if (len >= sizeof(buf)) + return false; + memcpy(buf, p, len); + buf[len] = '\0'; + p += len; + + if (!inet_pton(AF_INET6, buf, &addr)) + return false; + + if (bracket && !parse_literal(&p, "]")) + return false; + + *cursor = p; + *abuf = addr; + return true; +} + +/** + * parse_inany() - Parse an IPv4 or IPv6 address from a string + * @addr: On success, updated with parsed address + */ +bool parse_inany(const char **cursor, union inany_addr *addr) +{ + struct in_addr a4; + + if (parse_ipv6(cursor, &addr->a6)) + return true; + + if (parse_ipv4(cursor, &a4)) { + *addr = inany_from_v4(a4); + return true; + } + + return false; +} |
