1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00

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>
This commit is contained in:
Stefan Metzmacher 2016-03-04 02:18:38 +01:00
parent f7116f0ad0
commit 771042a238

View File

@ -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;
}