lib/util: let is_ipaddress_v6() cope with "fe80::1234%3"
authorStefan Metzmacher <metze@samba.org>
Thu, 13 Feb 2014 18:51:30 +0000 (19:51 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 24 Mar 2014 23:45:28 +0000 (00:45 +0100)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
lib/util/util_net.c

index 83afda4c78e95a060c93bf3233f982c00bf720c4..d58855da5b2b99afc6082ef5ce8960e43b486dc6 100644 (file)
@@ -330,28 +330,70 @@ bool is_ipaddress_v6(const char *str)
        int ret = -1;
 
        if (strchr_m(str, ':')) {
-               char addr[INET6_ADDRSTRLEN];
-               struct in6_addr dest6;
-               const char *sp = str;
+               char buf[INET6_ADDRSTRLEN] = { 0, };
+               size_t len;
+               const char *addr = str;
+               const char *idxs = NULL;
+               unsigned int idx = 0;
+               struct in6_addr ip6;
                char *p = strchr_m(str, '%');
 
+               if (p && (p > str)) {
+                       len = PTR_DIFF(p, str);
+                       idxs = p + 1;
+               } else {
+                       len = strlen(str);
+               }
+
+               if (len >= sizeof(buf)) {
+                       return false;
+               }
+               if (idxs != NULL) {
+                       strncpy(buf, str, len);
+                       addr = buf;
+               }
+
+               /*
+                * Cope with link-local.
+                * This is IP:v6:addr%ifidx.
+                */
+               if (idxs != NULL) {
+                       char c;
+
+                       ret = sscanf(idxs, "%5u%c", &idx, &c);
+                       if (ret != 1) {
+                               idx = 0;
+                       }
+
+                       if (idx > 0 && idx < UINT16_MAX) {
+                               /* a valid index */
+                               idxs = NULL;
+                       }
+               }
+
                /*
                 * Cope with link-local.
                 * This is IP:v6:addr%ifname.
                 */
+               if (idxs != NULL) {
+                       idx = if_nametoindex(idxs);
 
-               if (p && (p > str) && (if_nametoindex(p+1) != 0)) {
-                       size_t len = MIN(PTR_DIFF(p,str)+1, sizeof(addr));
-                       if (strlcpy(addr, str, len) >= len) {
-                               /* Truncate. */
-                               return false;
+                       if (idx > 0) {
+                               /* a valid index */
+                               idxs = NULL;
                        }
-                       sp = addr;
                }
-               ret = inet_pton(AF_INET6, sp, &dest6);
-               if (ret > 0) {
-                       return true;
+
+               if (idxs != NULL) {
+                       return false;
+               }
+
+               ret = inet_pton(AF_INET6, addr, &ip6);
+               if (ret <= 0) {
+                       return false;
                }
+
+               return true;
        }
 #endif
        return false;