When we converted isc_sockaddr_t to sockaddr_storage we also moved to
inet_net_pton(3). It turns out that was a mistake, at least it's not
portable for AF_INET6. Effectively revert that part and hand-roll it
using inet_pton(3).

OK?

p.s. it is kinda telling that isc, who introduced the API is (no
longer?) using it.

diff --git dighost.c dighost.c
index 2d2a52c86e2..2995b7e1602 100644
--- dighost.c
+++ dighost.c
@@ -935,10 +935,16 @@ parse_netprefix(struct sockaddr_storage **sap, int *plen, 
const char *value) {
        struct sockaddr_storage *sa = NULL;
        struct in_addr *in4;
        struct in6_addr *in6;
-       int prefix_length;
+       int prefix_length = -1, i;
+       char *sep;
+       char buf[INET6_ADDRSTRLEN + sizeof("/128")];
+       const char *errstr;
 
        REQUIRE(sap != NULL && *sap == NULL);
 
+       if (strlcpy(buf, value, sizeof(buf)) >= sizeof(buf))
+               fatal("invalid prefix '%s'\n", value);
+
        sa = calloc(1, sizeof(*sa));
        if (sa == NULL)
                fatal("out of memory");
@@ -952,14 +958,36 @@ parse_netprefix(struct sockaddr_storage **sap, int *plen, 
const char *value) {
                goto done;
        }
 
-       if ((prefix_length = inet_net_pton(AF_INET6, value, in6, sizeof(*in6)))
-           != -1) {
+       sep = strchr(buf, '/');
+       if (sep != NULL) {
+               *sep++ = '\0';
+               prefix_length = strtonum(sep, 0, 128, &errstr);
+               if (errstr != NULL)
+                       fatal("invalid address '%s'", value);
+       }
+
+       if (inet_pton(AF_INET6, buf, in6) == 1) {
                sa->ss_len = sizeof(struct sockaddr_in6);
                sa->ss_family = AF_INET6;
-       } else if ((prefix_length = inet_net_pton(AF_INET, value, in4,
-           sizeof(*in4))) != -1) {
+               if (prefix_length > 128 || prefix_length == -1)
+                       prefix_length = 128;
+       } else if (inet_pton(AF_INET, buf, in4) == 1) {
                sa->ss_len = sizeof(struct sockaddr_in);
                sa->ss_family = AF_INET;
+               if (prefix_length > 32 || prefix_length == -1)
+                       prefix_length = 32;
+       } else if (prefix_length != -1) {
+               if (prefix_length > 32)
+                       prefix_length = 32;
+               for (i = 0; i < 3 ; i++) {
+                       if (strlcat(buf, ".0", sizeof(buf)) > sizeof(buf))
+                               fatal("invalid address '%s'", value);
+                       if (inet_pton(AF_INET, buf, in4) == 1) {
+                               sa->ss_len = sizeof(struct sockaddr_in);
+                               sa->ss_family = AF_INET;
+                               goto done;
+                       }
+               }
        } else
                fatal("invalid address '%s'", value);
 


-- 
I'm not entirely sure you are real.

Reply via email to