2010-05-18 4 views
4

Я позвонил getpeername на свой подключенный сокет и теперь имеет адрес IPv6 подключенного однорангового узла. Как узнать, является ли IP-адрес моего партнера локальным?Сравнение IPv6-адреса однорангового узла с localhost

Редактировать: Чтобы уточнить, я имею в виду конкретно localhost, как в IP-адресе петли.

+1

Вопрос неоднозначный. R Samuel Klatchko предположил, что вы имеете в виду «localhost» (:: 1) и Remy Lebeau - TeamB предположил, что вы имеете в виду «локальный хост» (все локальные адреса IPv6). Просьба уточнить. – bortzmeyer

ответ

3

Я думаю, это как посмотреть, является ли входящее соединение локального, если у вас есть пир в struct sockaddr_in6, полученный из getpeername как так:

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

Оттуда вы можете заполнить самостоятельно struct sockaddr_in6 с адресом LOCALHOST ::1 и сравнить память для равенства:

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"); 

Или вы можете создать массив байтов, которые соответствуют с адресом LOCALHOST:

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"); 

И следите за отображаемым локальным хостом IPv4, ::ffff:127.0.0.1. Возможно, вам придется это проверить.

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"); 
+0

Вы можете хочу рассмотреть возможность сравнения только первых 13 байтов для проверки локального хоста, подключенного к IPv4. (В Linux все равно - если вы пингоруете что-либо в сети 127.0.0.0/8, это рассматривается как «localhost».) RFC 3330 определяет весь диапазон как loopback: http://tools.ietf.org/html/rfc3330 – mpontillo

3

В IPv6 адрес обратной связи ::1.

На двоичном уровне, то есть 127 0, сопровождаемые один 1.

+0

Иногда это отображается как «0: 0: 0: 0: 0: 0: 0: 1' вместо сокращенной формы ':: 1'. – jschmier

+0

jschmier: правильный, но нет необходимости использовать текстовую форму, getpeername возвращает двоичный код, который недвусмыслен. – bortzmeyer

3

После исключения из адреса замыкания на себя, извлечь список местной машины текущих активных IP-адресов (машина может иметь несколько IP-адресов, возложенные на него для различные сети), а затем прокрутите список до тех пор, пока не найдете совпадение. Как вы на самом деле получаете этот список, зависит от используемой ОС. OS может иметь свои собственные API для этого (например, Windows имеет GetAdaptersInfo() и связанные функции), или вы можете попробовать использовать gethostname() с gethostbyname() или getaddrinfo().