Do not want your code to block in
gethostbyname() or getaddrinfo() calls? Then,
TADNS is for you. Using it is easy because of the following:
It is written in ANSI C
The source code is in single .c file, so intergating it in
your build means copying of two files
Supports query cache: subsequent calls to resolve the same
host hit the cache, saving time and traffic
Can do A and MX lookups
Very clean and simple API
Get it and try it. TADNS is licensed under the
phk's beer-ware license:
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Sergey Lyubka wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
Usage example
static void my_callback(void *context, enum dns_query_type qtype,
const char *name, const unsigned char *addr, size_t addrlen)
{
if (addrlen == 0) {
(void) fprintf(stderr, "No idea about [%s]\n", name);
} else {
printf("%u.%u.%u.%u\n", addr[0], addr[1], addr[2], addr[3]);
}
}
int main(int argc, char *const *argv)
{
struct dns *dns;
char host[] = "www.sourceforge.net";
fd_set set;
struct timeval tv = {3, 0}; /* Wait max for 3 seconds */
/* ... */
/* Initialize the library */
dns = dns_init();
/* ... */
/* Make a request */
dns_queue(dns, NULL, host, DNS_A_RECORD, my_callback);
/* Wait for a reply. We can multiplex other IO here. */
FD_ZERO(&set);
FD_SET(dns_get_fd(dns), &set);
if (select(dns_get_fd(dns) + 1, &set, NULL, NULL, &tv) == 1)
dns_poll(dns);
/* ... */
}
At the end of tdns.c file you can find a piece of code
that emulates simple dig utility.
This is a user callback prototype. The user function is called
when by the dns_poll() function if the requested
information available. The context parameter is any
user data, but it must be unique between multiple request.
The IP address for the requested hostname is of
addrlen length, and located at addr pointer.
If addrlen is 0, it means lookup failure - not existent
host or lookup timeout.
struct dns *dns_init(void)
Initializes the library, and returns pointer to opaque
struct dns. Must be called first.
void dns_fini(struct dns *)
Cleanup function.
int dns_get_fd(struct dns *)
Returns UDP socket used to send DNS queries. It can be used
to multiplex the I/O by means of select() or other calls.
The actual lookup request. This function does not block,
so that is why the library is asynchronous. It searches the query
cache first. If there was a query for the same host before, and
the result has not being expired, the user callback is called
immediately, and function returns. If there is no suitable entry
in the cache, a UDP packet is crafted and sent to the DNS server.
The user callback is called later, from the
dns_poll() function.
void dns_cancel(struct dns *, const void *context)
Request cancellation. The callback will not be called for
that context.
void dns_poll(struct dns *)
Check the UDP socket for DNS replies. If there are any,
associated user callback is called with the reply data.