Málokterá síťová aplikace pro IPv4 se asi obejde bez použití systému DNS a tím i funkce gethostbyname(). V kontextu IPv6 je ale tato funkce nepoužitelná. Každý uzel Internetu podporující IPv6 totiž bude mít kromě jedné nebo více adres IPv6 obvykle také adresu IPv4. Obě verze adres mohou být v DNS přiřazeny stejnému doménovému jménu - adresu IPv4 najdeme v záznamu typu A a adresu IPv6 v záznamu typu AAAA. Funkce gethostbyname() neumožňuje říci, který z obou typů záznamu chceme, popřípadě zda chceme oba. RFC 2553 proto zavedlo nové funkce getipnodebyname() a getipnodebyaddr() pro převod jména na adresu a obráceně. Bohužel i tyto funkce se ukázaly jako nedostatečné, neboť nepodporují dosahy adres //(address scopes)//. V novějších verzích API byly proto také zavrženy. Pro převod jména na adresu tak zbyla jediná, protokolově nezávislá funkce - getaddrinfo(), jež má svůj původ ve standardu IEEE POSIX 1003.1g. Kromě gethostbyname() plně nahrazuje i funkci getservbyname(). Prototyp vypadá takto: int *getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res); Funkce vrací buď nulu v případě úspěchu anebo různé chybové kódy. Skutečný výsledek je předán prostřednictvím argumentu ''res'', který je ukazatelem na jednosměrný seznam struktur typu ''addrinfo'' definovaného v //netdb.h//: struct addrinfo { int ai_flags; /* Input flags. */ int ai_family; /* Protocol family for socket. */ int ai_socktype; /* Socket type. */ int ai_protocol; /* Protocol for socket. */ socklen_t ai_addrlen; /* Length of socket address. */ struct sockaddr *ai_addr; /* Socket address for socket. */ char *ai_canonname; /* Canonical name. */ struct addrinfo *ai_next; /* Pointer to next in list. */ }; Položka ''ai_next'' ukazuje na následující prvek seznamu, poslední prvek seznamu pak zde má NULL. Paměť pro seznam musí být alokována dynamicky, a proto musíme (alespoň v C) pamatovat na řádné uvolnění této paměti po použití. K tomu slouží funkce freeaddrinfo(). Každý z prvků seznamu obsahuje položky, které můžeme přímo použít jako argumenty pro funkci socket(): ''ai_family'' (v našem případě ''PF_INET'' či ''PF_INET6'', ''ai_socktype'' (obvykle ''SOCK_STREAM'' nebo ''SOCK_DGRAM'') a ''ai_protocol'' (obvykle ''IPPROTO_TCP'' nebo ''SOCK_UDP''). Položka ''ai_addr'' pak ukazuje na adresu soketu, jejíž délku specifikuje položka ''ai_addrlen''. Argument ''nodename'' by měl obsahovat doménové jméno, o které nám jde, popřípadě obvyklý textový zápis adresy IPv4 nebo IPv6. Pokud chceme, můžeme vyplnit i argument ''servname'' a to buď jménem služby podle ///etc/services// anebo dekadickým číslem portu ve formě řetězce. Argument ''hints'' umožňuje stanovit, o jaký typ dat máme zájem. Jeho typem je opět ''struct addrinfo'', v níž ovšem smějí být vyplněny jen tyto položky: ''ai_flags'', ''ai_family'', ''ai_socktype'' a ''ai_protocol''. Ostatní položky musí být vynulovány. V případě, že v některé kategorii jsme připraveni přijmout cokoli, nastavíme hodnoty podle následující tabulky. Nemáme-li preference v žádné kategorii, stačí předat NULL na místě argumentu ''hints''. ^ **Kritérium**^ **Položka**^ **Nastavení** | | Libovolná adresová rodina| ''ai_family''| ''AF_UNSPEC'' | | Libovolný typ soketu| ''ai_socktype''| 0 | | Libovolný protokol| ''ai_protocol''| 0 | Položka ''ai_flags'' v argumentu ''hints'' hints obsahuje příznaky //(flags)//, kterými můžeme své požadavky specifikovat ještě detailněji. Jak je obvyklé, jednotlivé příznaky můžeme kombinovat pomocí operace bitového OR (''|''). K dispozici jsou tyto příznaky: ** ''AI_PASSIVE'' **\\ Tento příznak hraje roli jen v případě, že je na místě argumentu ''nodename'' předána hodnota NULL. Příznak nastavíme, pokud chceme výstup funkce getaddrinfo() použít pro funkci bind(), tj. na lokální straně soketu. Adresa soketu se v tom případě vyplní s ''INADDR_ANY'' pro IPv4 nebo ''IN6ADDR_ANY_INIT'' pro IPv6 (viz oddíl [[bsd_sockets_-_zakladni_funkce|Základní funkce]]). Pokud chceme výstup funkce getaddrinfo() použít pro vzdálenou stranu soketu, tedy např. ve funkcích connect() či sendto(), pak tento příznak nenastavíme. Dostaneme pak adresu soketu s ''INADDR_LOOPBACK'' pro IPv4 nebo ''IN6ADDR_LOOPBACK_INIT'' pro IPv6. ** ''AI_CANONNAME'' **\\ Nastavíme-li tento příznak a argument ''nodename'' není NULL, funkce getaddrinfo() se pokusí též vyhledat //kanonické doménové jméno// uzlu. To se hodí třeba tehdy, když známe DNS alias a chceme zjistit kanonické jméno. ** ''AI_NUMERICHOST'' **\\ Pokud je tento příznak nastaven, musí být argument ''nodename'' řetězcem reprezentujícím adresu IPv4 nebo IPv6. Funkce getaddrinfo() pak vůbec nepoužívá DNS. ** ''AI_NUMERICSERV'' **\\ Tento příznak nastavíme, pokud chceme jako argument ''servname'' použít řetězec s dekadickým číslem portu. ** ''AI_V4MAPPED'' **\\ Tento příznak má smysl jen pro ''AF_INET6'' v položce ''ai_family'' argumentu ''hints''. Pokud je nastaven a funkce getaddrinfo() nenalezne pro zadané ''nodename'' v DNS žádné záznamy typu AAAA, poskytne jako výsledek obsah záznamů typu A (pokud takové existují) ve formě IPv4-mapovaných adres IPv6 //(IPv4-mapped IPv6 addresses)//. ** ''AI_ALL'' **\\ Je-li tento příznak nastaven zároveň s ''AI_V4MAPPED'' a ''hints.ai_family'' je ''AF_INET6'', pak funkce getaddrinfo() vrátí adresové údaje ze //všech// záznamů DNS typu AAAA i A, přičemž posledně jmenované budou opět ve formě IPv4-mapovaných adres IPv6. V případě, že adresová rodina není specifikována, tj. ''hints.ai_family==AF_UNSPEC'' anebo ''hints==NULL'', bere se nastavení příznaků ''AI_V4MAPPED'' a ''AI_ALL'' v úvahu jen tehdy, je-li na hostitelském počítači podporováno IPv6. ** ''AI_ADDRCONFIG'' **\\ Nastavení tohoto příznaku vede k tomu, že funkce getaddrinfo() vrátí adresy IPv4 jen tehdy, je-li na hostitelském počítači zkonfigurována nějaká lokální adresa IPv4 a podobně vrátí adresy IPv6 jen tehdy, je-li zkonfigurována aspoň jedna lokální adresa IPv6 (v obou případech se nepočítá adresa zpětné smyčky). V jistém smyslu inverzní funkcí ke getaddrinfo() je tato funkce: int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags); Jejím úkolem je převod obsahu adresy soketu na doménové jméno uzlu a/nebo jméno služby. Návratová hodnota je opět buď nula v případě úspěchu nebo příslušný chybový kód. Struktura typu ''sockaddr'', na niž ukazuje argument ''sa'', může obsahovat adresu IPv6 s vnořenou adresou IPv4, tedy buď IPv4-mapovanou nebo IPv4-kompatibilní adresu. V takovém pádu se vnořená adresa IPv4 extrahuje a nadále se pokračuje tak, jako by byla předložena struktura s adresou IPv4. Výsledky převodu funkce getnameinfo zapisuje do bufferů, na které ukazují argumenty ''node'' a ''service''. Tyto buffery musí mít dopředu přidělenu paměť a argumenty ''nodelen'' a ''servicelen'' udávají jejich délku. Je-li některý z argumentů ''node'' a ''service'' předán jako nulový ukazatel, příslušná hodnota se nevrací. Poslední argument ''flags'' specifikuje následující příznaky, které mohou být opět kombinovány pomocí bitového OR: ** ''NI_NOFQDN'' **\\ Při nastavení tohoto příznaku se pro lokální uzel vrátí jen jeho samotné jméno, tedy bez domény. ** ''NI_NUMERICHOST'' **\\ Při jeho nastavení se do ''*node'' zapíše řetězec reprezentující numerickou adresu. Pokud je to adresa IPv6, může v ní být vyznačena i zóna adresy //(address scope)//, například ''"fe80::1%eth0"''. ** ''NI_NUMERICSCOPE'' **\\ Je-li nastaven tento příznak společně s předchozím, pak se zóna v textové reprezentaci adresy IPv6 zapíše jako číslo (např. index rozhraní) a nikoli symbolické jméno (např. ''eth0''). ** ''NI_NUMERICSERV'' **\\ Obdobně při nastavení tohoto příznaku se do ''*service'' zapíše řetězec s dekadickým číslem portu. ** ''NI_NAMEREQD'' **\\ Pokud je příznak nastaven a doménové jméno uzlu nemůže být nalezeno, vrátí funkce getnameinfo nenulový chybový kód. ** ''NI_DGRAM'' **\\ Nastavení tohoto příznaku naznačuje, že se jedná o nespojovanou službu (''SOCK_DGRAM''). Implicitně se předpokládá spojovaná služba (''SOCK_STREAM'').