diff --git a/src/sa/sa.c b/src/sa/sa.c index b2b20663e..2db3652c2 100644 --- a/src/sa/sa.c +++ b/src/sa/sa.c @@ -12,6 +12,9 @@ #include #endif #include +#include +#include +#include #include #include #include @@ -68,7 +71,11 @@ int sa_set(struct sa *sa, const struct pl *addr, uint16_t port) */ int sa_pton(const char *addr, struct sa *sa) { - if (!addr) + struct addrinfo *res, *res0 = NULL; + struct addrinfo hints; + int err = 0; + + if (!addr || !sa) return EINVAL; if (inet_pton(AF_INET, addr, &sa->u.in.sin_addr) > 0) { @@ -86,12 +93,31 @@ int sa_pton(const char *addr, struct sa *sa) sa->u.in6.sin6_family = AF_INET6; } } + else if (!strncmp(addr, "fe80:", 5) && strchr(addr, '%')) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_NUMERICHOST; + + if (getaddrinfo(addr, NULL, &hints, &res0)) + return EADDRNOTAVAIL; + + for (res = res0; res; res = res->ai_next) { + + err = sa_set_sa(sa, res->ai_addr); + if (err) + continue; + + break; + } + + freeaddrinfo(res0); + } #endif else { return EINVAL; } - return 0; + return err; }