diff options
author | ume <ume@FreeBSD.org> | 2000-03-07 07:52:01 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2000-03-07 07:52:01 +0000 |
commit | 0fcca1988ee7566ebe8482e5e77f0810aafa07fd (patch) | |
tree | 265eb49c22806297f0229666165e347ee1861e79 /lib/libutil | |
parent | a45b12452c37704c7a020b7962bd1093e99e4aaf (diff) | |
download | FreeBSD-src-0fcca1988ee7566ebe8482e5e77f0810aafa07fd.zip FreeBSD-src-0fcca1988ee7566ebe8482e5e77f0810aafa07fd.tar.gz |
Since crypto/openssh/login.c was changed to use realhostname_sa(),
when connecting via IPv6, hostname was not recorded to utmp anymore.
Because, if hostname is longer than buffer size, getnameinfo() returns
with ENI_MEMORY.
Reviewed by: shin
Approved by: jkh
Diffstat (limited to 'lib/libutil')
-rw-r--r-- | lib/libutil/realhostname.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/lib/libutil/realhostname.c b/lib/libutil/realhostname.c index 2c9c5c5..20d4538 100644 --- a/lib/libutil/realhostname.c +++ b/lib/libutil/realhostname.c @@ -87,19 +87,21 @@ int realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen) { int result, error; + char buf[NI_MAXHOST]; result = HOSTNAME_INVALIDADDR; - error = getnameinfo(addr, addrlen, host, hsize, NULL, 0, 0); - if (error == NULL) { + error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, 0); + if (error == 0) { struct addrinfo hints, *res, *ores; struct sockaddr *sa; memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = + (addr->sa_family == AF_INET) ? AF_INET : AF_UNSPEC; hints.ai_flags = AI_CANONNAME; - error = getaddrinfo(host, NULL, &hints, &res); + error = getaddrinfo(buf, NULL, &hints, &res); if (error) { result = HOSTNAME_INVALIDNAME; goto numeric; @@ -122,13 +124,20 @@ realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen) port = ((struct sockinet *)addr)->si_port; ((struct sockinet *)addr)->si_port = 0; if (!memcmp(sa, addr, sa->sa_len)) { - if (res->ai_canonname != 0) - strncpy(host, - res->ai_canonname, - hsize); result = HOSTNAME_FOUND; ((struct sockinet *)addr)->si_port = port; + if (res->ai_canonname == 0) { + freeaddrinfo(ores); + goto numeric; + } + if (strlen(res->ai_canonname) > hsize && + addr->sa_family == AF_INET) { + freeaddrinfo(ores); + goto numeric; + } + strncpy(host, res->ai_canonname, + hsize); break; } ((struct sockinet *)addr)->si_port = port; @@ -148,11 +157,18 @@ realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen) if (IN6_IS_ADDR_V4MAPPED(in6) && !memcmp(&in6->s6_addr[12], in, sizeof(*in))) { - if (res->ai_canonname != 0) + result = HOSTNAME_FOUND; + if (res->ai_canonname == 0) { + freeaddrinfo(ores); + goto numeric; + } + if (strlen(res->ai_canonname) > hsize) + strncpy(host, inet_ntoa(*in), + hsize); + else strncpy(host, res->ai_canonname, hsize); - result = HOSTNAME_FOUND; break; } } @@ -161,9 +177,9 @@ realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen) freeaddrinfo(ores); } else { numeric: - getnameinfo(addr, addrlen, host, hsize, NULL, 0, - NI_NUMERICHOST|NI_WITHSCOPEID); - /* XXX: do 'error' check */ + if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, + NI_NUMERICHOST|NI_WITHSCOPEID) == 0) + strncpy(host, buf, hsize); } return result; |