diff options
| author | Stefan Metzmacher <metze@samba.org> | 2014-02-13 19:51:30 +0100 |
|---|---|---|
| committer | Andrew Bartlett <abartlet@samba.org> | 2014-03-25 00:45:28 +0100 |
| commit | 8a6694707385fb1ccd7b38ff5643fdc278ba3400 (patch) | |
| tree | b768069753bbfcc2f020fac5ab658a5460ebe183 | |
| parent | dbf37008e04ad999078aaf8eb2f13daece752fa1 (diff) | |
| download | samba-8a6694707385fb1ccd7b38ff5643fdc278ba3400.tar.gz samba-8a6694707385fb1ccd7b38ff5643fdc278ba3400.tar.xz samba-8a6694707385fb1ccd7b38ff5643fdc278ba3400.zip | |
lib/util: let is_ipaddress_v6() cope with "fe80::1234%3"
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
| -rw-r--r-- | lib/util/util_net.c | 66 |
1 files changed, 54 insertions, 12 deletions
diff --git a/lib/util/util_net.c b/lib/util/util_net.c index 83afda4c78..d58855da5b 100644 --- a/lib/util/util_net.c +++ b/lib/util/util_net.c @@ -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; |
