summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-10-26 16:03:20 -0700
committerJeremy Allison <jra@samba.org>2007-10-26 16:03:20 -0700
commita3f7db3d30ced566c8340696914f1be3293a9c5b (patch)
tree75c4646d53f0b7d79f74277cc073f1e683fa45df
parent4b3635d6bc1bd5e4135ef208dff052e1d9b58a12 (diff)
downloadsamba-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
-rw-r--r--source/lib/util_sock.c55
-rw-r--r--source/libsmb/namequery.c26
2 files changed, 51 insertions, 30 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;
}
diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c
index 90e6be6a909..34fe09b8c29 100644
--- a/source/libsmb/namequery.c
+++ b/source/libsmb/namequery.c
@@ -1594,32 +1594,6 @@ bool resolve_name(const char *name,
char *sitename = NULL;
int count = 0;
-#if defined(HAVE_IPV6)
- unsigned int if_idx = 0;
- const char *p = strchr_m(name, '%');
-
- if (p && (if_idx = if_nametoindex(p+1)) != 0) {
- char *newname = SMB_STRDUP(name);
- if (!newname) {
- return false;
- }
- newname[PTR_DIFF(p,name)] = '\0';
- if (is_ipaddress(newname) &&
- interpret_string_addr(return_ss,
- newname, AI_NUMERICHOST)) {
- struct sockaddr_in6 *psa6 =
- (struct sockaddr_in6 *)&return_ss;
- if (psa6->sin6_scope_id == 0 &&
- IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) {
- psa6->sin6_scope_id = if_idx;
- }
- SAFE_FREE(newname);
- return true;
- }
- SAFE_FREE(newname);
- }
-#endif
-
if (is_ipaddress(name)) {
return interpret_string_addr(return_ss, name, AI_NUMERICHOST);
}