diff --git a/src/login_nopam.c b/src/login_nopam.c index c6a6b41e..8ff06380 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include /* for inet_ntoa() */ @@ -68,6 +69,7 @@ /* Delimiters for fields and for lists of users, ttys or hosts. */ static char fs[] = ":"; /* field separator */ static char sep[] = ", \t"; /* list-element separator */ +static char inet_ntop_buffer[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; static bool list_match (char *list, const char *item, bool (*match_fn) (const char *, const char *)); static bool user_match (const char *tok, const char *string); @@ -263,18 +265,41 @@ static bool user_match (const char *tok, const char *string) static const char *resolve_hostname (const char *string) { - /* - * Resolve hostname to numeric IP address, as suggested - * by Dave Hagewood . --marekm - */ - struct hostent *hp; + int gai; + char *p; + struct addrinfo *addrs; + struct sockaddr *sa; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; - hp = gethostbyname (string); - if (NULL != hp) { - return inet_ntoa (*((struct in_addr *) *(hp->h_addr_list))); + gai = getaddrinfo(string, NULL, NULL, &addrs); + if (gai != 0) + goto notfound; + + sa = addrs[0].ai_addr; + switch (sa->sa_family) { + case AF_INET: + sin = (struct sockaddr_in *) sa; + inet_ntop(AF_INET, &sin->sin_addr, + inet_ntop_buffer, NITEMS(inet_ntop_buffer)); + p = inet_ntop_buffer; + break; + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + inet_ntop(AF_INET6, &sin6->sin6_addr, + inet_ntop_buffer, NITEMS(inet_ntop_buffer)); + p = inet_ntop_buffer; + break; + default: + SYSLOG ((LOG_ERR, "Hypothetical future IPv7?")); + abort(); } - SYSLOG ((LOG_ERR, "%s - unknown host", string)); + freeaddrinfo(addrs); + return p; + +notfound: + SYSLOG ((LOG_ERR, "getaddrinfo(%s): %s", string, gai_strerror(gai))); return string; }