getaddrinfo - getaddrinfo
De funktioner getaddrinfo () og getnameinfo () konvertere domænenavne , værtsnavne og IP-adresser mellem læsbare tekst repræsentationer og strukturerede binære formater for operativsystemet ? S netværk API. Begge funktioner findes i POSIX standard applikationsprogrammeringsgrænseflade (API).
getaddrinfo og getnameinfo er inverse funktioner af hinanden. De er netværksprotokol agnostiske og understøtter både IPv4 og IPv6 . Det er den anbefalede grænseflade til navneopløsning i opbygning af protokolluafhængige applikationer og til overgang af ældre IPv4-kode til IPv6-internettet.
Internt udfører funktionerne opløsninger ved hjælp af Domain Name System (DNS) ved at kalde andre funktioner på lavere niveau, såsom gethostbyname () .
Den 16. februar 2016 blev en sikkerhedsfejl annonceret i glibc- implementeringen af getaddrinfo () ved hjælp af en bufferoverløbsteknik , der muliggør udførelse af vilkårlig kode af angriberen.
Indhold
struct addrinfo
Den C datastruktur til at repræsentere adresser og værtsnavne inden for netværk API er følgende:
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 */
};
I nogle ældre systemer typen af ai_addrlen er size_t stedet for socklen_t . De fleste socketfunktioner , såsom accept () og getpename () , kræver, at parameteren har typen socklen_t *, og programmerere videresender ofte adressen til ai_addrlen- elementet i addrinfo- strukturen. Hvis typerne er inkompatible, f.eks. På et 64-bit Solaris 9- system, hvor størrelse_t er 8 byte og socklen_t er 4 byte, kan der føre til fejl i kørsel.
Strukturen indeholder strukturer ai_family og sockaddr med sit eget sa_family felt. Disse er indstillet til den samme værdi, når strukturen oprettes med funktion getaddrinfo i nogle implementeringer.
getaddrinfo ()
getaddrinfo () konverterer human-læsbare tekststrenge, der repræsenterer værtsnavne eller IP-adresser, til en dynamisk allokeret sammenkoblet liste med strukt addrinfo strukturer. Funktionsprototyperne for disse funktioner er specificeret som følger:
#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);
- værtsnavn
- kan enten være et domænenavn, såsom "eksempel.com", en adressestreng, såsom "127.0.0.1", eller NULL, i hvilket tilfælde adressen 0.0.0.0 eller 127.0.0.1 tildeles afhængigt af antydningsflagene.
- service
- kan være et portnummer, der er bestået som streng, såsom "80", eller et servicenavn, f.eks. "ekko". I sidstnævnte tilfælde bruger en typisk implementering getervbyname () til at forespørge filen / etc / services for at løse tjenesten til et portnummer.
- Tips
- kan enten være NULL eller en addrinfo- struktur med den ønskede type service.
- res
- er en markør, der peger på en ny addrinfo- struktur med de ønskede oplysninger efter vellykket afslutning af funktionen. Funktionen returnerer 0 ved succes og fejlværdien uden nul, hvis den mislykkes.
Selvom implementeringer varierer mellem platforme, forsøger funktionen først at få et portnummer normalt ved forgrening på service . Hvis strengværdien er et tal, konverteres den til et heltal og kalder htons () . Hvis det er et servicenavn, såsom www , er tjenesten opslag med getervbyname () ved hjælp af protokollen fra hints-> ai_socktype som den anden parameter til denne funktion. Hvis der derefter gives værtsnavn (ikke NULL), løser et opkald til gethostbyname () det, eller på anden måde bruges adressen 0.0.0.0 , hvis tip-> ai_flags er indstillet til AI_PASSIVE , og 127.0.0.1 ellers. Den tildelte en ny addrinfo- struktur fyldt med den passende sockaddr_in under en af disse betingelser og tilføjer også den port, der blev hentet i begyndelsen, til den. Endelig frigøres ** res- parameteren for at få den til at pege på en nyligt tildelt addrinfo- struktur. I nogle implementeringer, såsom Unix-versionen til Mac OS, det tip-> ai_protocol tilsidesætter den tip-> ai_ socktype værdi, mens det i andre er det modsatte, så både skal defineres med tilsvarende værdier for koden til at være arbejde på tværs af flere platforme.
getnameinfo ()
getnameinfo () konverterer den interne binære repræsentation af en IP-adresse i form af en struktur sockaddr- pointer til tekststrenge, der består af værtsnavnet, eller, hvis adressen ikke kan løses til et navn, en tekstmæssig IP-adresserepræsentation såvel som tjenesten portnavn eller nummer. Funktionsprototypen er specificeret som følger:
#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 ()
Denne funktion frigør hukommelsen, der er tildelt af getaddrinfo () -funktionen. Da resultatet af sidstnævnte er en linket liste over addrinfo-strukturer, løber freeaddrinfo () igennem listen og frigør hver enkelt efter tur.
#include <sys/socket.h>
#include <netdb.h>
void freeaddrinfo(struct addrinfo *ai);
- ai er leder af addrinfo-listen
Eksempel
Følgende eksempel bruger getaddrinfo () til at løse domænenavnet www.example.com i sin liste over adresser og kalder derefter getnameinfo () på hvert resultat for at returnere det kanoniske navn på adressen. Generelt producerer dette det originale værtsnavn , medmindre den bestemte adresse har flere navne, i hvilket tilfælde det kanoniske navn returneres. I dette eksempel udskrives domænenavnet tre gange én gang for hvert af de tre opnåede resultater.
#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;
}
Se også
Referencer
eksterne links
- RFC 3493 , Basic Socket Interface Extensions til IPv6