summaryrefslogtreecommitdiffstats
path: root/login-utils/login.c
diff options
context:
space:
mode:
authorKarel Zak2017-07-04 12:50:39 +0200
committerKarel Zak2017-07-04 13:03:08 +0200
commit1c8792f1ae7fa38cf1d4418ad99c207f65dfdb1a (patch)
treec93a7be7b2ac07c72aa9a9052d18b317888cab28 /login-utils/login.c
parentMerge branch 'path-fixes' of https://github.com/rudimeier/util-linux (diff)
downloadkernel-qcow2-util-linux-1c8792f1ae7fa38cf1d4418ad99c207f65dfdb1a.tar.gz
kernel-qcow2-util-linux-1c8792f1ae7fa38cf1d4418ad99c207f65dfdb1a.tar.xz
kernel-qcow2-util-linux-1c8792f1ae7fa38cf1d4418ad99c207f65dfdb1a.zip
login: use IPv4 on IPv4-mapping-to-IPv6
It seems that on some systems (e.g. RHEL7) the libc function getaddrinfo() is not able to translate ::ffff: address to IPv4. The result is 0.0.0.0 host address in the last(1) and utmpdump(1) output. /sbin/login -h "::ffff:192.168.1.7" utmpdump: [7] [03926] [1 ] [user1 ] [pts/1 ] [::ffff:192.168.1.7 ] [0.0.0.0 ] [Thu May 12 17:49:50 2016 ] Not sure if this is about order of the getaddrinfo() results, system configuration or libc version. It's irrelevant for login(1). We have to be robust enough to write usable address to log files everywhere. The solution is to detect IPv4-mapping-to-IPv6 and use IPv4 for utmp. Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1296233 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'login-utils/login.c')
-rw-r--r--login-utils/login.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/login-utils/login.c b/login-utils/login.c
index 64b41f4eb..9bc1bd9c4 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -1088,8 +1088,15 @@ static void init_remote_info(struct login_context *cxt, char *remotehost)
} else if (info->ai_family == AF_INET6) {
struct sockaddr_in6 *sa =
(struct sockaddr_in6 *) info->ai_addr;
+#ifdef IN6_IS_ADDR_V4MAPPED
+ if (IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr)) {
+ const uint8_t *bytes = sa->sin6_addr.s6_addr;
+ struct in_addr addr = { *(const in_addr_t *) (bytes + 12) };
- memcpy(cxt->hostaddress, &(sa->sin6_addr), sizeof(sa->sin6_addr));
+ memcpy(cxt->hostaddress, &addr, sizeof(struct in_addr));
+ } else
+#endif
+ memcpy(cxt->hostaddress, &(sa->sin6_addr), sizeof(sa->sin6_addr));
}
freeaddrinfo(info);
}