aboutgitcodebugslistschat
path: root/inany.c
diff options
context:
space:
mode:
Diffstat (limited to 'inany.c')
-rw-r--r--inany.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/inany.c b/inany.c
index 543b60d..2a586ed 100644
--- a/inany.c
+++ b/inany.c
@@ -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;
+}