---
name: "libgetdns"
section: "3"
platform: "linux"
package: "getdns"
version: "1.7.3-2"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/libgetdns"
---

# libgetdns(3)

## NAME

libgetdns -- an implementation of a modern asynchronous DNS API by and for application developers

## LIBRARY

DNS Resolver library (libgetdns, -lgetdns)

## SYNOPSIS

**libgetdns**

This man page describes the getdns library, the general concepts behind the API and some of the common elements of the public interface to the library.  Each of the public entry points and more complex data types are captured in separate man pages.

## DESCRIPTION

getdns is modern asynchronous DNS API intended to be useful to application developers and operating system distributors as a way of making all types of DNS information easily available in many types of programs. The major features of this new API are:

    Full support for event-driven programming\
     Supports DNSSEC in multiple ways\
     Mirroring of the resolution in getaddrinfo()\
     Easily supports all RRtypes, even those yet to be defined

Each of the entry points is offered with both asynchronous and synchronous signatures.  The asynchronous functions rely on event handling and callback via libevent. Functions are thread safe.

A context structure maintains DNS query and response data and is used to maintain state during calls to the public entry points.

The project page for this implementation is at

-

  http://getdnsapi.net

The specification is maintained at

-

  http://getdnsapi.net/spec

The git repository for this implementation is at

-

  http://github.com/getdnsapi/getdns

## DATA STRUCTURES

The API uses a few data structures to pass data into and return data from the public entry points.

- list

  an ordered list, the members of the list can be any of the four data types.

- dict

  a name-value pair. The name is a string literal, and the value can be any of the four data types. The order of the name-value pairs in a dict is not important.

- int

  an integer compatible with uint32\_t.

- bindata

  a struct used to hold binary data defined as { size\_t size; uint8\_t \*binary\_stuff; }.

## ASYNCHRONOUS USE

The getdns specification emphasizes the asynchronous nature of the API and allows implementations to define their own approach. This page documents this implementation's decisions and facilities provided to the developer.

This implementation provides asynchronous support via the following mechanisms:

File Descriptor Polling\
 Event Loop Integrations:

libevent\
 libuv\
 libev

Custom Event Loop Integrations

All functions and types discussed in this page are declared in getdns\_extra.h

### Build-in Event loop

The library has an built in event loop that can be used if none of the extensions for external event loops are used. The library will execute requests and dispatch callbacks with a call to *getdns\_context\_run().* If an event loop extension is used, this will run the extension's eventloop.

void getdns\_context\_run(getdns\_context \*context)

Run the context's event loop until nothing more to do.

uint32\_t getdns\_context\_get\_num\_pending\_requests(getdns\_context\* context, struct timeval\* next\_timeout)

Get the number of outstanding asynchronous requests for a given context as well as the the amount of time until the next timeout.  The next\_timeout struct can be NULL.  If supplied and the number of outstanding requests is \> 0, then the timeout represents the relative time until the next timeout.

getdns\_return\_t getdns\_context\_process\_async(getdns\_context\* context)

Inform the context to process its outstanding requests.  Users should call this when either a timeout has occurred or the file descriptor signals that it is ready.  User callbacks are fired during this call.

### Included Event Loop Integrations

A number of applications achieve asynchronous behavior by leveraging event loop abstraction libraries. If the build system discovers a supported event loop, the event loop extension is built in addition to the getdns library. Extensions are built as an additional shared library. The following event loop libraries are supported:

**libevent1 and libevent2**

The libevent extension allows a context to attach to a event\_base. The event loop is then run like any other application using libevent via event\_base\_dispatch or event\_base\_loop and expect getdns callbacks to fire.

Note that if both libevent1 and libevent2 reside on system, the extension uses libevent2.

Extension library: libgetdns\_ext\_event.\[shared\_lib\_ext\]\
 Extension header: getdns/getdns\_ext\_libevent.h

**libuv**

The libuv extension allows a context to attach to a uv\_loop\_s. The event loop can then be run like any other application using libuv via uv\_run and expect getdns callbacks to fire.

Extension library: libgetdns\_ext\_uv.\[shared\_lib\_ext\]\
 Extension header: getdns\_ext\_libuv.h

**libev**

The libev extension allows a context to attach to a ev\_loop. The event loop can then be run like any other application using libev via ev\_run and expect getdns callbacks to fire.

Extension library: libgetdns\_ext\_ev.\[shared\_lib\_ext\]\
 Extension header: getdns\_ext\_libev.h

### getdns\_context event loop extension functions

