The Domain Name System (DNS) is a hierarchical, distributed global database, most commonly used for mapping hostnames to their respective IP addresses. It is defined in RFC 1034 and RFC 1035, and numerous updates thereof.
A domain name is a sequence of labels separated by the period character (.
). Each label can have a maximum of 63 characters, and a domain name can have a maximum of 255 characters.
The DNS is often described as a tree structure, with the "root zone" at the top, the Top Level Domains (TLDs) e.g. com
, uk
, etc below that, etc. Within a domain name the labels are shown in a "little endian" order with the leaf node label appearing left-most, and the TLD appearing right-most. If a trailing period appears after the TLD then the name is said to be a Fully Qualified Domain Name, where the trailing period represents the root zone itself.
The getaddrinfo()
function is the recommended POSIX function for interfacing with the system resolver. Depending on system configuration it will perform name lookups in the DNS, /etc/hosts
, mDNS, etc.
It is preferred over the deprecated gethostbyname()
family of functions because it supports both IPv4 and IPv6 addressing, and can also perform service name lookups at the same time (e.g. mapping http
to port 80)
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
...
struct addrinfo hints;
struct addrinfo *result;
int r;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; // allow IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // make a stream (TCP) connection
r = getaddrinfo(hostname, "http", &hints, &result);
if (r != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(r));
} else {
// iterate over the linked list
for (struct addrinfo *rp = result; rp != NULL; rp = rp->ai_next) {
// use rp fields to create a socket and connect to it
}
freeaddrinfo(result);
}