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;
"fe80::6af7:28ff:fefa:d137" , -1);
test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136",
"fe80:0000:0000:0000:6af7:28ff:fefa:d136" , 0);
+ test_sock_addr_cmp("::ffff:192.0.2.128", "192.0.2.128", 0);
return 0;
}