pobierz informacje o dodaniu

W programowaniu w języku C funkcje getaddrinfo() i getnameinfo() konwertują nazwy domen , nazwy hostów i adresy IP między czytelną dla człowieka reprezentacją tekstową a ustrukturyzowanym formatem binarnym dla sieciowego interfejsu API systemu operacyjnego . Obie funkcje są zawarte w standardowym interfejsie programowania aplikacji (API) POSIX .

getaddrinfo i getnameinfo są funkcjami odwrotnymi do siebie. Są niezależne od protokołów sieciowych i obsługują zarówno IPv4 , jak i IPv6 . Jest to zalecany interfejs do rozpoznawania nazw w aplikacjach niezależnych od protokołów oraz do przenoszenia starszego kodu IPv4 do Internetu IPv6.

Wewnętrznie funkcje wykonują rozwiązania przy użyciu systemu nazw domen (DNS), wywołując inne funkcje niższego poziomu, takie jak gethostbyname() .

16 lutego 2016 roku ogłoszono błąd bezpieczeństwa w implementacji getaddrinfo(() glibc , wykorzystujący technikę przepełnienia bufora , która może umożliwić atakującemu wykonanie dowolnego kodu.

informacje o adresie struktury

Struktura danych C używana do reprezentowania adresów i nazw hostów w interfejsie API sieci jest następująca:

struct addrinfo { int ai_flags; int ai_rodzina; int ai_socktype; int ai_protokół; socklen_t ai_addrlen; struct sockaddr* ai_addr; char* ai_canonname; /* nazwa kanoniczna */ struct addrinfo* ai_next; /* ta struktura może tworzyć połączoną listę */ };

W niektórych starszych systemach typem ai_addrlen jest size_t zamiast socklen_t . Większość funkcji gniazd, takich jak accept() i getpeername() , wymaga, aby parametr miał typ socklen_t * , a programiści często przekazują adres do elementu ai_addrlen struktury addrinfo . Jeśli typy są niekompatybilne, np. w 64-bitowym Solaris 9 , gdzie size_t wynosi 8 bajtów, a socklen_t wynosi 4 bajty, mogą wystąpić błędy w czasie wykonywania.

Struktura zawiera struktury ai_family i sockaddr z własnym polem sa_family . Są one ustawione na tę samą wartość, gdy struktura jest tworzona za pomocą funkcji getaddrinfo w niektórych implementacjach.

getaddrinfo()

getaddrinfo() konwertuje czytelne dla człowieka łańcuchy tekstowe reprezentujące nazwy hostów lub adresy IP na dynamicznie przydzielaną połączoną listę struktur struct addrinfo. Prototyp funkcji dla tej funkcji jest określony w następujący sposób:

int getaddrinfo(const char* nazwa hosta, const char* service, const struct addrinfo* podpowiedzi, struct addrinfo** res);
hostname
może być nazwą domeny, taką jak „example.com”, ciągiem adresu, takim jak „127.0.0.1” lub NULL, w którym to przypadku adres 0.0.0.0 lub 127.0.0.1 jest przypisywany w zależności od flag wskazówek .
service
może być numerem portu przekazanym jako ciąg znaków, na przykład „80”, lub nazwą usługi, np. „echo”. W tym drugim przypadku typowa implementacja używa funkcji getservbyname() do zapytania pliku /etc/services w celu rozwiązania usługi na numer portu.
wskazówki
mogą mieć wartość NULL lub strukturę addrinfo z typem żądanej usługi.
res
jest wskaźnikiem wskazującym na nową strukturę addrinfo z informacjami wymaganymi po pomyślnym zakończeniu funkcji. Funkcja zwraca 0 w przypadku sukcesu i niezerową wartość błędu, jeśli się nie powiedzie.

Chociaż implementacje różnią się w zależności od platformy, funkcja najpierw próbuje uzyskać numer portu, zwykle poprzez rozgałęzienie usługi . Jeśli wartość łańcucha jest liczbą, konwertuje ją na liczbę całkowitą i wywołuje funkcję htons() . Jeśli jest to nazwa usługi, taka jak www , usługa jest wyszukiwana za pomocą funkcji getservbyname() , używając protokołu pochodzącego z podpowiedzi->ai_socktype jako drugiego parametru tej funkcji. Następnie, jeśli nazwa hosta (nie NULL), wywołanie gethostbyname() rozwiązuje problem lub w inny sposób używany jest adres 0.0.0.0 , jeśli podpowiedzi->ai_flags są ustawione na AI_PASSIVE i 127.0.0.1 w przeciwnym razie. Przydziela nową addrinfo wypełnioną odpowiednim sockaddr_in w jednym z tych warunków, a także dodaje do niej port pobrany na początku. Wreszcie **res jest usuwany, aby wskazywał na nowo przydzieloną strukturę addrinfo . W niektórych implementacjach, takich jak wersja Unix dla Mac OS, tips->ai_protocol zastępuje wartość tips->ai_socktype, podczas gdy w innych jest odwrotnie, więc oba muszą być zdefiniowane z równoważnymi wartościami, aby kod działał na wielu platformy.

freeaddrinfo()

Ta funkcja zwalnia pamięć przydzieloną przez funkcję getaddrinfo() . Wynikiem tego ostatniego jest połączona lista struktur addrinfo zaczynających się od adresu ai , freeaddrinfo() przechodzi przez listę i zwalnia każdą z nich po kolei.

void freeaddrinfo(struct addrinfo *ai);

pobierz informacje o nazwie ()

Funkcja getnameinfo() konwertuje wewnętrzną binarną reprezentację adresu IP w postaci wskaźnika do struct sockaddr na łańcuchy tekstowe składające się z nazwy hosta lub, jeśli adres nie może być przekształcony w nazwę, tekstową reprezentację adresu IP, jak oraz nazwę lub numer portu serwisowego. Prototyp funkcji jest określony w następujący sposób:

int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags);

