libs6dns
s6-dns
Software
skarnet.org

The s6dns_message library interface

The following functions are declared in the s6-dns/s6dns-message.h header, and implemented in the libs6dns.a or libs6dns.so library.

General information

s6dns_message provides functions to read and parse DNS messages sent by servers and caches and containing answers to queries.

Data structures

A s6dns_message_header_t is a structure containing the header of a received DNS packet, broken down for easy access to the bits.

A s6dns_message_rr_t is a structure containing the information about a resource record given by an answer packet - all of it, except the value of the answer itself, which is rtype-specific and has to be decoded by rtype-specific functions.

A s6dns_message_rr_func_t is the type of such a function. The prototype is
int f (s6dns_message_rr_t const *rr, char const *packet, unsigned int packetlen, unsigned int pos, unsigned int section, void *data)

Various structures designed to store specific resource record types are also provided. The list includes:

Functions

Header management

void s6dns_message_header_pack (char *s, s6dns_message_header_t const *h)
Packs the header *h into the 12 bytes pointed to by s.

void s6dns_message_header_unpack (char const *s, s6dns_message_header_t *h)
Unpacks the 12 bytes pointed to by s into the structure *h.

Low-level RR decoding

The following primitives are used in the implementation of s6dns_message_rr_func_t-typed functions, to read and decode information stored in a DNS packet. Their arguments are:

  1. A pointer to the structure where the information is going to be stored
  2. A read-only pointer to the beginning of the DNS packet
  3. The length of the DNS packet
  4. A pointer to an integer containing the current position in the DNS packet, i.e. where the information is going to be read. If the functions succeed, they automatically update the position so information can be read sequentially.

int s6dns_message_get_string (s6dns_domain_t *d, char const *packet, unsigned int packetlen, unsigned int *pos)
Reads a character-string and stores it into *d. Returns 1 on success and 0 on failure. Note that *d does not contain a domain, but the s6dns_domain_t structure is adapted to store strings that do not exceed 255 characters. d→s can be used to access the string, and d→len its length.

int s6dns_message_get_strings (char *s, unsigned int rdlength, char const *packet, unsigned int packetlen, unsigned int *pos
This function takes an additional parameter rdlength. It reads a series of character-strings and stores their concatenation into the string s, which must be preallocated; it can never store more than rdlength bytes. It returns -1 if it fails; on success, it returns the number of bytes written. The rdlength parameter must be the length of the resource record containing the series of character-strings.

size_t s6dns_message_get_domain_nodecode (char *out, size_t outmax, char const *packet, unsigned int packetlen, unsigned int *pos)
Reads a domain and stores it, in packet form, into *out, which is a character array that must have been preallocated by the user; outmax is the maximum number of characters that can be stored in out. As a special case, out can be NULL, in which case nothing will be written, but the domain will still be parsed and pos will still be updated. The function returns the number of characters written to out (or that would have been). If 0, it denotes a failure, and errno is set:

unsigned int s6dns_message_get_domain (s6dns_domain_t *d, char const *packet, unsigned int packetlen, unsigned int *pos)
Reads a domain and stores it, in string form, into *d. Returns 1 on success and 0 on failure, and sets errno just like the function above.

int s6dns_message_get_hinfo (s6dns_message_rr_hinfo_t *p, char const *packet, unsigned int packetlen, unsigned int *pos)
Reads a HINFO RR and stores it into *p. Returns 1 on success or 0 on failure.

int s6dns_message_get_mx (s6dns_message_rr_mx_t *p, char const *packet, unsigned int packetlen, unsigned int *pos)
Reads a MX RR and stores it into *p. Returns 1 on success or 0 on failure.

int s6dns_message_get_soa (s6dns_message_rr_soa_t *p, char const *packet, unsigned int packetlen, unsigned int *pos)
Reads a SOA RR and stores it into *p. Returns 1 on success or 0 on failure.

int s6dns_message_get_srv (s6dns_message_rr_srv_t *p, char const *packet, unsigned int packetlen, unsigned int *pos)
Reads a SRV RR and stores it into *p. Returns 1 on success or 0 on failure.

int s6dns_message_get_caa (s6dns_message_rr_caa_t *p, char const *packet, unsigned int packetlen, unsigned int *pos, uint16_t rdlength)
Reads a CAA RR and stores it into *p. Returns 1 on success or 0 on failure. rdlength is the length of the RDATA field of the record; this value is needed to properly parse a CAA record.

High-level RR-specific parsing functions

s6dns_message_func_t s6dns_message_parse_answer_strings
Parses character-strings located in the answer section of the packet. The data argument is interpreted as a pointer to a s6dns_mpag_t, which is a structure defined in the s6-dns/s6dns-message.h header and used to store multiple character-strings.

s6dns_message_func_t s6dns_message_parse_answer_domain
Parses domains located in the answer section of the packet. The data argument is interpreted as a pointer to a s6dns_dpag_t, which is a structure defined in the s6-dns/s6dns-message.h header and used to store multiple domains.

s6dns_message_func_t s6dns_message_parse_answer_a
Parses A RRs located in the answer section of the packet. The data argument is interpreted as a pointer to a stralloc, and 4 bytes are appended to this stralloc for every IPv4 address found.

s6dns_message_func_t s6dns_message_parse_answer_aaaa
Parses AAAA RRs located in the answer section of the packet. The data argument is interpreted as a pointer to a stralloc, and 16 bytes are appended to this stralloc for every IPv6 address found.

s6dns_message_func_t s6dns_message_parse_answer_hinfo
Parses HINFO RRs located in the answer section of the packet. The data argument is interpreted as a pointer to a genalloc containing s6dns_message_rr_hinfo_t structures.

s6dns_message_func_t s6dns_message_parse_answer_mx
Parses MX RRs located in the answer section of the packet. The data argument is interpreted as a pointer to a genalloc containing s6dns_message_rr_mx_t structures.

s6dns_message_func_t s6dns_message_parse_answer_soa
Parses SOA RRs located in the answer section of the packet. The data argument is interpreted as a pointer to a genalloc containing s6dns_message_rr_soa_t structures.

s6dns_message_func_t s6dns_message_parse_answer_srv
Parses SRV RRs located in the answer section of the packet. The data argument is interpreted as a pointer to a genalloc containing s6dns_message_rr_srv_t structures.

s6dns_message_func_t s6dns_message_parse_answer_caa
Parses CAA RRs located in the answer section of the packet. The data argument is interpreted as a pointer to a genalloc containing s6dns_message_rr_caa_t structures.

High-level packet parsing

int s6dns_message_parse (s6dns_message_header_t *h, char const *packet, unsigned int packetlen, s6dns_message_rr_func_t *f, void *data)
This function parses the DNS packet packet of length packetlen. It stores the packet header into *h. Then, for every RR in the answer, authority or additional section of the packet, it calls f with the relevant parameters. data is the extra pointer given to f to store information. If the parsing succeeds, the function returns 2 if the packet contains an answer section and 1 if it does not. Otherwise, it returns -1 if there is a local error unrelated to the packet, or 0 if no appropriate answer can be decoded from the packet. errno then contains one of the following values: