getaddrinfo - getaddrinfo

As funções getaddrinfo () e getnameinfo () converter nomes de domínio , nomes de host e endereços IP entre as representações texto legível e formatos binários estruturados para o sistema operacional API de rede 's. Ambas as funções estão contidas no POSIX padrão aplicativo interface de programação (API).

getaddrinfo e getnameinfo são funções inversas uma da outra. Eles são protocolo de rede agnóstica, e apoiar tanto IPv4 e IPv6 . É a interface recomendada para a resolução de nomes em aplicações independentes de protocolo de construção e para a transição legado código de IPv4 para a Internet IPv6.

Internamente, as funções executam resoluções usando o Domain Name System (DNS), chamando outra, funções de nível inferior, como gethostbyname () .

Em 16 de fevereiro 2016, um bug de segurança foi anunciado no glibc implementação de getaddrinfo (), usando um buffer overflow técnica, que podem permitir a execução de código arbitrário pelo atacante.

addrinfo struct

O C estrutura de dados usada para representar os endereços e nomes de host dentro da API de rede é o seguinte:

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 */
};

Em alguns sistemas mais antigos do tipo de ai_addrlen é size_t em vez de socklen_t . A maioria das funções de soquete, como accept () e getpeername () , requerem o parâmetro de ter tipo socklen_t * e os programadores muitas vezes passar o endereço para o ai_addrlen elemento do addrinfo estrutura. Se os tipos de são incompatíveis, por exemplo, em um 64 bits Solaris 9 sistema onde size_t é de 8 bytes e socklen_t é de 4 bytes, em seguida, executar-tempo podem ocorrer erros.

A estrutura contém estruturas ai_family e sockaddr com seu próprio sa_family campo. Estes são definidos para o mesmo valor quando a estrutura é criada com função getaddrinfo em algumas implementações.

getaddrinfo ()

getaddrinfo () converte cadeias de texto legível que representam nomes de host ou endereços IP em um alocada dinamicamente lista ligada de estruturas struct addrinfo. Os protótipos de funções para estas funções são especificados como se segue:

#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);
nome de anfitrião
pode ser um nome de domínio, como "example.com", uma cadeia de endereço, como "127.0.0.1", ou NULL, caso em que o endereço 127.0.0.1 0.0.0.0 ou é atribuído de acordo com as bandeiras dicas.
serviço
pode ser um número de porta passado como cadeia, tais como "80", ou um nome de serviço, por exemplo, "eco". Neste último caso, uma implementação típica usa getservbyname () para consultar o arquivo / etc / services para resolver o serviço para um número de porta.
dicas
pode ser nulo ou um addrinfo estrutura com o tipo de serviço solicitado.
res
é um ponteiro que aponta para um novo addrinfo estrutura com a informação requerida após a conclusão bem sucedida da função. A função retorna 0 no sucesso e valor de erro diferente de zero se ele falhar.

Embora as implementações variar entre as plataformas, a primeira função de tentativas para obter um número de porta normalmente por ramificação em serviço . Se o valor da cadeia é um número, ele converte para um inteiro e chama htons () . Se é um nome de serviço, tais como www , o serviço é de pesquisa com getservbyname () , utilizando o protocolo derivado de hints-> ai_socktype como o segundo parâmetro para essa função. Então, se hostname é dado (não NULL), uma chamada para gethostbyname () resolve-lo, ou de outra forma o endereço 0.0.0.0 é usado, se hints-> ai_flags está definido para AI_PASSIVE , e 127.0.0.1 contrário. É atribuído um novo addrinfo estrutura preenchido com o apropriado sockaddr_in em uma dessas condições e também adiciona a porta recuperado no início a ele. Finalmente, o ** res parâmetro é referência para torná-lo apontar para um recém-alocado addrinfo estrutura. Em algumas implementações, tais como a versão Unix para o Mac OS, o hints-> ai_protocol substitui a hints-> ai_socktype valor, enquanto em outros é o oposto, de modo que ambos precisam ser definidos com valores equivalentes para o código para ser um trabalho através de várias plataformas.

getnameinfo ()

getnameinfo () converte a representação binária interna de um endereço IP na forma de um struct sockaddr ponteiro para cadeias de texto que consistem no nome ou, se o endereço não pode ser resolvido em um nome, uma representação endereço IP textual, bem como o serviço nome da porta ou número. O protótipo da função é especificado como segue:

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

Essa função libera a memória alocada pelo getaddrinfo () função. Como o resultado do último é uma lista ligada de estruturas addrinfo, freeaddrinfo () percorre a lista e liberta cada um por sua vez.

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

void freeaddrinfo(struct addrinfo *ai);
  • ai é o cabeça da lista addrinfo

Exemplo

O exemplo a seguir usa getaddrinfo () para resolver o nome de domínio www.example.com em sua lista de endereços e, em seguida, chama getnameinfo () em cada resultado para retornar o nome canônico para o endereço. Em geral, isso produz o original nome do host , a menos que o endereço particular tem vários nomes, caso em que o canônico nome é devolvido. Neste exemplo, o nome de domínio é impresso três vezes, uma vez para cada um dos três resultados obtidos.

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

Veja também

Referências

links externos

  • RFC 3493 , extensões de soquete básico interface para IPv6