tags:

views:

128

answers:

3

I have called getpeername on my connected socket and now have an IPv6 address of the connected peer. How do I tell whether my peer's IP address is localhost?

Edit: To clarify, I mean specifically localhost, as in the loopback IP address.

+3  A: 

In IPv6, the loopback address is ::1.

At the binary level, that is 127 0's followed by a single 1.

R Samuel Klatchko
It is sometimes displayed as `0:0:0:0:0:0:0:1` instead of the abbreviated form of `::1`.
jschmier
jschmier: correct but there is no need to use the text form, getpeername returns the binary one, which is unambiguous.
bortzmeyer
+3  A: 

After ruling out the loopback address, retreive the local machine's list of current active IPs (the machine may have multiple IPs assigned to it for different networks) and then loop through that list until you find a match. How you actually get that list depends on the OS you are using. The OS may have its own APIs for that (Windows has GetAdaptersInfo() and related functions, for instance), or you can try using gethostname() with gethostbyname() or getaddrinfo().

Remy Lebeau - TeamB
+1  A: 

I guess this is how to see whether the incoming connection is localhost, assuming you have the peer in a struct sockaddr_in6, obtained from getpeername like so:

    struct sockaddr_in6 peer;
    socklen_t len = sizeof(peer);
    getpeername( sock, (struct sockaddr *) &peer, &len); // todo: error check

From there, you can fill in your own struct sockaddr_in6 with the localhost address ::1 and compare the memory for equality:

    struct sockaddr_in6 localhost;
    memset(localhost.sin6_addr.s6_addr, 0, 16);
    localhost.sin6_addr.s6_addr[15] = 1;

    if( memcmp(peer.sin6_addr.s6_addr, localhost.sin6_addr.s6_addr, 16) == 0)
        printf("localhost!\n");

Or you can create an array of bytes that correspond with the localhost address:

    static const unsigned char localhost_bytes[] =
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };

    if( memcmp(peer.sin6_addr.s6_addr, localhost_bytes, 16) == 0)
        printf("localhost!\n");

And watch out for the mapped IPv4 localhost, ::ffff:127.0.0.1. You may have to check that, too.

    static const unsigned char mapped_ipv4_localhost[] =
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1 };

    if( memcmp(peer.sin6_addr.s6_addr, mapped_ipv4_localhost, 16) == 0)
        printf("mapped IPv4 localhost!\n");
indiv