summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2014-02-13 19:51:30 +0100
committerAndrew Bartlett <abartlet@samba.org>2014-03-25 00:45:28 +0100
commit8a6694707385fb1ccd7b38ff5643fdc278ba3400 (patch)
treeb768069753bbfcc2f020fac5ab658a5460ebe183
parentdbf37008e04ad999078aaf8eb2f13daece752fa1 (diff)
downloadsamba-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.c66
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;