Przykład

Poniższy przykład wykorzystuje metodę getaddrinfo() do zamiany nazwy domeny www.example.com na jej listę adresów, a następnie wywołuje funkcję getnameinfo() dla każdego wyniku, aby zwrócić kanoniczną nazwę adresu. Ogólnie rzecz biorąc, daje to oryginalną nazwę hosta , chyba że konkretny adres ma wiele nazw, w którym to przypadku zwracana jest nazwa kanoniczna . W tym przykładzie nazwa domeny jest drukowana trzy razy, po jednym dla każdego z trzech uzyskanych wyników.

 #include <stdio.h> #include <stdlib.h> #include <netdb.h> #include <netinet/in.h> #include <sys/socket.h> #ifndef NI_MAXHOST #define NI_MAXHOST 1025 #endif int main (void) { struct addrinfo* wynik; struct informacje o adresie* res;  w terrorze;  /* przekształca nazwę domeny w listę adresów */   error = getaddrinfo("www.example.com", NULL, NULL, &result);  if (błąd!= 0) { if (błąd == EAI_SYSTEM) { perror("getaddrinfo"); } else { fprintf(stderr, "błąd w getaddrinfo: %s\n", gai_strerror(błąd));  } wyjdź(EXIT_FAILURE);  } /* przejrzyj wszystkie zwrócone wyniki i wykonaj wyszukiwanie odwrotne */ for (res = wynik; res != NULL; res = res->ai_next) { char nazwa_hosta[NI_MAXHOST];   error = getnameinfo(res->ai_addr, res->ai_addrlen, nazwa hosta, NI_MAXHOST, NULL, 0, 0);  if (błąd != 0) { fprintf(stderr, "błąd w getnameinfo: %s\n", gai_strerror(błąd)); Kontynuować;  } if (*nazwa hosta != '\0') printf("nazwa hosta: %s\n", nazwa hosta);  }   freeaddrinfo(wynik);  zwróć 0; }  

Zobacz też

Linki zewnętrzne