getnameinfo(3) tłumaczenie adresu na nazwę w sposób niezależny od protokołu

SKŁADNIA

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

Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)):

getnameinfo(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

OPIS

Funkcja getnameinfo() jest odwrotnością funkcji getaddrinfo(3): tłumaczy, w sposób niezależny od protokołu, adres gniazda na odpowiadające mu nazwę komputera i usługi. Łączy w sobie funkcjonalność funkcji gethostbyaddr(3) oraz getservbyport(3), ale w przeciwieństwie do nich getnameinfo() jest bezpieczna dla wątków i pozwala programowi wyeliminować zależności od IPv4-kontra-IPv6.

Argument sa jest wskaźnikiem do ogólnej struktury adresu gniazda (typu sockaddr_in lub sockaddr_in6) o rozmiarze salen, która przechowuje wejściowy adres IP i numer portu. Argumenty host i port są wskaźnikami do zaalokowanych przez program wywołujący tę funkcję buforów (odpowiednio o rozmiarach hostlen i servlen), w których getnameinfo() umieści zakończone NULL-em łańcuchy znaków zawierające odpowiednio nazwę komputera i nazwy usług.

Funkcja wywołująca może określić, że nazwa komputera (lub nazwa serwisu) nie jest potrzebna, przez przekazanie wartości NULL w argumencie host (lub serv) albo przez podanie 0 w parametrze hostlen (lub servlen). Jednakże co najmniej jeden z podanych parametrów (nazwa komputera lub nazwa serwisu) musi być ustawiony.

Argument flags zmienia zachowanie getnameinfo() w następujący sposób:

NI_NAMEREQD
Jeśli ustawiono, to w razie nieznalezienia nazwy komputera zwracany jest błąd.
NI_DGRAM
Jeżeli ustawiono, to serwis jest oparty raczej na datagramach (UDP) niż na strumieniach (TCP). Jest to wymagane dla kilku portów (512-514), które mają przypisane inne serwisy dla UDP niż dla TCP.
NI_NOFQDN
Jeżeli ustawiono, to zwracana jest tylko lokalna część nazwy komputera, a nie jego pełną domenowa nazwa sieciowa.
NI_NUMERICHOST
Jeśli ustawiono, to nazwa komputera jest zwracana w formie numerycznej. (Może się to również zdarzyć wtedy, gdy nie ustawiono tej flagi i nie można znaleźć nazwy komputera).
NI_NUMERICSERV
Jeśli ustawiono, to nazwa komputera jest zwracana w formie numerycznej. (Może się to również zdarzyć wtedy, gdy nie ustawiono tej flagi i nie można znaleźć nazwy komputera).

Rozszerzenia getnameinfo() dotyczące międzynarodowych nazw domen

Począwszy do wersji 2.3.4 biblioteki glibc, getnameinfo() został rozszerzony i pozwala na przezroczystą konwersję nazw komputerów do i z formatu międzynarodowych nazw domenowych (Internationalized Domain Name --- IDN; patrz RFC 3490, Internationalizing Domain Names in Applications (IDNA)). Zostały zdefiniowane trzy nowe flagi:

NI_IDN
Jeśli użyto tego znacznika, to nazwa znaleziona przez proces wyszukiwania jest konwertowana z formatu IDN na kodowanie zgodne z bieżącymi ustawieniami językowymi. Nazwy składające się wyłącznie ze znaków ASCII nie są zmieniane, co pozwala na bezproblemowe używanie tego znacznika w istniejących programach i środowiskach.
NI_IDN_ALLOW_UNASSIGNED, NI_IDN_USE_STD3_ASCII_RULES
Ustawienie tych znaczników włączy odpowiednio znaczniki IDNA_ALLOW_UNASSIGNED (zezwala na używanie nieprzypisanych znaków Unikodu) i IDNA_USE_STD3_ASCII_RULES (upewnia się, że zwracana nazwa komputera jest zgodna ze standardem STD3), które będą używane podczas obsługi IDNA.

WARTOŚĆ ZWRACANA

W przypadku powodzenia zwracane jest 0, a nazwy komputera i usług, jeśli ich zażądano, są wypełniane łańcuchami znaków zakończonymi NULL-em. Nazwy te mogą zostać obcięte, tak aby zmieściły się w podanych długościach bufora. W razie błędu zwracany jest jeden z poniższych niezerowych kodów błędu:
EAI_AGAIN
Obecnie nie można znaleźć nazwy. Proszę spróbować później.
EAI_BADFLAGS
Argument flags ma niepoprawną wartość.
EAI_FAIL
Wystąpił błąd krytyczny.
EAI_FAMILY
Nieznana rodzina adresów lub długość adresu nie jest odpowiednia dla podanej rodziny.
EAI_MEMORY
Brak pamięci.
EAI_NONAME
Nie można rozwinąć nazwy dla podanych parametrów. Ustawiono NI_NAMEREQD, a nie można znaleźć nazwy komputera albo nie zażądano ani nazwy komputera, ani nazwy serwisu.
EAI_OVERFLOW
Bufor, na który wskazywał parametr host lub serv, był za mały.
EAI_SYSTEM
Wystąpił błąd systemowy. Numer błędu można znaleźć w zmiennej errno.

Funkcja gai_strerror(3) przekształca te kody błędów w komunikat zrozumiały dla człowieka, więc jest odpowiednia do raportowania błędów.

PLIKI

/etc/hosts
/etc/nsswitch.conf
/etc/resolv.conf

WERSJE

getnameinfo() jest dostarczane przez glibc od wersji 2.1.

ZGODNE Z

RFC 2553, POSIX.1-2001.

UWAGI

Aby pomóc programiście w wyborze odpowiedniego rozmiaru buforów, w <netdb.h> zdefiniowano stałe
#define NI_MAXHOST      1025
#define NI_MAXSERV      32

Od glibc 2.8 powyższe definicje są dostępne, jeśli zdefinowano jedno z następujących makr: _BSD_SOURCE, _SVID_SOURCE lub _GNU_SOURCE.

Pierwsza z nich jest stałą MAXDNAME zdefiniowaną w pliku nagłówkowym <arpa/nameser.h> z nowszych wersji BIND-a. Druga jest zgadywaniem opartym na liście serwisów w bieżącym RFC dotyczącym przypisanych numerów (Assigned Numbers RFC).

Przed glibc w wersji 2.2 argumenty hostlen i servlen były wprowadzane jako size_t.

PRZYKŁAD

Następujący kod próbuje pobrać numeryczną nazwę komputera i nazwę usługi dla podanego adresu gniazda. Proszę zauważyć, że nie ustawiono na sztywno żadnej rodziny adresów.

struct sockaddr *sa;    /* wejście */
socklen_t len;         /* wejście */
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
if (getnameinfo(sa, len, hbuf, sizeof(hbuf), sbuf,
            sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0)
    printf("komputer=%s, serwis=%s\n", hbuf, sbuf);

Następująca wersja sprawdza, czy adres gniazda ma odwrotne mapowanie adresu.

struct sockaddr *sa;    /* wejście */
socklen_t len;         /* wejście */
char hbuf[NI_MAXHOST];
if (getnameinfo(sa, len, hbuf, sizeof(hbuf),
            NULL, 0, NI_NAMEREQD))
    printf("nie można znaleźć nazwy komputera");
else
    printf("komputer=%s\n", hbuf);

Przykładowy program używający getnameinfo() można znaleźć w getaddrinfo(3).

O STRONIE

Angielska wersja tej strony pochodzi z wydania 3.71 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów, oraz najnowszą wersję oryginału można znaleźć pod adresem http://www.kernel.org/doc/man-pages/.

TŁUMACZENIE

Autorami polskiego tłumaczenia niniejszej strony podręcznika man są: Robert Luberda <[email protected]> i Michał Kułach <[email protected]>.

Polskie tłumaczenie jest częścią projektu manpages-pl; uwagi, pomoc, zgłaszanie błędów na stronie http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją 3.71 oryginału.