aboutgitcodebugslistschat
path: root/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/parse.c b/parse.c
index ad21040..c8d3a9b 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
+}