getaddrinfo - getaddrinfo

Te funkcje getaddrinfo () i getnameinfo () konwersji nazw domen , nazwy hostów i adresy IP pomiędzy reprezentacjami człowieka czytelnych formatach tekstowych i binarnych strukturyzowanych dla systemu operacyjnego „s sieci API. Obie funkcje są zawarte w POSIX standardowy interfejs programowania aplikacji (API).

getaddrinfo i getnameinfo są odwrotne funkcje siebie. Są one niezależne od protokołu sieciowego i obsługiwać zarówno IPv4 i IPv6 . Jest zalecany interfejs do rozpoznawania nazw w protokole budynek niezależnych aplikacji i przejście starszego kodu IPv4 do internetu IPv6.

Wewnętrznie, funkcje wykonywania uchwał za pomocą Domain Name System (DNS) przez wywołanie innego, niższego poziomu funkcji, takich jak gethostbyname () .

W dniu 16 lutego 2016 r bug bezpieczeństwa zostało ogłoszone w glibc realizacji getaddrinfo (), za pomocą przepełnienia bufora technikę, która może umożliwić wykonanie dowolnego kodu przez atakującego.

struct addrinfo

C Struktura Dane przedstawiające adresy i nazwami wewnątrz API sieci jest następujący:

struct addrinfo {
    int       ai_flags;
    int       ai_family;
    int       ai_socktype;
    int       ai_protocol;
    socklen_t ai_addrlen;
    struct    sockaddr* ai_addr;
    char*     ai_canonname;      /* canonical name */
    struct    addrinfo* ai_next; /* this struct can form a linked list */
};

W niektórych starszych systemów typu ai_addrlen jest size_t zamiast socklen_t . Większość funkcji, takich jak gniazdo accept () i getpeername () , wymaga parametru mieć typ socklen_t * i programiści często przekazać adres do ai_addrlen element addrinfo struktury. Jeśli typy są niezgodne, np w 64-bitowym Solaris 9 systemie, w którym size_t ma 8 bajtów i socklen_t wynosi 4 bajtów, a Błędy czasu może spowodować.

Struktura zawiera struktur ai_family i sockaddr z własnym sa_family dziedzinie. Są one ustawione na tę samą wartość, gdy struktura jest tworzony z funkcją getaddrinfo w niektórych implementacjach.

getaddrinfo ()

getaddrinfo () przekształca człowieka czytelnych ciągów tekstowych reprezentujących hostów lub adresów IP do dynamicznie przydzielonego połączonej listy struktur struct addrinfo. Prototypy funkcyjne dla tych funkcji są określone w następujący sposób:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int getaddrinfo(const char* hostname,
                const char* service,
                const struct addrinfo* hints,
                struct addrinfo** res);
hostname
może być albo nazwę domeny, takie jak „example.com”, ciąg adresu, takich jak „127.0.0.1”, lub NULL, w którym to przypadku adres 127.0.0.1 0.0.0.0 lub jest przypisany w zależności od flagi podpowiedzi.
usługa
może być numer portu przekazywany jako ciąg znaków, takich jak „80” lub nazwa usługi, np „echo”. W tym ostatnim przypadku typowa realizacja wykorzystuje getservbyname () do kwerendy pliku / etc / services rozwiązać usługi do numeru portu.
poradnik
może być NULL lub addrinfo struktura z rodzaju żądanej usługi.
res
Jest to wskaźnik, który wskazuje na nowej addrinfo struktury z informacjami wymaganymi po pomyślnym zakończeniu funkcji. Funkcja zwraca 0 po sukcesie i niezerowej wartości błędu, jeśli to się nie powiedzie.

Choć implementacje różnią się między platformami, funkcja najpierw spróbuje uzyskać numer portu, zwykle przez rozgałęzienia na służbie . Jeśli wartość ciąg jest liczbą, to zamienia go na liczbę całkowitą i wzywa htons () . Jeśli jest to nazwa usługi, takie jak www , usługa jest wyszukiwanie z getservbyname () , stosując protokół pochodzi z hints-> ai_socktype jako drugi parametr do tej funkcji. Następnie, jeśli nazwa hosta jest podany (NULL), wezwanie do gethostbyname () postanawia, lub inaczej adres 0.0.0.0 jest używany, jeśli hints-> ai_flags jest ustawiony na AI_PASSIVE i 127.0.0.1 inaczej. To przydzielony nowy addrinfo konstrukcję wypełnioną odpowiednią sockaddr_in w jednym z tych warunków, a także dodaje port pobierane na początku do niego. Wreszcie ** res parametr jest dereferencjonowane aby wskazywać na nowo przydzielonego addrinfo struktury. W niektórych implementacjach, takie jak wersja systemu Unix dla systemu Mac OS The hints-> ai_protocol nadpisuje hints-> ai_socktype wartości, podczas gdy w innych jest odwrotnie, więc oba muszą być zdefiniowane z równoważnymi wartościami kodu za pracę w obrębie wielu platformy.

getnameinfo ()

getnameinfo () konwertuje wewnętrzną binarną reprezentację adresu IP w postaci struct sockaddr wskaźnik do ciągów tekstowych składających się z nazwy hosta lub, jeśli adres nie może być rozwiązany w nazwie, reprezentacja adresu tekstowy IP, a także usługi nazwa portu lub numer. Prototyp funkcja jest określona w następujący sposób:

#include <sys/socket.h>
#include <netdb.h>

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

freeaddrinfo ()

Funkcja ta zwalnia pamięć przydzieloną przez getaddrinfo () funkcji. Jak wynika z tego ostatniego jest połączone lista addrinfo struktur freeaddrinfo () przechodzi poprzez liście i uwalnia jedną po drugiej.

#include <sys/socket.h>
#include <netdb.h>

void freeaddrinfo(struct addrinfo *ai);
  • ai jest głową listy addrinfo

Przykład

W poniższym przykładzie użyto getaddrinfo () , aby rozwiązać nazwę domeny www.example.com do swojej listy adresów, a następnie wywołuje getnameinfo () na każdego wyniku powrotu nazwę kanoniczną na adres. W ogóle, to tworzy oryginalną nazwę hosta , chyba że dany adres ma wiele nazw, w którym to przypadku kanoniczna jest zwracana nazwa. W tym przykładzie nazwa domeny zostanie wydrukowany trzy razy, raz dla każdej 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* result;
    struct addrinfo* res;
    int error;

    /* resolve the domain name into a list of addresses */
    error = getaddrinfo("www.example.com", NULL, NULL, &result);
    if (error != 0) {   
        if (error == EAI_SYSTEM) {
            perror("getaddrinfo");
        } else {
            fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
        }   
        exit(EXIT_FAILURE);
    }   

    /* loop over all returned results and do inverse lookup */
    for (res = result; res != NULL; res = res->ai_next) {   
        char hostname[NI_MAXHOST];
        error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0); 
        if (error != 0) {
            fprintf(stderr, "error in getnameinfo: %s\n", gai_strerror(error));
            continue;
        }
        if (*hostname != '\0')
            printf("hostname: %s\n", hostname);
    }   

    freeaddrinfo(result);
    return 0;
}

Zobacz też

Referencje

Linki zewnętrzne

  • RFC 3493 , Basic Gniazdo interfejsu Rozszerzenia dla IPv6