The following are functions used by the extension entry point to attach to a particular context.

The application sets an event loop extension on a context.  The extension\_data is optional data that is passed into the extension methods.  If an event loop is already set on a context then it is cleaned up.  All outstanding requests are also canceled.

-

  getdns\_return\_t getdns\_extension\_set\_eventloop(struct getdns\_context\* context, getdns\_eventloop\_extension\* extension, void\* extension\_data);

The application gets the extension data associated with a context.

-

  void\* getdns\_context\_get\_extension\_data(struct getdns\_context\* context);

When no more work must be done the application detaches an event loop from a context

-

  getdns\_return\_t getdns\_extension\_detach\_eventloop(struct getdns\_context\* context);

## SYNCHRONOUS USE

There are four synchronous functions parallel to the four getdns async functions, except that there is no callback parameter. When an application calls one of these synchronous functions, the API gathers all the required information and then returns the result. The value returned is exactly the same as the response returned in the callback if you had used the async version of the function.

When you are done with the data in the response, call getdns\_free\_sync\_request\_memory so that the API can free the memory from its internal pool.

## EXTENSIONS

Applications may populate an extension dictionary when making a call to the public entry points.  To use an extension add it to the extension dictionary prior to making the call to the public entry point and set the value depending on the behavior you expect.  These extensions include:

"dnssec\_return\_status" (int)

Set to GETDNS\_EXTENSION\_TRUE to include the DNSSEC status for each DNS record in the replies\_tree

"dnssec\_return\_only\_secure" (int)

Set to GETDNS\_EXTENSION\_TRUE to cause only records that the API can validate as secure with DNSSEC to be returned in the *replies\_tree* and *replies\_full lists*

"dnssec\_return\_validation\_chain" (int)

Set to GETDNS\_EXTENSION\_TRUE to cause the set of additional DNSSEC-related records needed for validation to be returned in the response object as the list named *additional\_dnssec* at the top level of the response object

"return\_both\_v4\_and\_v6" (int)

Set to GETDNS\_EXTENSION\_TRUE to cause the results of both A and AAAA records for the queried name to be included in the response object.

"add\_opt\_parameters" (dict)

TBD (complicated)

"add\_warning\_for\_bad\_dns"

Set to GETDNS\_EXTENSION\_TRUE to cause each reply in the *replies\_tree* to contain an additional name whose data type is a list, *bad\_dns* which contains zero or more ints that indicate the types of bad DNS found in the reply.

GETDNS\_BAD\_DNS\_CNAME\_IN\_TARGET: query type does not allow a CNAME pointed to a CNAME\
 GETDNS\_BAD\_DNS\_ALL\_NUMERIC\_LABEL: one or more labels is all numeric\
 GETDNS\_BAD\_DNS\_CNAME\_RETURNED\_FOR\_OTHER\_TYPE: query type for other than CNAME returned a CNAME

"specify\_class" (int)

