[PATCH] IPv6 question
Matthias Andree <[email protected]> Mon, 24 Aug 2015 23:59:00 +0200
| Newsgroups | gmane.network.leafnode |
|---|---|
| Message-ID | <[email protected]> |
The attached patch should fix the issue, but I cannot reproduce the original problem (not using CentOS 7, but Ubuntu 14.04) - I can't seem to get IPv4-mapped IPv6 addresses here through inetd nor xinetd 2.3.15 built from source.
0001-Fix-for-IPv4-mapped-IPv6-addresses-ffff-10.9.8.7.patch
(text/x-patch, 2.6 KB)
From 650fe949dff11c380a30a64582043b286a1a004a Mon Sep 17 00:00:00 2001 From: Matthias Andree <[email protected]> Date: Mon, 24 Aug 2015 23:48:28 +0200 Subject: [PATCH] Fix for IPv4-mapped IPv6 addresses (::ffff:10.9.8.7). --- NEWS | 2 ++ checkpeerlocal.c | 28 +++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 0bf17da..fcbfce6 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ - The roff manual page sources now render proper hyphens (-), minus characters (\-) and en-dashes (\[en]) depending on their context. This is so that copying-and-pasting from the manual page works properly. +- The code that checks if the peer is local now properly deals with IPv4 + mapped IPv6 addresses. ============================================================================== * 1.11.10, 2013-06-11 diff --git a/checkpeerlocal.c b/checkpeerlocal.c index 4417e24..36ec69a 100644 --- a/checkpeerlocal.c +++ b/checkpeerlocal.c @@ -159,6 +159,17 @@ static void pat(const struct sockaddr *addr) } #endif +/** extract IPv4 address from IPv6-mapped IPv4 address (::ffff:10.9.8.7) + */ +#if HAVE_IPV6 +static void extract_v6mappedv4(const struct sockaddr_in6 *i6, struct sockaddr_in *out) +{ + out->sin_family = AF_INET; + out->sin_port = i6->sin6_port; + memcpy(&out->sin_addr, &(i6->sin6_addr.s6_addr[12]), 4); +} +#endif + /** * check whether the peer of the socket is local to any of our network * interfaces, \return @@ -196,6 +207,15 @@ int checkpeerlocal(int sock) } #endif + if (IN6_IS_ADDR_V4MAPPED(&addr.sin6.sin6_addr)) { + /* map to IPv4 */ + struct sockaddr_in si; + D((printf("IPv4 mapped IPv6 address: "))); + extract_v6mappedv4(&addr.sin6, &si); + memcpy(&addr.sin, &si, sizeof(struct sockaddr_in)); + D(pat(&addr.sa)); + } + if (getifaddrs(&ifap) != 0) { D(printf("getifaddrs failed: %s\n", strerror(errno))); return -1; @@ -280,6 +300,10 @@ int checkpeerlocal(int sock) return -1; } +#ifdef TEST_LOCAL + memcpy(&addr, &tstaddr, sizeof(addr)); +#endif + type = addr.ss.ss_family; D(printf("address type of peer socket: %d\n", type)); @@ -315,9 +339,7 @@ int checkpeerlocal(int sock) /* map to IPv4 */ struct sockaddr_in si; D((printf("IPv4 mapped IPv6 address\n"))); - si.sin_family = AF_INET; - si.sin_port = i6->sin6_port; - memcpy(&si.sin_addr, &(i6->sin6_addr.s6_addr[12]), 4); + extract_v6mappedv4(i6, &si); memcpy(&addr.sin, &si, sizeof(struct sockaddr_in)); } else { return 0; -- 1.9.1