diff options
author | Jeremy Allison <jra@samba.org> | 2007-10-26 16:03:20 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2007-10-26 16:03:20 -0700 |
commit | a3f7db3d30ced566c8340696914f1be3293a9c5b (patch) | |
tree | 75c4646d53f0b7d79f74277cc073f1e683fa45df /source/lib | |
parent | 4b3635d6bc1bd5e4135ef208dff052e1d9b58a12 (diff) | |
download | samba-a3f7db3d30ced566c8340696914f1be3293a9c5b.tar.gz samba-a3f7db3d30ced566c8340696914f1be3293a9c5b.tar.xz samba-a3f7db3d30ced566c8340696914f1be3293a9c5b.zip |
Move the horrible hack for link local addresses out of namequery.c
and into util_sock.c. is_ipaddress() now copes with link:local:v6%ifname
addresses, as does interpret_string_addr().
Jeremy
Diffstat (limited to 'source/lib')
-rw-r--r-- | source/lib/util_sock.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c index 80d4af8cdb6..91da4074582 100644 --- a/source/lib/util_sock.c +++ b/source/lib/util_sock.c @@ -53,11 +53,27 @@ bool is_ipaddress(const char *str) int ret = -1; #if defined(HAVE_IPV6) - struct in6_addr dest6; + if (strchr_m(str, ':')) { + char addr[INET6_ADDRSTRLEN]; + struct in6_addr dest6; + const char *sp = str; + char *p = strchr_m(str, '%'); - ret = inet_pton(AF_INET6, str, &dest6); - if (ret > 0) { - return true; + /* + * Cope with link-local. + * This is IP:v6:addr%ifname. + */ + + if (p && (p > str) && (if_nametoindex(p+1) != 0)) { + strlcpy(addr, str, + MIN(PTR_DIFF(p,str)+1, + sizeof(addr))); + sp = addr; + } + ret = inet_pton(AF_INET6, addr, &dest6); + if (ret > 0) { + return true; + } } #endif return is_ipaddress_v4(str); @@ -200,7 +216,27 @@ bool interpret_string_addr(struct sockaddr_storage *pss, const char *str, int flags) { + char addr[INET6_ADDRSTRLEN]; struct addrinfo *res = NULL; +#if defined(HAVE_IPV6) + unsigned int scope_id = 0; + + if (strchr_m(str, ':')) { + char *p = strchr_m(str, '%'); + + /* + * Cope with link-local. + * This is IP:v6:addr%ifname. + */ + + if (p && (p > str) && ((scope_id = if_nametoindex(p+1)) != 0)) { + strlcpy(addr, str, + MIN(PTR_DIFF(p,str)+1, + sizeof(addr))); + str = addr; + } + } +#endif zero_addr(pss, AF_INET); @@ -212,6 +248,17 @@ bool interpret_string_addr(struct sockaddr_storage *pss, } /* Copy the first sockaddr. */ memcpy(pss, res->ai_addr, res->ai_addrlen); + +#if defined(HAVE_IPV6) + if (pss->ss_family == AF_INET6 && scope_id) { + struct sockaddr_in6 *ps6 = (struct sockaddr_in6 *)pss; + if (IN6_IS_ADDR_LINKLOCAL(&ps6->sin6_addr) && + ps6->sin6_scope_id == 0) { + ps6->sin6_scope_id = scope_id; + } + } +#endif + freeaddrinfo(res); return true; } |