Set to the DNS class number (other than Internet (IN) class desired in query.

"return\_call\_reporting" (int)

Set to GETDNS\_EXTENSION\_TRUE to add the name *call\_reporting* (list) to the top level of the response object that includes a dict for each call made to the API.  TBD: more detail

This implementation of the getdns API is licensed under the BSD license.

## DNSSEC

If an application wants the API to do DNSSEC validation for a request, it must set one or more DNSSEC-related extensions. Note that the default is for none of these extensions to be set and the API will not perform DNSSEC. Note that getting DNSSEC results can take longer in a few circumstances.

To return the DNSSEC status for each DNS record in the replies\_tree list, use the dnssec\_return\_status extension. The extension's value (an int) is set to GETDNS\_EXTENSION\_TRUE to cause the returned status to have the name dnssec\_status (an int) added to the other names in the record's dict ("header", "question", and so on). The values for that name are GETDNS\_DNSSEC\_SECURE, GETDNS\_DNSSEC\_BOGUS, GETDNS\_DNSSEC\_INDETERMINATE, and GETDNS\_DNSSEC\_INSECURE. Thus, a reply might look like:

```
{     # This is the first reply
      "dnssec_status": GETDNS_DNSSEC_INDETERMINATE,
      "header": { "id": 23456, "qr": 1, "opcode": 0, ... },
      . . .
```

If instead of returning the status, you want to only see secure results, use the dnssec\_return\_only\_secure extension. The extension's value (an int) is set to GETDNS\_EXTENSION\_TRUE to cause only records that the API can validate as secure with DNSSEC to be returned in the replies\_tree and replies\_full lists. No additional names are added to the dict of the record; the change is that some records might not appear in the results. When this context option is set, if the API receives DNS replies but none are determined to be secure, the error code at the top level of the response object is GETDNS\_RESPSTATUS\_NO\_SECURE\_ANSWERS.

Applications that want to do their own validation will want to have the DNSSEC-related records for a particular response. Use the dnssec\_return\_validation\_chain extension. The extension's value (an int) is set to GETDNS\_EXTENSION\_TRUE to cause a set of additional DNSSEC-related records needed for validation to be returned in the response object. This set comes as validation\_chain (a list) at the top level of the response object. This list includes all resource record dicts for all the resource records (DS, DNSKEY and their RRSIGs) that are needed to perform the validation from the root up. Thus, a reply might look like:

```
{     # This is the response object
    "validation_chain":
    [ { "name": <bindata for .>,
    "type": GETDNS_RRTYPE_DNSKEY,
    "rdata": { "flags": 256, . . . },
      . . .
    },
    { "name": <bindata for .>,
      "type": GETDNS_RRTYPE_DNSKEY,
      "rdata": { "flags": 257, . . . },
      . . .
    },
    { "name": <bindata for .>,
      "type": GETDNS_RRTYPE_RRSIG,
      "rdata": { "signers_name": <bindata for .>,
                 "type_covered": GETDNS_RRTYPE_DNSKEY,
                 . . .
               },
    },
    { "name": <bindata for com.>,
      "type": GETDNS_RRTYPE_DS,
      . . .
    },
    { "name": <bindata for com.>,
      "type": GETDNS_RRTYPE_RRSIG
      "rdata": { "signers_name": <bindata for .>,
                 "type_covered": GETDNS_RRTYPE_DS,
                 . . .
               },
      . . .
    },
    { "name": <bindata for com.>,
      "type": GETDNS_RRTYPE_DNSKEY
      "rdata": { "flags": 256, . . . },
      . . .
    },
    { "name": <bindata for com.>,
      "type": GETDNS_RRTYPE_DNSKEY
      "rdata": { "flags": 257, . . . },
      . . .
    },
    { "name": <bindata for com.>,
      "type": GETDNS_RRTYPE_RRSIG
      "rdata": { "signers_name": <bindata for com.>,
                 "type_covered": GETDNS_RRTYPE_DNSKEY,
                 . . .
               },
      . . .
    },
    { "name": <bindata for example.com.>,
      "type": GETDNS_RRTYPE_DS,
      . . .
    },
    { "name": <bindata for example.com.>,
      "type": GETDNS_RRTYPE_RRSIG
      "rdata": { "signers_name": <bindata for com.>,
                 "type_covered": GETDNS_RRTYPE_DS,
                 . . .
               },
      . . .
    },
    { "name": <bindata for example.com.>,
      "type": GETDNS_RRTYPE_DNSKEY
      "rdata": { "flags": 257, ... },
      . . .
    },
    . . .
  ]
  "replies_tree":
  [
  . . .
```

If a request is using a context in which stub resolution is set, and that request also has any of the dnssec\_return\_status, dnssec\_return\_only\_secure, or dnssec\_return\_validation\_chain extensions specified, the API will not perform the request and will instead return an error of GETDNS\_RETURN\_DNSSEC\_WITH\_STUB\_DISALLOWED.

## OPT RESOURCE RECORDS

For lookups that need an OPT resource record in the Additional Data section, use the add\_opt\_parameters extension. The extension's value (a dict) contains the parameters; these are described in more detail in RFC 2671. They are:

*maximum\_udp\_payload\_size* (an int) between 512 and 65535; if not specified, this defaults to those from the DNS context

*extended\_rcode* (an int) between 0 and 255; if not specified, this defaults to those from the DNS context

*version* (an int) between 0 and 255; if not specified, this defaults to 0

*do\_bit* (an int) between 0 and 1; if not specified, this defaults to those from the DNS context

*options* (a list) contains dicts for each option to be specified. Each list time contains two names: option\_code (an int) and option\_data (a bindata). The API marshalls the entire set of options into a properly-formatted RDATA for the resource record.

It is very important to note that the OPT resource record specified in the add\_opt\_parameters extension might not be the same the one that the API sends in the query. For example, if the application also includes any of the DNSSEC extensions, the API will make sure that the OPT resource record sets the resource record appropriately, making the needed changes to the settings from the add\_opt\_parameters extension.

The use of this extension can conflict with the values in the DNS context. For example, the default for an OS might be a maximum payload size of 65535, but the extension might specify 1550. In such a case, the API will honor the values stated in the extension, but will honor the values from the DNS context if values are not given in the extension.

## RESPONSE DATA

The callback function contains a pointer to a response object. A response object is always a dict. The response object always contains at least three names: replies\_full (a list) and replies\_tree (a list), and status (an int). replies\_full is a list of DNS replies (each is bindata) as they appear on the wire. replies\_tree is a list of DNS replies (each is a dict) with the various part of the reply parsed out. status is a status code for the query.

Because the API might be extended in the future, a response object might also contain names other than replies\_full, replies\_tree, and status. Similarly, any of the dicts described here might be extended in later versions of the API. Thus, an application using the API must not assume that it knows all possible names in a dict.

The following lists the status codes for response objects. Note that, if the status is that there are no responses for the query, the lists in replies\_full and replies\_tree will have zero length.

**GETDNS\_RESPSTATUS\_GOOD** At least one response was returned

**GETDNS\_RESPSTATUS\_NO\_NAME** Queries for the name yielded all negative responses

**GETDNS\_RESPSTATUS\_ALL\_TIMEOUT** All queries for the name timed out

**GETDNS\_RESPSTATUS\_NO\_SECURE\_ANSWERS** The context setting for getting only secure responses was specified, and at least one DNS response was received, but no DNS response was determined to be secure through DNSSEC.

The top level of replies\_tree can optionally have the following names: canonical\_name (a bindata), intermediate\_aliases (a list), answer\_ipv4\_address (a bindata), answer\_ipv6\_address (a bindata), and answer\_type (an int).

The value of canonical\_name is the name that the API used for its lookup. It is in FQDN presentation format.  The values in the intermediate\_aliases list are domain names from any CNAME or unsynthesized DNAME found when resolving the original query. The list might have zero entries if there were no CNAMEs in the path. These may be useful, for example, for name comparisons when following the rules in RFC 6125.  The value of answer\_ipv4\_address and answer\_ipv6\_address are the addresses of the server from which the answer was received.  The value of answer\_type is the type of name service that generated the response. The values are:

    GETDNS\_NAMETYPE\_DNS\
     Normal DNS (RFC 1035)\
     GETDNS\_NAMETYPE\_WINS\
     The WINS name service (some reference needed)

If the call was getdns\_address or getdns\_address\_sync, the top level of replies\_tree has an additional name, just\_address\_answers (a list). The value of just\_address\_answers is a list that contains all of the A and AAAA records from the answer sections of any of the replies, in the order they appear in the replies. Each item in the list is a dict with at least two names: address\_type (whose value is a bindata; it is currently either "IPv4" or "IPv6") and address\_data (whose value is a bindata). Note that the dnssec\_return\_only\_secure extension affects what will appear in the just\_address\_answers list. If the DNS returns other address types, those types will appear in this list as well.

The API can make service discovery through SRV records easier. If the call was getdns\_service or getdns\_service\_sync, the top level of replies\_tree has an additional name, srv\_addresses (a list). The list is ordered by priority and weight based on the weighting algorithm in RFC 2782, lowest priority value first. Each element of the list is dict has at least two names: port and domain\_name. If the API was able to determine the address of the target domain name (such as from its cache or from the Additional section of responses), the dict for an element will also contain address\_type (whose value is a bindata; it is currently either "IPv4" or "IPv6") and address\_data (whose value is a bindata). Note that the dnssec\_return\_only\_secure extension affects what will appear in the srv\_addresses list.

## STRUCTURE OF DNS REPLIES\_TREE

The names in each entry in the the replies\_tree list for DNS responses include header (a dict), question (a dict), answer (a list), authority (a list), and additional (a list), corresponding to the sections in the DNS message format. The answer, authority, and additional lists each contain zero or more dicts, with each dict in each list representing a resource record.

The names in the header dict are all the fields from Section 4.1.1. of RFC 1035. They are: id, qr, opcode, aa, tc, rd, ra, z, rcode, qdcount, ancount, nscount, and arcount. All are ints.

The names in the question dict are the three fields from Section 4.1.2. of RFC 1035: qname (a bindata), qtype (an int), and qclass (an int).

Resource records are a bit different than headers and question sections in that the RDATA portion often has its own structure. The other names in the resource record dicts are name (a bindata), type (an int), class (an int), ttl (an int) and rdata (a dict); there is no name equivalent to the RDLENGTH field.

The rdata dict has different names for each response type. There is a complete list of the types defined in the API. For names that end in "-obsolete" or "-unknown", the bindata is the entire RDATA field. For example, the rdata for an A record has a name ipv4\_address (a bindata); the rdata for an SRV record has the names priority (an int), weight (an int), port (an int), and target (a bindata).

Each rdata dict also has a rdata\_raw field (a bindata). This is useful for types not defined in this version of the API. It also might be of value if a later version of the API allows for additional parsers. Thus, doing a query for types not known by the API still will return a result: an rdata with just a rdata\_raw.

It is expected that later extensions to the API will give some DNS types different names. It is also possible that later extensions will change the names for some of the DNS types listed above.

## CALLBACK FUNCTIONS

A call to the async getdns functions typically returns before any network or file I/O occurs. After the API marshalls all the needed information, it calls the callback function that was passed by the application. The callback function might be called at any time, even before the calling function has returned. The API guarantees that the callback will be called exactly once unless the calling function returned an error, in which case the callback function is never called.

The getdns calling function calls the callback with the parameters defined as follows:

typedef void (\*getdns\_callback\_t)(

getdns\_context\_t context,\
 uint16\_t callback\_type,\
 getdns\_dict \*response,\
 void \*userarg,\
 getdns\_transaction\_t transaction\_id)

*context* see getdns\_context (3)

*callback\_type* Supplies the reason for the callback.

**GETDNS\_CALLBACK\_COMPLETE** The response has the requested data in it

**GETDNS\_CALLBACK\_CANCEL** The calling program canceled the callback; response is NULL

**GETDNS\_CALLBACK\_TIMEOUT** The requested action timed out; response is NULL

**GETDNS\_CALLBACK\_ERROR** The requested action had an error; response is NULL

*response* A response object with the response data. This is described in the section titled "RESPONSE DATA" elsewhere in this manual page. The response object is part of the API's memory space, and will be freed by the API with the callback returns.

*userarg* Identical to the userarg passed to the calling function.

*transaction\_id* The transaction identified assigned by the calling function, used to associate a DNS response to a specific DNS request.

To cancel an outstanding callback, use the following function.

getdns\_return\_t\
 **getdns\_cancel\_callback** (getdns\_context\_t context, getdns\_transaction\_t transaction\_id)

This causes the API to call the callback with a callback\_type of GETDNS\_CALLBACK\_CANCEL if the callback for this transaction\_id has not already been called. The callback code for cancellation should clean up any memory related to the identified call, such as to deallocate the memory for the userarg. getdns\_cancel\_callback() may return immediately, even before the callback finishes its work and returns. Calling getdns\_cancel\_callback() with a transaction\_id of a callback that has already been called or an unknown transaction\_id returns GETDNS\_RETURN\_UNKNOWN\_TRANSACTION; otherwise, getdns\_cancel\_callback() returns GETDNS\_RETURN\_GOOD.

## FILES

## EXAMPLES

TBD

## DIAGNOSTICS

TBD

## SEE ALSO

[**getdns\_address**(3)](/getdns_address/3.md), **getdns\_bindata**(3), [**getdns\_context**(3)](/getdns_context/3.md), [**getdns\_convert**(3)](/getdns_convert/3.md), [**getdns\_dict**(3)](/getdns_dict/3.md), [**getdns\_general**(3)](/getdns_general/3.md), [**getdns\_hostname**(3)](/getdns_hostname/3.md), [**getdns\_list**(3)](/getdns_list/3.md), [**getdns\_root\_trust\_anchor**(3)](/getdns_root_trust_anchor/3.md) [**getdns\_service**(3)](/getdns_service/3.md) [**getdns\_validate\_dnssec**(3)](/getdns_validate_dnssec/3.md)

## REPORTING PROBLEMS

Bug reports should be sent to the getdns-bugs@getdns.net

## AUTHORS

The getdns API was documented by Paul Hoffman.  This implementation of the getdns API was written by:

Craig Despeaux, Verisign Inc.\
 John Dickinson, Sinodun\
 Sara Dickinson, Sinodun\
 Neel Goyal, Verisign Inc.\
 Shumon Huque, Verisign Labs\
 Olaf Kolkman, NLnet Labs\
 Allison Mankin, Verisign Inc. - Verisign Labs.\
 Melinda Shore, No Mountain Software LLC\
 Willem Toorop, NLnet Labs\
 Gowri Visweswaran, Verisign Labs\
 Wouter Wijngaards, NLnet Labs\
 Glen Wiley, Verisign Inc.
