summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2016-03-04 02:18:38 +0100
committerStefan Metzmacher <metze@samba.org>2016-03-10 06:52:26 +0100
commit771042a2387b596fff2ab59a1a68d75c6c27b2cc (patch)
treec3bf50ac0e77a147f8a705037df99216f2cc961b
parentf7116f0ad021dc3652f31f7d2a55612b6133eff8 (diff)
downloadsamba-771042a2387b596fff2ab59a1a68d75c6c27b2cc.tar.gz
lib/util_net: move ipv6 linklocal handling into interpret_string_addr_internal()
Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Günther Deschner <gd@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--lib/util/util_net.c95
1 files changed, 56 insertions, 39 deletions
diff --git a/lib/util/util_net.c b/lib/util/util_net.c
index d58855da5b2..f5fe323db2d 100644
--- a/lib/util/util_net.c
+++ b/lib/util/util_net.c
@@ -49,6 +49,10 @@ bool interpret_string_addr_internal(struct addrinfo **ppres,
{
int ret;
struct addrinfo hints;
+#if defined(HAVE_IPV6)
+ char addr[INET6_ADDRSTRLEN] = { 0, };
+ unsigned int scope_id = 0;
+#endif
ZERO_STRUCT(hints);
@@ -58,8 +62,60 @@ bool interpret_string_addr_internal(struct addrinfo **ppres,
/* always try as a numeric host first. This prevents unnecessary name
* lookups, and also ensures we accept IPv6 addresses */
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+
+#if defined(HAVE_IPV6)
+ 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)) {
+ /* Length of string we want to copy.
+ This is IP:v6:addr (removing the %ifname).
+ */
+ size_t len = PTR_DIFF(p,str);
+
+ if (len+1 > sizeof(addr)) {
+ /* string+nul too long for array. */
+ return false;
+ }
+ memcpy(addr, str, len);
+ addr[len] = '\0';
+
+ str = addr;
+ }
+ }
+#endif
+
ret = getaddrinfo(str, NULL, &hints, ppres);
if (ret == 0) {
+#if defined(HAVE_IPV6)
+ struct sockaddr_in6 *ps6 = NULL;
+
+ if (scope_id == 0) {
+ return true;
+ }
+ if (ppres == NULL) {
+ return true;
+ }
+ if ((*ppres) == NULL) {
+ return true;
+ }
+ if ((*ppres)->ai_addr->sa_family != AF_INET6) {
+ return true;
+ }
+
+ ps6 = (struct sockaddr_in6 *)(*ppres)->ai_addr;
+
+ if (IN6_IS_ADDR_LINKLOCAL(&ps6->sin6_addr) &&
+ ps6->sin6_scope_id == 0) {
+ ps6->sin6_scope_id = scope_id;
+ }
+#endif
+
return true;
}
@@ -94,35 +150,6 @@ static bool interpret_string_addr_pref(struct sockaddr_storage *pss,
{
struct addrinfo *res = NULL;
int int_flags;
-#if defined(HAVE_IPV6)
- char addr[INET6_ADDRSTRLEN];
- 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)) {
- /* Length of string we want to copy.
- This is IP:v6:addr (removing the %ifname).
- */
- size_t len = PTR_DIFF(p,str);
-
- if (len+1 > sizeof(addr)) {
- /* string+nul too long for array. */
- return false;
- }
- memcpy(addr, str, len);
- addr[len] = '\0';
-
- str = addr;
- }
- }
-#endif
zero_sockaddr(pss);
@@ -157,16 +184,6 @@ static bool interpret_string_addr_pref(struct sockaddr_storage *pss,
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;
}