inet_ntop возвращает частично неверный адрес IPv6 - PullRequest
1 голос
/ 12 февраля 2020

Мне известен этот аналогичный вопрос , но ответы не имеют смысла и, возможно, связаны с другой проблемой.

В моем приложении iOS я подключаюсь к серверу, используя CFSockets и wi sh, чтобы показать удаленный адрес сервера. При использовании IPv4 он работает, как и ожидалось, но есть странные результаты с IPv6, где сетевой префикс адреса правильный, но биты хоста совершенно разные.

int sock_fd = <...> // Assume I already have the fd
struct sockaddr addr;
socklen_t addr_len = sizeof(addr);
getpeername(sock_fd, &addr, &addr_len);
char addressString[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr, addressString, INET6_ADDRSTRLEN);

То, что я ожидал, было 2607:f2f8:a4c8::2, но я получаю адрес с правильным префиксом сети, но каждый раз с разными битами хоста, например:

               vvvvvvvvvvvvvvvvvvvv Random?
2607:f2f8:a4c8:0:c400:13b0:f6c5:afa
^^^^^^^^^^^^^^ Correct

1 Ответ

1 голос
/ 17 февраля 2020

Страница справочника getpeername(2) дает подсказку о том, почему это происходит:

Параметр address_len должен быть инициализирован, чтобы указать количество пространства, на которое указывает адрес. По возвращении он содержит фактический размер возвращаемого адреса (в байтах).

Адрес усекается, если предоставленный буфер слишком мал.

Размер struct sockaddr равен слишком мал для адресов IPv6 и приведет к усечению адреса.

Вам нужно использовать struct sockaddr_storage с getpeername, а не просто struct sockaddr

struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
getpeername(socket, (struct sockaddr *)&addr, &addr_len)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...