LIBUNBOUND(3)
π libunbound(3) β NAME π
okay so bestie, listen: libunbound is the Unbound DNS validating resolver 1.26.2 functions. that's the whole name section and it ate. periodt.
π SYNOPSIS π
#include <unbound.h>
struct ub_ctx * ub_ctx_create(void);
void ub_ctx_delete(struct ub_ctx* ctx);
int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val);
int ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** val);
int ub_ctx_config(struct ub_ctx* ctx, char* fname);
int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr);
int ub_ctx_set_stub(struct ub_ctx* ctx, char* zone, char* addr,
int isprime);
int ub_ctx_set_tls(struct ub_ctx* ctx, int tls);
int ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname);
int ub_ctx_hosts(struct ub_ctx* ctx, char* fname);
int ub_ctx_add_ta(struct ub_ctx* ctx, char* ta);
int ub_ctx_add_ta_autr(struct ub_ctx* ctx, char* fname);
int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname);
int ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname);
int ub_ctx_debugout(struct ub_ctx* ctx, FILE* out);
int ub_ctx_debuglevel(struct ub_ctx* ctx, int d);
int ub_ctx_async(struct ub_ctx* ctx, int dothread);
int ub_poll(struct ub_ctx* ctx);
int ub_wait(struct ub_ctx* ctx);
int ub_fd(struct ub_ctx* ctx);
int ub_process(struct ub_ctx* ctx);
int ub_resolve(struct ub_ctx* ctx, char* name,
int rrtype, int rrclass, struct ub_result** result);
int ub_resolve_async(struct ub_ctx* ctx, char* name,
int rrtype, int rrclass, void* mydata, ub_callback_type*
callback, int* async_id);
int ub_cancel(struct ub_ctx* ctx, int async_id);
void ub_resolve_free(struct ub_result* result);
const char * ub_strerror(int err);
int ub_ctx_print_local_zones(struct ub_ctx* ctx);
int ub_ctx_zone_add(struct ub_ctx* ctx, char* zone_name, char*
zone_type);
int ub_ctx_zone_remove(struct ub_ctx* ctx, char* zone_name);
int ub_ctx_data_add(struct ub_ctx* ctx, char* data);
int ub_ctx_data_remove(struct ub_ctx* ctx, char* data);
β¨ DESCRIPTION π¦
okay so picture this: Unbound is an implementation of a DNS resolver, and it does caching and DNSSEC validation. this page is the library API, the one you use with the -lunbound library. the actual server daemon? that's described over in unbound(8) β different icon, different vibe. and the important part: this library works independent from a running unbound server. you can use it to convert hostnames to ip addresses, and back, and obtain other information from the DNS. plus it performs public-key validation of results with DNSSEC. literally so secure of it. π₯
the library uses a variable of type struct ub_ctx to keep context between calls. you, the user, have to maintain it β creating it with ub_ctx_create and deleting it with ub_ctx_delete. it can be created and deleted at any time. and listen: creating it anew removes any previous configuration (such as trusted keys) and clears any cached results. so like, it's giving fresh start energy, but also don't do it by accident bestie. π
the functions are thread-safe, and a context can be used in a threaded (as well as in a non-threaded) environment. also resolution (and validation) can be performed blocking and non-blocking (also called asynchronous). the async method returns from the call immediately, so that processing can go on, while the results become available later. that's main character energy fr fr. π«Ά
the functions are discussed in turn below. no cap, we're about to go through every single one. π
β¨ FUNCTIONS β¨
Okay bestie, here comes the whole roster of things you can actually call. Every single one, no skips. π
ub_ctx_createβ makes you a brand-new context, all set up with defaults. Heads up though: it does not pull in the info from/etc/resolv.confand/etc/hostsby default β you gotta go get those yourself withub_ctx_resolvconfandub_ctx_hosts. And before you call this one, if you're using lib openssl, call the openssl functionsCRYPTO_set_id_callbackandCRYPTO_set_locking_callbackto set up async operation (your app calls these once, just for initialisation). Openssl 1.0.0 or later uses theCRYPTO_THREADID_set_callbackfunction instead. π±ub_ctx_deleteβ deletes the validation context and frees up all the resources hanging off it. Queries that are still async out there? They get killed, and their callbacks never get called. Bye girl πub_ctx_set_optionβ the power-user interface π lets you hand it one of the options from the config file format, peepunbound.conf(5). Not every option is relevant here, bestie. For some specific ones β like adding trust anchors β there are special routines instead. Pass the option name with the trailing':'.ub_ctx_get_optionβ the power-user interface for getting an option value. Some options just cannot be gotten, and others hand you back a newline separated list. Pass the option name without the trailing':'. The value you get back has to befree(2)d by you, the caller. π«Άub_ctx_configβ power-user interface again: point it at an unbound config file, seeunbound.conf(5), and it gets read for configuration. Not all options are relevant. For some specific options, like adding trust anchors, special routines exist instead. β οΈ Thread-safety tea: this function is thread-safe only if a single instance ofub_ctx*exists in the application. If several instances exist, the application itself has to make sureub_ctx_configis not called in parallel by those different instances.ub_ctx_set_fwdβ sets the machine to forward DNS queries to, i.e. the caching resolver you wanna use. IP4 or IP6 address. It forwards all DNS requests to that machine, which is expected to be running a recursive resolver. If that proxy isn't DNSSEC capable, validation may fail. π¬ You can call this several times β in that case the addresses get used as backup servers. At this time it is only possible to set configuration before the first resolve is done.ub_ctx_set_stubβ sets a stub zone: the authoritative dns servers to use for a particular zone. IP4 or IP6 address. If the address isNULLthe stub entry gets removed. Set isprime true if you're configuring root hints with it. Otherwise it's similar to the stub zone item from unbound's config file. Can be called several times, for different zones, or to add multiple addresses for a particular zone. At this time it is only possible to set configuration before the first resolve is done.ub_ctx_set_tlsβ enables DNS over TLS (DoT) π for machines that were set withub_ctx_set_fwd. At this time it is only possible to set configuration before the first resolve is done.ub_ctx_resolvconfβ by default the root servers are queried and full resolver mode is used, but you can use this call to read the list of nameservers to use from the filename you give it. Usually that's"/etc/resolv.conf". It uses those nameservers as caching proxies. If they don't support DNSSEC, validation may fail. Only nameservers get picked up β the searchdomain, ndots and other settings fromresolv.conf(5)are ignored. π If you passfnameNULL,"/etc/resolv.conf"gets used (if you're on Windows, the system-wide configured nameserver is picked instead). At this time it is only possible to set configuration before the first resolve is done.ub_ctx_hostsβ reads the list of hosts from the filename you give. Usually"/etc/hosts". When queried for, these addresses are not marked DNSSEC secure. If you passfnameNULL,"/etc/hosts"gets used (if you're on Windows,etc/hostsfromWINDIRis picked instead). At this time it is only possible to set configuration before the first resolve is done.ub_ctx_add_taβ adds a trust anchor to the given context. At this time it is only possible to add trusted keys before the first resolve is done. The format is a string, similar to the zone-file format:[domainname] [type] [rdata contents]. Both DS and DNSKEY records are accepted. πub_ctx_add_ta_autrβ adds a filename with an automatically tracked trust anchor to the given context. Pass the name of a file with the managed trust anchor. You can create this file withunbound-anchor(8)for the root anchor. You can also create it with an initial file containing one line with a DNSKEY or DS record. If the file is writable, it gets updated when the trust anchor changes. β¨ At this time it is only possible to add trusted keys before the first resolve is done.ub_ctx_add_ta_fileβ adds trust anchors to the given context. Pass the name of a file with DS and DNSKEY records in zone file format. At this time it is only possible to add trusted keys before the first resolve is done.ub_ctx_trustedkeysβ adds trust anchors to the given context. Pass the name of a bind-style config file withtrusted-keys{}. At this time it is only possible to add trusted keys before the first resolve is done.ub_ctx_debugoutβ sets debug and error log output to the given stream. PassNULLto disable output. Default isstderr. File-names or using syslog can be enabled using config options β this routine is for using your own stream, iykwim.ub_ctx_debuglevelβ sets debug verbosity for the context. Output goes tostderr. Higher debug level = more output. Spammy but informative, honestly.ub_ctx_asyncβ sets a context behaviour for asynchronous action. If set to true, it enables threading and a call toub_resolve_asynccreates a thread to handle work in the background. If false, a process is forked to handle the work in the background instead. π§΅ Changes to this setting afterub_resolve_asynccalls have been made have no effect β delete and re-create the context if you wanna change it.ub_pollβ polls a context to see if it's got any new results. Do not poll in a loop, bestie, that's not the move β instead extract the fd below to poll for readiness and then check, or wait using the wait routine. Returns0if there's nothing to read, or nonzero if a result is available. If it's nonzero, callub_processto do callbacks.ub_waitβ waits for a context to finish with results. It callsub_processafter the wait for you π«Ά. After the wait, there are no more outstanding asynchronous queries.ub_fdβ gets the file descriptor. Wait for it to become readable β at that point answers are returned from the asynchronous validating resolver. Then callub_processto continue processing. πub_processβ call this routine to continue processing results from the validating resolver (when the fd becomes readable). It will perform the necessary callbacks.ub_resolveβ performs resolution and validation of the target name. The name is a domain name in a zero terminated text string. Therrtypeandrrclassare DNS type and class codes. The result structure is newly allocated with the resulting data.ub_resolve_asyncβ performs asynchronous resolution and validation of the target name. The arguments mean the same as forub_resolve, except no data is returned immediately β instead a callback gets called later. The callback receives a copy of themydatapointer, which you can use to pass information to the callback. The callback type is a function pointer to a function declared as:
void my_callback_function(void* my_arg, int err,
struct ub_result* result);
The async_id is returned so you can (at your option) decide to track it and cancel the request if needed. If you pass a NULL pointer, the async_id is not returned.
ub_cancelβ cancels an async query in progress. This may return an error if the query does not exist, or if the query is already being delivered β in that case you may still get a callback for the query. πub_resolve_freeβ frees thestruct ub_resultcontents after use. Clean up after yourself, periodt.ub_strerrorβ converts an error value from one of the unbound library functions into a human readable string. Fr fr, so useful.ub_ctx_print_local_zonesβ debug printout of the local authority information to debug output.ub_ctx_zone_addβ adds a new zone to the local authority info, just like thelocal-zoneunbound.conf(5)statement.ub_ctx_zone_removeβ deletes a zone from the local authority info.ub_ctx_data_addβ adds resource record data to the local authority info, like thelocal-dataunbound.conf(5)statement.ub_ctx_data_removeβ deletes local authority data for the name you give it.
π¦ RESULT DATA STRUCTURE π¦
The result of the DNS resolution and validation comes back to you as struct ub_result. That result structure holds these entries, and yes, we're listing all of them:
struct ub_result {
char* qname; /* text string, original question */
int qtype; /* type code asked for */
int qclass; /* class code asked for */
char** data; /* array of rdata items, NULL terminated*/
int* len; /* array with lengths of rdata items */
char* canonname; /* canonical name of result */
int rcode; /* additional error code in case of no data */
void* answer_packet; /* full network format answer packet */
int answer_len; /* length of packet in octets */
int havedata; /* true if there is data */
int nxdomain; /* true if nodata because name does not exist */
int secure; /* true if result is secure */
int bogus; /* true if a security failure happened */
char* why_bogus; /* string with error if bogus */
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
int ttl; /* number of seconds the result is valid */
};
So here's the vibe check on secure and bogus: if both secure and bogus are false, that means security was not enabled for the domain of the query. Otherwise, they are not both true β exactly one of them is true. π
β¨ RETURN VALUES β¨
okay bestie, here's the tea on what these functions hand back to you π
- Lots of these routines return an error code. The magic number
0(zero, yes the plain one) means no error happened, we're thriving, nothing is wrong, periodt β¨ - Got some other number back? π No stress β you can pass it straight to
ub_strerrorand it'll give you a readable error string. And just so you know,ub_strerrorreturns a zero terminated string. π ub_ctx_createreturnsNULLon an error β and that error is specifically a malloc failure. So if you seeNULL, the memory said no πub_pollreturnstrueif some information may be available, andfalseotherwise. Hopeful little guy, isn't it π«Άub_fdreturns a file descriptor, or-1on error πub_ctx_configandub_ctx_resolvconfwill attempt to leaveerrnoinformative when they return with a file read failure. Attempt, bestie. They try their best π
πΈ SEE ALSO πΈ
Go read these next, they're part of the lore, iykyk π
π AUTHOR π
The Unbound developers are mentioned in the CREDITS file in the distribution. Shoutout to the whole squad, iconic behaviour honestly π
π COPYRIGHT π
1999-2026, NLnet Labs π
and that's a wrap on the whole page, bestie!! this was LIBUNBOUND(3), living in source/version 1.26.2, dated Oct 21, 2026 π¦ go forth and bind some names, you main character πβ¨πΈπ«Ά
π¦ where this page comes from
- arch rolling: unbound 1.26.2-1 Β· 0BSD AND BSD-3-Clause
- debian trixie: libunbound-dev 1.26.2-0+deb13u1 Β· BSD-3-NLnetLabs
- fedora 44: unbound-devel 1.26.2-1.fc44 Β· BSD-3-Clause
- fedora 44: unbound-devel 1.26.2-1.fc44 Β· BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms