udns(3) | Library Functions Manual | udns(3) |
udns - stub DNS resolver library
#include <udns.h> struct dns_ctx; struct dns_query; extern struct dns_ctx dns_defctx; struct dns_ctx *ctx; typedef void dns_query_fn(ctx, void *result, void *data); typedef int dns_parse_fn(const unsigned char *qnd,
const unsigned char *pkt,
const unsigned char *cur,
const unsigned char *end,
void **resultp); cc ... -ludns
The DNS library, udns, implements thread-safe stub DNS resolver functionality, which may be used both traditional, syncronous way and asyncronously, with application-supplied event loop.
While DNS works with both TCP and UDP, performing UDP query first and if the result does not fit in UDP buffer (512 bytes max for original DNS protocol), retrying the query over TCP, the library uses UDP only, but uses EDNS0 (RFC2671) extensions which allows larger UDP buffers.
The library uses single UDP socket to perform all operations even when asking multiple nameservers. This way, it is very simple to use the library in asyncronous event-loop applications: an application should add only single socket to the set of filedescriptors it monitors for I/O.
The library uses two main objects, resolver context of type struct dns_ctx, and query structure of type struct dns_query, both are opaque for an application. Resolver context holds global information about the resolver, such as list of nameservers to use, list of active requests and the like. Query objects holds information about a single DNS query in progress and are allocated/processed/freed by the library. Pointer to query structure may be treated as an identifier of an in-progress query and may be used to cancel the asyncronous query or to wait for it to complete.
Asyncronous interface works as follows. An application initializes resolver context, submits any number of queries for it using one of supplied dns_submit_XXX() routines (each return the query identifier as pointer to query structure), waits for input on the UDP socket used by the library, and gives some control to the library by calling dns_ioevent() and dns_timeouts() routines when appropriate. The library performs all necessary processing and executes application supplied callback routine when a query completes (either successefully or not), giving it the result if any, pointer to the resolver context (from which completion status may be obtained), and the data pointer supplied by an application when the query has been submitted. When submitting a query, an application requests how to handle the reply -- to either return raw DNS reply packet for its own low-level processing, or it may provide an address of parsing routine of type dns_parse_fn to perform conversion of on-wire format into easy to use data structure (the library provides parsing routines for several commonly used resource record types, as well as type-safe higher-level inteface that requests parsing automatically). The I/O monitoring and timeout handling may be either traditional select() or poll() based, or any callback-driven technique may be used.
Additionally, the library provides traditional syncronous interface, which may be intermixed with asyncronous calls (during syncronous query processing, other asyncronous queries for the same resolver context continued to be processed as usual). An application uses one of numerous dns_resolve_XXX() routines provided by the library to perform a query. As with asyncronous interface, an application may either request to return raw DNS packet or type-specific data structure by providing the parsing routine to handle the reply. Every routine from dns_resolve_XXX() series return pointer to result or NULL in case of any error. Query completion status (or length of the raw DNS packet) is available from the resolver context using dns_status() routine, the same way as for the asyncronous interface.
Internally, library uses on-wire format of domain names, referred to as DN format in this manual page. This is a series of domain labels whith preceeding length byte, terminated by zero-length label wich is integral part of the DN format. There are several routines provided to convert from traditional asciiz string to DN and back. Higher-level type-specific query interface hides the DN format from an application.
Every DNS Resource Record (RR) has a type and a class. The library defines several integer constants, DNS_C_XXX and DNS_T_XXX, to use as symbolic names for RR classes and types, such as DNS_C_IN for Internet class, DNS_T_A for IPv4 address record type and so on. See udns.h header file for complete list of all such constants.
The following constants are defined in udns.h header file:
Additionally, several constants are defined to simplify work with raw DNS packets, such as DNS response codes (DNS_R_XXX), DNS header layout (DNS_H_XXX) and others. Again, see udns.h for complete list. Library error codes (DNS_E_XXX) are described later in this manual page.
Resolver context, of type struct dns_ctx, is an object which is opaque to an application. Several routines provided by the library to initialize, copy and free resolver contexts. Most other high-level routines in this library expects a pointer to resolver context, ctx, as the first argument. There is a default resolver context available, named dns_defctx. When the context pointer ctx passed to a routine is NULL, dns_defctx is used. Several resolver contexts may be active at the same time, for example, when an application is multi-threaded and each thread uses resolver.
In order to use the library, an application should initialize and open one or more resolver context objects. These are two separate actions, performed by dns_init() (or dns_reset()), and dns_open(). Between the two calls, an application is free to pefrorm additional initialisation, such as setting custom nameservers, options or domain search lists. Optionally, in case no additional custom initialisation is required, dns_init() may open the context if do_open argument (see below) is non-zero.
When initializing resolver context, the library uses information from system file /etc/resolv.conf (see resolv.conf(5)), consults environment variables $LOCALDOMAIN, $NSCACHEIP, $NAMESERVERS and $RES_OPTIONS, and local host name to obtain list of local nameservers, domain name search list and various resolver options.
The following routines to initialize resolver context are available:
void dns_reset(ctx) int dns_init(ctx, int do_open)
struct dns_ctx *dns_new(struct dns_ctx *copy) void dns_free(ctx)
int dns_add_serv(ctx, const char *servaddr) int dns_add_serv_s(ctx, const struct sockaddr *sa) int dns_add_srch(ctx, const char *srch)
int dns_set_opts(ctx, const char *opts)
void dns_set_opt(ctx, int opt, val)
int dns_open(ctx) int dns_sock(const ctx) void dns_close(ctx)
int dns_active(const ctx)
int dns_status(const ctx)
void dns_ioevent(ctx, time_t now)
int dns_timeouts(ctx, int maxwait, time_t now)
typedef void dns_utm_fn(ctx, int timeout, void *data) void dns_set_tmcbck(ctx, dns_utm_fn *utmfn, void *data)
The data argument passed to the routine will be the same as passed to dns_set_tmcbck().
When a timer expires, an application should call dns_timeouts() routine (see below). Non-callback timer usage is provided too.
XXXX TODO: some more resolver context routines, like dns_set_dbgfn() etc.
There are two ways to perform DNS queries: traditional syncronous way, when udns performs all the necessary processing and return control to the application only when the query completes, and asyncronous way, when an application submits one or more queries to the library using given resolver context, and waits for completion by monitoring filedescriptor used by library and calling library routines to process input on that filedescriptor. Asyncronous mode works with callback routines: an application supplies an address of a routine to execute when the query completes, and a data pointer, which is passed to the callback routine.
Queries are submitted to the library in a form of struct dns_query. To perform asyncronous query, an application calls one of the dns_submit_XXX() rounines, and provides necessary information for a callback, together with all the query parameters. When the query completes, library will call application-supplied callback routine, giving it the resolver context (wich holds query completion status), dynamically allocated result (which will be either raw DNS packet or, if applicatin requested parsing the result by specifying non-NULL parse routine, ready-to-use type-specific structure), and a data pointer provided by an application when it submitted the query. It is the application who's responsible for freeing the result memory.
Generic query callback routine looks like this:
typedef void dns_query_fn(ctx, void *result, void *data)Type-specific query interface expects similar form of callback routine with the only difference in type of result argument, which will be pointer to specific data structure (decoded reply) instead of this void pointer to raw DNS packet data.
Result parsing routine looks like this:
typedef int dns_parse_fn(const unsigned char *qdn,When called by the library, the arguments are as follows: pkt points to the start of the packet received; end points past the end of the packet received; cur points past the query DN in the query section of the packet; qdn points to the original query DN. The routine should allocate a single buffer to hold the result, parse the reply filling in the buffer, and return the buffer using resultp argument. It returns 0 in case of error, or udns error code (DNS_E_XXX constants) in case of error. Note that by the time when the parse routine is called by the library, packet is already verified to be a reply to the original query, by matching query DN, query class and query type.
const unsigned char *pkt,
const unsigned char *cur,
const unsigned char *end,
void **resultp);
Type-specific query inteface supplies necessary parsing routines automatically.
In case of error, query completion status as returned by dns_status(ctx), will contain one of the following values:
Library provides two series of routines which uses similar interface -- one for asyncronous queries and another for syncronous queries. There are two general low-level routines in each series to submit (asyncronous interface) and resolve (syncronous interface) queries, as well as several type-specific routines with more easy-to-use interfaces. To submit an asyncronous query, use one of dns_submit_XXX() routine, each of which accepts query parameters, pointers to callback routine and to callback data, and optional current time hint. Note type-specific dns_submit_XXX() routines expects specific type of the callback routine as well, which accepts reply as a pointer to corresponding structure, not a void pointer). Every dns_submit_XXX() routine return pointer to internal query structure of type struct dns_query, used as an identifier for the given query.
To resolve a query syncronously, use one of dns_resolve_XXX() routines, which accepts the same query parameters (but not the callback pointers) as corresponding dns_submit_XXX(), and return the query result, which is the same as passed to the callback routine in case of asyncronous interface.
In either case, the result memory (if the query completed successefully) is dynamically allocated and should be freed by an application. If the query failed for any reason, the result will be NULL, and error status will be available from dns_status(ctx) routine as shown above.
struct dns_query * dns_submit_dn(ctx,
const unsigned char *dn, qcls, qtyp, flags,
parse, cbck, data) struct dns_query * dns_submit_p(ctx,
const char *name, qcls, qtyp, flags,
parse, cbck, data)
enum dns_class qcls;
enum dns_type qtyp;
int flags;
dns_parse_fn *parse;
dns_query_fn *cbck;
void *data;
void *dns_resolve_dn(ctx,
const unsigned char *dn, qcls, qtyp, flags, parse); void *dns_resolve_p(ctx,
const char *name, qcls, qtyp, flags, parse)
enum dns_class qcls;
enum dns_type qtyp;
int flags;
dns_parse_fn *parse;
void *dns_resolve(ctx, struct dns_query *q)
void dns_cancel(ctx, struct dns_query *q)
In addition to the generic low-level query interface, the library provides a set of routines to perform specific queries in a type-safe manner, as well as parsers for several well-known resource record types. The library implements high-level interface for A, AAAA, PTR, MX and TXT records and DNSBL and RHSBL functionality. These routines returns specific types as result of a query, instead of raw DNS packets. The following types and routines are available.
struct dns_rr_null {
char *dnsn_qname; /* original query name */
char *dnsn_cname; /* canonical name */
unsigned dnsn_ttl; /* Time-To-Live (TTL) value */
int dnsn_nrr; /* number of records in the set */ };
NULL RR set, used as a base for all other RR type structures. Every RR structure as used by the library have four standard fields as in struct dns_rr_null.
struct dns_rr_a4 { /* IN A RRset */
char *dnsa4_qname; /* original query name */
char *dnsa4_cname; /* canonical name */
unsigned dnsa4_ttl; /* Time-To-Live (TTL) value */
int dnsa4_nrr; /* number of addresses in the set */
struct in_addr dnsa4_addr[]; /* array of addresses */ }; typedef void
dns_query_a4_fn(ctx, struct dns_rr_a4 *result, data) dns_parse_fn dns_parse_a4; struct dns_query * dns_submit_a4(ctx, const char *name, int flags,
dns_query_a4_fn *cbck, data); struct dns_rr_a4 * dns_resolve_a4(ctx, const char *name, int flags);
The dns_rr_a4 structure holds a result of an IN A query, which is an array of IPv4 addresses. Callback routine for IN A queries expected to be of type dns_query_a4_fn, which expects pointer to dns_rr_a4 structure as query result instead of raw DNS packet. The dns_parse_a4() is used to convert raw DNS reply packet into dns_rr_a4 structure (it is used internally and may be used directly too with generic query interface). Routines dns_submit_a4() and dns_resolve_a4() are used to perform A IN queries in a type-safe manner. The name parameter is the domain name in question, and flags is query flags bitmask, with one bit, DNS_NOSRCH, of practical interest (if the name is absolute, that is, it ends up with a dot, DNS_NOSRCH flag will be set automatically).
struct dns_rr_a6 { /* IN AAAA RRset */
char *dnsa6_qname; /* original query name */
char *dnsa6_cname; /* canonical name */
unsigned dnsa6_ttl; /* Time-To-Live (TTL) value */
int dnsa6_nrr; /* number of addresses in the set */
struct in6_addr dnsa6_addr[]; /* array of addresses */ }; typedef void
dns_query_a6_fn(ctx, struct dns_rr_a6 *result, data) dns_parse_fn dns_parse_a6; struct dns_query * dns_submit_a6(ctx, const char *name, int flags,
dns_query_a6_fn *cbck, data); struct dns_rr_a6 * dns_resolve_a6(ctx, const char *name, int flags);
The dns_rr_a6 structure holds a result of an IN AAAA query, which is an array of IPv6 addresses. Callback routine for IN AAAA queries expected to be of type dns_query_a6_fn, which expects pointer to dns_rr_a6 structure as query result instead of raw DNS packet. The dns_parse_a6() is used to convert raw DNS reply packet into dns_rr_a6 structure (it is used internally and may be used directly too with generic query interface). Routines dns_submit_a6() and dns_resolve_a6() are used to perform AAAA IN queries in a type-safe manner. The name parameter is the domain name in question, and flags is query flags bitmask, with one bit, DNS_NOSRCH, of practical interest (if the name is absolute, that is, it ends up with a dot, DNS_NOSRCH flag will be set automatically).
struct dns_rr_ptr { /* IN PTR RRset */
char *dnsptr_qname; /* original query name */
char *dnsptr_cname; /* canonical name */
unsigned dnsptr_ttl; /* Time-To-Live (TTL) value */
int dnsptr_nrr; /* number of domain name pointers */
char *dnsptr_ptr[]; /* array of domain name pointers */ }; typedef void
dns_query_ptr_fn(ctx, struct dns_rr_ptr *result, data) dns_parse_fn dns_parse_ptr; struct dns_query * dns_submit_a4ptr(ctx, const struct in_addr *addr,
dns_query_ptr_fn *cbck, data); struct dns_rr_ptr * dns_resolve_a4ptr(ctx, const struct in_addr *addr); struct dns_query * dns_submit_a6ptr(ctx, const struct in6_addr *addr,
dns_query_ptr_fn *cbck, data); struct dns_rr_ptr * dns_resolve_a6ptr(ctx, const struct in6_addr *addr);
The dns_rr_ptr structure holds a result of an IN PTR query, which is an array of domain name pointers for a given IPv4 or IPv6 address. Callback routine for IN PTR queries expected to be of type dns_query_ptr_fn, which expects pointer to dns_rr_ptr structure as query result instead of raw DNS packet. The dns_parse_ptr() is used to convert raw DNS reply packet into dns_rr_ptr structure (it is used internally and may be used directly too with generic query interface). Routines dns_submit_a4ptr() and dns_resolve_a4ptr() are used to perform IN PTR queries for IPv4 addresses in a type-safe manner. Routines dns_submit_a6ptr() and dns_resolve_a6ptr() are used to perform IN PTR queries for IPv6 addresses.
struct dns_mx { /* single MX record */
int priority; /* priority value of this MX */
char *name; /* domain name of this MX */ }; struct dns_rr_mx { /* IN MX RRset */
char *dnsmx_qname; /* original query name */
char *dnsmx_cname; /* canonical name */
unsigned dnsmx_ttl; /* Time-To-Live (TTL) value */
int dnsmx_nrr; /* number of mail exchangers in the set */
struct dns_mx dnsmx_mx[]; /* array of mail exchangers */ }; typedef void
dns_query_mx_fn(ctx, struct dns_rr_mx *result, data) dns_parse_fn dns_parse_mx; struct dns_query * dns_submit_mx(ctx, const char *name, int flags,
dns_query_mx_fn *cbck, data); struct dns_rr_mx * dns_resolve_mx(ctx, const char *name, int flags);
The dns_rr_mx structure holds a result of an IN MX query, which is an array of mail exchangers for a given domain. Callback routine for IN MX queries expected to be of type dns_query_mx_fn, which expects pointer to dns_rr_mx structure as query result instead of raw DNS packet. The dns_parse_mx() is used to convert raw DNS reply packet into dns_rr_mx structure (it is used internally and may be used directly too with generic query interface). Routines dns_submit_mx() and dns_resolve_mx() are used to perform IN MX queries in a type-safe manner. The name parameter is the domain name in question, and flags is query flags bitmask, with one bit, DNS_NOSRCH, of practical interest (if the name is absolute, that is, it ends up with a dot, DNS_NOSRCH flag will be set automatically).
struct dns_txt { /* single TXT record */
int len; /* length of the text */
unsigned char *txt; /* pointer to the text */ }; struct dns_rr_txt { /* TXT RRset */
char *dnstxt_qname; /* original query name */
char *dnstxt_cname; /* canonical name */
unsigned dnstxt_ttl; /* Time-To-Live (TTL) value */
int dnstxt_nrr; /* number of text records in the set */
struct dns_txt dnstxt_txt[]; /* array of TXT records */ }; typedef void
dns_query_txt_fn(ctx, struct dns_rr_txt *result, data) dns_parse_fn dns_parse_txt; struct dns_query * dns_submit_txt(ctx, const char *name, enum dns_class qcls,
int flags, dns_query_txt_fn *cbck, data); struct dns_rr_txt * dns_resolve_txt(ctx, const char *name,
enum dns_class qcls, int flags);
The dns_rr_txt structure holds a result of a TXT query, which is an array of text records for a given domain name. Callback routine for TXT queries expected to be of type dns_query_txt_fn, which expects pointer to dns_rr_txt structure as query result instead of raw DNS packet. The dns_parse_txt() is used to convert raw DNS reply packet into dns_rr_txt structure (it is used internally and may be used directly too with generic query interface). Routines dns_submit_txt() and dns_resolve_txt() are used to perform IN MX queries in a type-safe manner. The name parameter is the domain name in question, and flags is query flags bitmask, with one bit, DNS_NOSRCH, of practical interest (if the name is absolute, that is, it ends up with a dot, DNS_NOSRCH flag will be set automatically). Note that each TXT string is represented by struct dns_txt, while zero-terminated (and the len field of the structure does not include the terminator), may contain embedded null characters -- content of TXT records is not interpreted by the library in any way.
struct dns_srv { /* single SRV record */
int priority; /* priority of the record */
int weight; /* weight of the record */
int port; /* the port number to connect to */
char *name; /* target host name */ }; struct dns_rr_srv { /* SRV RRset */
char *dnssrv_qname; /* original query name */
char *dnssrv_cname; /* canonical name */
unsigned dnssrv_ttl; /* Time-To-Live (TTL) value */
int dnssrv_nrr; /* number of text records in the set */
struct dns_srv dnssrv_srv[]; /* array of SRV records */ }; typedef void
dns_query_srv_fn(ctx, struct dns_rr_srv *result, data) dns_parse_fn dns_parse_srv; struct dns_query * dns_submit_srv(ctx, const char *name, const char *service, const char *protocol,
int flags, dns_query_txt_fn *cbck, data); struct dns_rr_srv * dns_resolve_srv(ctx, const char *name, const char *service, const char *protocol,
int flags);
The dns_rr_srv structure holds a result of an IN SRV (rfc2782) query, which is an array of servers (together with port numbers) which are performing operations for a given service using given protocol on a target domain name. Callback routine for IN SRV queries expected to be of type dns_query_srv_fn, which expects pointer to dns_rr_srv structure as query result instead of raw DNS packet. The dns_parse_srv() is used to convert raw DNS reply packet into dns_rr_srv structure (it is used internally and may be used directly too with generic query interface). Routines dns_submit_srv() and dns_resolve_srv() are used to perform IN SRV queries in a type-safe manner. The name parameter is the domain name in question, service and protocl specifies the service and the protocol in question (the library will construct query DN according to rfc2782 rules) and may be NULL (in this case the library assumes name parameter holds the complete SRV query), and flags is query flags bitmask, with one bit, DNS_NOSRCH, of practical interest (if the name is absolute, that is, it ends up with a dot, DNS_NOSRCH flag will be set automatically).
struct dns_naptr { /* single NAPTR record */
int order; /* record order */
int preference; /* preference of this record */
char *flags; /* application-specific flags */
char *service; /* service parameter */
char *regexp; /* substitutional regular expression */
char *replacement; /* replacement string */ }; struct dns_rr_naptr { /* NAPTR RRset */
char *dnsnaptr_qname; /* original query name */
char *dnsnaptr_cname; /* canonical name */
unsigned dnsnaptr_ttl; /* Time-To-Live (TTL) value */
int dnsnaptr_nrr; /* number of text records in the set */
struct dns_naptr dnsnaptr_naptr[]; /* array of NAPTR records */ }; typedef void
dns_query_naptr_fn(ctx, struct dns_rr_naptr *result, data) dns_parse_fn dns_parse_naptr; struct dns_query * dns_submit_naptr(ctx, const char *name, int flags,
dns_query_txt_fn *cbck, data); struct dns_rr_naptr * dns_resolve_naptr(ctx, const char *name, int flags);
The dns_rr_naptr structure holds a result of an IN NAPTR (rfc3403) query. Callback routine for IN NAPTR queries expected to be of type dns_query_naptr_fn, expects pointer to dns_rr_naptr structure as query result instead of raw DNS packet. The dns_parse_naptr() is used to convert raw DNS reply packet into dns_rr_naptr structure (it is used internally and may be used directly too with generic query interface). Routines dns_submit_naptr() and dns_resolve_naptr() are used to perform IN NAPTR queries in a type-safe manner. The name parameter is the domain name in question, and flags is query flags bitmask, with one bit, DNS_NOSRCH, of practical interest (if the name is absolute, that is, it ends up with a dot, DNS_NOSRCH flag will be set automatically).
A DNS-based blocklists, or a DNSBLs, are in wide use nowadays, especially to protect mailservers from spammers. The library provides DNSBL interface, a set of routines to perform queries against DNSBLs. Routines accepts an IP address (IPv4 and IPv6 are both supported) and a base DNSBL zone as query parameters, and returns either dns_rr_a4 or dns_rr_txt structure. Note that IPv6 interface return IPv4 RRset.
struct dns_query * dns_submit_a4dnsbl(ctx,Perform (submit or resolve) a DNSBL query for the given dnsbl domain and an IP addr in question, requesting either A or TXT records.
const struct in_addr *addr, const char *dnsbl,
dns_query_a4_fn *cbck, void *data); struct dns_query * dns_submit_a4dnsbl_txt(ctx,
const struct in_addr *addr, const char *dnsbl,
dns_query_txt_fn *cbck, void *data); struct dns_query * dns_submit_a6dnsbl(ctx,
const struct in6_addr *addr, const char *dnsbl,
dns_query_a4_fn *cbck, void *data); struct dns_query * dns_submit_a6dnsbl_txt(ctx,
const struct in6_addr *addr, const char *dnsbl,
dns_query_txt_fn *cbck, void *data); struct dns_rr_a4 *dns_resolve_a4dnsbl(ctx,
const struct in_addr *addr, const char *dnsbl) struct dns_rr_txt *dns_resolve_a4dnsbl_txt(ctx,
const struct in_addr *addr, const char *dnsbl) struct dns_rr_a4 *dns_resolve_a6dnsbl(ctx,
const struct in6_addr *addr, const char *dnsbl) struct dns_rr_txt *dns_resolve_a6dnsbl_txt(ctx,
const struct in6_addr *addr, const char *dnsbl)
RHSBL is similar to DNSBL, but instead of an IP address, the parameter is a domain name.
struct dns_query * dns_submit_rhsbl(ctx, const char *name, const char *rhsbl,Perform (submit or resolve) a RHSBL query for the given rhsbl domain and name in question, requesting either A or TXT records.
dns_query_a4_fn *cbck, void *data); struct dns_query * dns_submit_rhsbl_txt(ctx, const char *name, const char *rhsbl,
dns_query_txt_fn *cbck, void *data); struct dns_rr_a4 * dns_resolve_rhsbl(ctx, const char *name, const char *rhsbl); struct dns_rr_txt * dns_resolve_rhsbl_txt(ctx, const char *name, const char *rhsbl);
A DN is a series of domain name labels each starts with length byte, followed by empty label (label with zero length). The following routines to work with DNs are provided.
unsigned dns_dnlen(const unsigned char *dn)
unsigned dns_dnlabels(const unsigned char *dn)
unsigned dns_dnequal(dn1, dn2)
const unsigned char *dn1, *dn2;
unsigned dns_dntodn(sdn, ddn, dnsiz)
const unsigned char *sdn;
unsigned char *ddn;
unsigned dnsiz;
int dns_ptodn(name, namelen, dn, dnsiz, isabs) int dns_sptodn(name, dn, dnsiz)
const char *name; unsigned namelen;
unsigned char *dn; unsigned dnsiz;
int *isabs;
dns_ptodn(name, 0, dn, dnlen, 0).
extern const unsigned char dns_inaddr_arpa_dn[] int dns_a4todn(const struct in_addr *addr, const unsigned char *tdn,
unsigned char *dn, unsigned dnsiz) int dns_a4ptodn(const struct in_addr *addr, const char *tname,
unsigned char *dn, unsigned dnsiz) extern const unsigned char dns_ip6_arpa_dn[] int dns_a6todn(const struct in6_addr *addr, const unsigned char *tdn,
unsigned char *dn, unsigned dnsiz) int dns_a6ptodn(const struct in6_addr *addr, const char *tname,
unsigned char *dn, unsigned dnsiz)
int dns_dntop(dn, name, namesiz)
const unsigned char *dn;
const char *name; unsigned namesiz;
const char *dns_dntosp(const unsigned char *dn)
unsigned dns_dntop_size(const unsigned char *dn)
The following routines are provided to encode and decode DNS on-wire packets. This is low-level interface.
DNS response codes (returned by dns_rcode() routine) are defined as constants prefixed with DNS_R_. See udns.h header file for the complete list. In particular, constants DNS_R_NOERROR (0), DNS_R_SERVFAIL, DNS_R_NXDOMAIN may be of interest to an application.
unsigned dns_get16(const unsigned char *p) unsigned dns_get32(const unsigned char *p)
unsigned char *dns_put16(unsigned char *d, unsigned n) unsigned char *dns_put32(unsigned char *d, unsigned n)
DNS_HSIZE (12)
unsigned dns_qid(const unsigned char *pkt) int dns_rd(const unsigned char *pkt) int dns_tc(const unsigned char *pkt) int dns_aa(const unsigned char *pkt) int dns_qr(const unsigned char *pkt) int dns_ra(const unsigned char *pkt) unsigned dns_opcode(const unsigned char *pkt) unsigned dns_rcode(const unsigned char *pkt) unsigned dns_numqd(const unsigned char *pkt) unsigned dns_numan(const unsigned char *pkt) unsigned dns_numns(const unsigned char *pkt) unsigned dns_numar(const unsigned char *pkt) const unsigned char *dns_payload(const unsigned char *pkt)
int dns_getdn(pkt, curp, pkte, dn, dnsiz) const unsigned char *dns_skipdn(cur, pkte)
const unsigned char *pkt, *pkte, **curp, *cur;
unsigned char *dn; unsigned dnsiz;
struct dns_rr {
unsigned char dnsrr_dn[DNS_MAXDN]; /* the RR DN name */
enum dns_class dnsrr_cls; /* class of the RR */
enum dns_type dnsrr_typ; /* type of the RR */
unsigned dnsrr_ttl; /* TTL value */
unsigned dnsrr_dsz; /* size of data in bytes */
const unsigned char *dnsrr_dptr; /* pointer to the first data byte */
const unsigned char *dnsrr_dend; /* next byte after RR */ };
struct dns_parse {
const unsigned char *dnsp_pkt; /* pointer to the packet being parsed */
const unsigned char *dnsp_end; /* end of the packet pointer */
const unsigned char *dnsp_cur; /* current packet positionn */
const unsigned char *dnsp_ans; /* pointer to the answer section */
int dnsp_rrl; /* number of RRs left */
int dnsp_nrr; /* number of relevant RRs seen so far */
unsigned dnsp_ttl; /* TTL value so far */
const unsigned char *dnsp_qdn; /* the domain of interest or NULL */
enum dns_class dnsp_qcls; /* class of interest or 0 for any */
enum dns_type dnsp_qtyp; /* type of interest or 0 for any */
unsigned char dnsp_dnbuf[DNS_MAXDN]; /* domain name buffer */ };
int dns_initparse(struct dns_parse *p,
const unsigned char *qdn,
const unsigned char *pkt,
const unsigned char *cur,
const unsigned char *end)
int dns_nextrr(struct dns_parse *p, struct dns_rr *rr);
void dns_rewind(struct dns_parse *p, const unsigned char *qdn)
int dns_stdrr_size(const struct dns_parse *p);
void *dns_stdrr_finish(struct dns_rr_null *ret, char *cp,
const struct dns_parse *p);
See library source for usage examples of all the above low-level routines, especially source of the parsing routines.
int dns_pton(int af, const char *src, void *dst);
const char *dns_ntop(int af, const void *src,
char *dst, int dstsize)
The udns library has been written by Michael Tokarev, mjt+udns@tls.msk.ru.
This manual page corresponds to udns version 0.4, released Jan-2014.
Jan 2014 | Library Functions |