getnameinfo - перевод адреса в имя не зависящим от протокола способом
getnameinfo(3)
перевод адреса в имя не зависящим от протокола способом
ОБЗОР
#include <sys/socket.h>
#include <netdb.h>
int getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, socklen_t hostlen,
char *serv, socklen_t servlen, int flags);
Требования макроса тестирования свойств для glibc
(см. feature_test_macros(7)):
getnameinfo(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE ||
_POSIX_SOURCE
ОПИСАНИЕ
Функция
getnameinfo() выполняет операцию, обратную
getaddrinfo(3); она
преобразует адрес сокета в соответствующие узел и службу, способом, который
не зависит от протокола. Она сочетает в себе действия функций
gethostbyaddr(3) и
getservbyport(3), но в отличии от этих функций
getnameinfo() реентерабельна и позволяет программам не зависеть от типа
IPv4 и IPv6.
Аргумент sa — это указатель на обобщённую структуру адреса сокета (типа
sockaddr_in или sockaddr_in6) размером salen, которая содержит
IP-адрес и номер порта. Аргументы host и serv указывают на выделенные
вызывающим буферы (размером hostlen и servlen, соответственно), в
которые getnameinfo() помещает строки (заканчивающееся null), содержащие
имя узла и службы, соответственно.
Вызывающий может указать, что имя узла (или службы) не требуется, указав в
аргументе host (или serv) NULL или в hostlen (или servlen)
значение 0. Однако, по крайней мере один параметр, имя узла или службы,
должно быть запрошено.
Аргумент flags меняет поведение функции getnameinfo() следующим
образом:
NI_NAMEREQD
Если этот флаг установлен, то возвращается ошибка, если имя машины не может
быть определено.
NI_DGRAM
Если этот флаг установлен, то сначала используется имя службы на основе
дейтаграмм (UDP), а не потоков (TCP). Это требуется для немногих портов
(512-514), которые имеют различные службы для UDP и TCP.
NI_NOFQDN
Если этот флаг установлен, то возвращается только часть имени машины от
полностью определённого доменного имени (FQDN) для локальных машин.
NI_NUMERICHOST
Если этот флаг установлен, то имя узла возвращается в числовой форме (если
этот флаг не установлен, то это также произойдёт в случае, когда имя узла
невозможно определить).
NI_NUMERICSERV
Если этот флаг установлен, тогда имя службы возвращается в числовой форме
(если этот флаг не установлен, то это также произойдёт в случае, когда имя
узла невозможно определить).
Расширения getnameinfo() для интернациональных доменных имён
Начиная с glibc 2.3.4, getnameinfo() была расширена для выборочного
прозрачного разрешения имён для формата интернациональных доменных имён
(IDN) (смотрите RFC 3490, Internationalizing Domain Names in Applications
(IDNA)). Было определено четыре новых флага:
NI_IDN
Если этот флаг установлен, то при необходимости искомое имя преобразуется из
формата IDN в кодировку локали. Имена из только ASCI-символов не меняются
при преобразовании, из-за чего данный флаг можно использовать в существующих
программах и средах.
NI_IDN_ALLOW_UNASSIGNED, NI_IDN_USE_STD3_ASCII_RULES
Установка этих флагов включает IDNA_ALLOW_UNASSIGNED (разрешать не
назначенные кодовые точки Юникода) и IDNA_USE_STD3_ASCII_RULES (проверять
вывод на соответствие имени узла STD3) соответственно для возможности работы
с IDNA.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается 0, а строки (оканчивающееся null) имени
узла и службы (если запрашивались) записываются в соответствующий буфер
заданной длины. При ошибке возвращается одно из следующих ненулевых значений
ошибки:
EAI_AGAIN
Имя не может быть определено в настоящий момент. Попробуйте повторить
попытку позже.
EAI_BADFLAGS
Параметр flags имеет неверное значение.
EAI_FAIL
Произошла неисправимая ошибка.
EAI_FAMILY
Не распознано семейство адресов, или для данного семейства была указана
неверно длина адреса.
EAI_MEMORY
Не хватает памяти.
EAI_NONAME
Имя не может быть определено для указанных параметров. Установлен флаг
NI_NAMEREQD и имя машины не может быть определено, или не было запрошено
не имя машины и не имя службы.
EAI_OVERFLOW
Размер буфера, на который указывает host или serv слишком мал.
EAI_SYSTEM
Произошла системная ошибка. Код системной ошибки можно найти в переменной
errno.
Функция gai_strerror(3) транслирует эти коды ошибок в читаемый формат,
подходящий для сообщений об ошибке.
ФАЙЛЫ
/etc/hosts
/etc/nsswitch.conf
/etc/resolv.conf
ВЕРСИИ
Функция
getnameinfo() появилась в glibc начиная с версии 2.1.
АТРИБУТЫ
Описание терминов данного раздела смотрите в
attributes(7).
Интерфейс Атрибут Значение
getnameinfo()
безвредность в потоках: безвредно (MT-Safe env locale)
СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, RFC 2553.
ЗАМЕЧАНИЯ
Чтобы помочь программисту выбрать нужный размер буферов в
<netdb.h> определены константы
#define NI_MAXHOST 1025
#define NI_MAXSERV 32
Начиная с glibc 2.8, эти определения доступны только, если определён один из
макросов тестирования свойств: _BSD_SOURCE, _SVID_SOURCE или
_GNU_SOURCE.
Первая — это константа MAXDNAME из новых версий заголовочного файла
<arpa/nameser.h> BIND. Последняя — вычислена на основе служб,
перечисленных в текущем RFC «Assigned Numbers».
В glibc до версии 2.2 аргументы hostlen и servlen имели тип size_t.
ПРИМЕР
Следующий код пытается получить имя машины и службы в числовой форме для
указанного адреса сокета. Обратите внимание, что здесь нет прямых упоминаний
определённого семейства адресов.
struct sockaddr *sa; /* входные */
socklen_t len; /* входные */
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
if (getnameinfo(sa, len, hbuf, sizeof(hbuf), sbuf,
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0)
printf("host=%s, serv=%s\n", hbuf, sbuf);
Следующая версия проверяет, имеет ли адрес сокета обратное отображение
адреса.
struct sockaddr *sa; /* входные */
socklen_t len; /* входные */
char hbuf[NI_MAXHOST];
if (getnameinfo(sa, len, hbuf, sizeof(hbuf),
NULL, 0, NI_NAMEREQD))
printf("не удалось получить имя узла");
else
printf("host=%s\n", hbuf);
Пример программы, использующей getnameinfo(), можно найти в
getaddrinfo(3).