summaryrefslogtreecommitdiff
path: root/ctdb/common
diff options
context:
space:
mode:
authorMartin Schwenke <martin@meltin.net>2017-03-01 17:22:22 +1100
committerMartin Schwenke <martins@samba.org>2017-09-01 04:06:32 +0200
commit15c91774d943fba1985f33d10e24030264ce64c8 (patch)
tree800ce3b7f28aaa75be1c3f2c978bdaa075013673 /ctdb/common
parente78d2cbff2e30dbea4a7d05bab8f8a5fedfebd79 (diff)
downloadsamba-15c91774d943fba1985f33d10e24030264ce64c8.tar.gz
ctdb-common: Parse IPv4-mapped IPv6 addresses into IPv4 addresses
Tools like ctdb_killtcp can't route packets to IPv4-mapped IPv6 addresses so this works around that. Add a test case to confirm that this works. Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com> Autobuild-User(master): Martin Schwenke <martins@samba.org> Autobuild-Date(master): Fri Sep 1 04:06:32 CEST 2017 on sn-devel-144
Diffstat (limited to 'ctdb/common')
-rw-r--r--ctdb/common/system_util.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/ctdb/common/system_util.c b/ctdb/common/system_util.c
index 57452aa6a1a..96ea71dafaf 100644
--- a/ctdb/common/system_util.c
+++ b/ctdb/common/system_util.c
@@ -168,12 +168,35 @@ bool parse_ip(const char *addr, const char *ifaces, unsigned port, ctdb_sock_add
ZERO_STRUCTP(saddr); /* valgrind :-) */
- /* now is this a ipv4 or ipv6 address ?*/
- p = index(addr, ':');
+ /* IPv4 or IPv6 address?
+ *
+ * Use rindex() because we need the right-most ':' below for
+ * IPv4-mapped IPv6 addresses anyway...
+ */
+ p = rindex(addr, ':');
if (p == NULL) {
ret = parse_ipv4(addr, port, &saddr->ip);
} else {
+ uint8_t ipv4_mapped_prefix[12] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff
+ };
+
ret = parse_ipv6(addr, ifaces, port, saddr);
+ if (! ret) {
+ return ret;
+ }
+
+ /*
+ * Check for IPv4-mapped IPv6 address
+ * (e.g. ::ffff:192.0.2.128) - reparse as IPv4 if
+ * necessary
+ */
+ if (memcmp(&saddr->ip6.sin6_addr.s6_addr[0],
+ ipv4_mapped_prefix,
+ sizeof(ipv4_mapped_prefix)) == 0) {
+ /* Reparse as IPv4 */
+ ret = parse_ipv4(p+1, port, &saddr->ip);
+ }
}
return ret;