API DNS
gethostbyname() și gethostbyaddr()
Până de curând, pentru a afla un nume pe baza unei adrese IP și o adresă pe baza unui nume, se foloseau funcțiile gethostbyname() și gethostbyaddr(), împreună cu structura hostent. Între timp, acest API pentru DNS a fost scos din uz.
getaddrinfo()
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res);
Funcția getaddrinfo() primește informații despre numele unei gazde și al unui serviciu Internet, și returnează adresa sau adresele corespunzătoare. Parametrul node reprezintă numele simbolic (sub forma unui șir de caractere) al mașinii căreia vrem sa-i aflăm adresa (de exemplu, node poate fi “www.google.com”). Mai poate de asemenea fi reprezentat ca un șir care conține o adresă IPv4 sau IPv6.
Parametrul service specifică portul returnat în output, și poate fi pus pe NULL (caz în care portul din output rămâne neinițializat) sau poate fi dat ca un nume de serviciu (de exemplu, “http”) sau ca o valoare numerică (“80”).
Parametrul hints reprezintă criterii pentru filtrarea adreselor întoarse de apelul funcției getaddrinfo(). Este de tipul struct addrinfo, definit mai jos:
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;
struct addrinfo *ai_next;
};
În cazul în care se dorește filtrarea, se pot completa unul sau mai multe din următoarele câmpuri (restul punându-se pe 0):
- ai_family - se specifică familia de adrese pentru valorile returnate, putând fi setată ca AF_INET (pentru IPv4), AF_INET6 (pentru IPv6) sau AF_UNSPEC (pentru ambele)
- ai_socktype - se filtrează după tipul de socket (SOCK_DGRAM sau SOCK_STREAM, de exemplu)
- ai_protocol - se specifică protocolul setat în adresele returnate de funcția getaddrinfo()
- ai_flags - se pot seta o serie de flag-uri.
În final, rezultatul este pus în parametrul res, fiind reprezentat ca o listă înlănțuită de structuri de tipul addrinfo, care se parcurge prin intermediul câmpului ai_next. Din câmpul ai_addr al rezultatului, se pot citi informațiile despre adresa și portul stației gazdă căutate (prin cast la struct sockaddr_in, de exemplu).
În caz de succes, funcția întoarce 0, iar în caz de eroare întoarce o valoare negativă, care poate fi interpretată prin intermediul funcției gai_strerror():
const char *gai_strerror(int errcode);
Important
Parametrul res este alocat de către funcția getaddrinfo(), însă el trebuie dezalocat explicit de către utilizator prin intermediul funcției freeaddrinfo():
void freeaddrinfo(struct addrinfo *res);
Pentru a afișa adresa IP (v4 sau v6) corespunzătoare numelui simbolic din parametrul node, se poate utiliza funcția inet_ntop():
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
Primul parametrul specifică familia de protocoale (AF_INET sau AF_INET6), al doilea parametru reprezintă structura de adresă (adică, de exemplu, câmpurile sin_addr sau sin6_addr din structurile sockaddr_in pentru IPv4 sau sockaddr_in6 pentru IPv6), al treilea parametru reprezintă un șir de caractere unde va fi scrisă adresa sub formă de string, iar ultimul parametru reprezintă dimensiunea șirului de caractere în octeți. Valoarea de retur a funcției este un pointer la un șir de caractere identic cu cel din parametrul dst, sau NULL în caz de eroare.
getnameinfo()
#include <sys/socket.h>
#include <netdb.h>
int getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *host,
socklen_t hostlen, char *serv, socklen_t servlen, int flags);
Funcția getnameinfo() realizează operația inversă față de getaddrinfo(). Mai precis, primește o adresă și returnează numele simbolic și serviciul specifice adresei respective. Primii doi parametri reprezintă adresa IP (v4 sau v6) care este căutată. Se trimit structuri specifice protocolului dorit (sockaddr_in sau sockaddr_in6) și dimensiunea lor. Rezultatele apelului sunt puse în șirurile de caractere host și serv, care sunt alocate de către utilizator. Parametrii hostlen și servlen reprezintă dimensiunile celor două șiruri de caractere.
Funcția returnează 0 dacă s-a reușit cererea DNS, sau o valoare negativă interpretată cu gai_strerror() în caz contrar.