IP address v4/v6 equivalence testing

2019-07-04 11:19发布

问题:

Is it possible to test IP addresses for equivalence in a dual stack environment using both IPv4 and IPv6? If so, how?

My application uses websocket++ on top of Boost ASIO.

As an example, on my LAN, one application connects to another listening on 192.168.1.2, but using this answer's IP address getter

std::string s = socket.remote_endpoint().address().to_string();

gives ::ffff:192.168.1.3 as the client's address.

The problem is that .2 will have its own node list with the original v4 address for .3, so by simple string comparison of the getter above vs a v4 version held on disk, it will seek a redundant connection to .3 even though already connected.

I've further read that things can get more complicated since by this dotted quad notation, ::ffff:192.0.2.128 is also ::ffff:c000:0280.

I am building a p2p application that accepts addresses from untrusted sources, so to prevent redundant connections, I need to be able to absolutely test for equivalence.

Can my intent be implemented? If so, how? If not, should I only use v4? I'd much rather include future capabilities now rather than worrying about integration later.

回答1:

I think you can just use the ip::tcp::address classes' operator==.

See it Live On Coliru

#include <boost/asio.hpp>

using boost::asio::ip::address;

address from_string_ip6(std::string const& ip)
{
    address a = address::from_string(ip);
    if (a.is_v4())
        return boost::asio::ip::address_v6::v4_mapped(a.to_v4());
    else
        return a;
}

int main()
{
    address a = from_string_ip6("192.0.2.111");
    address b = from_string_ip6("::ffff:192.0.2.111");
    address c = from_string_ip6("::ffff:c000:026f");

    assert(a == b);
    assert(a == c);
    assert(b == c);
}

Update If you want to include name-resolution: ipv4 and ipv6 from any valid address