NAME
dns_transmit_* - The dns_transmit library interface
SYNOPSIS
#include <dns.h>
dns_transmit_start(&dt, s, flagrecursive, q, t, localip);
dns_transmit_io(&dt, x, &deadline);
dns_transmit_get(&dt, x, &stamp);
dns_transmit_free(&dt);
struct dns_transmit dt = {0};
char s[64];
int flagrecursive;
char *q;
char t[2];
char localip[4];
iopause_fd x[1];
struct taia deadline;
struct taia stamp;
DESCRIPTION
The dns_transmit functions send a DNS query to some DNS servers. They
save the first useful response inside dt.
The query asks for Internet records of type t for the domain name
packet-encoded in q. It requests server recursion if flagrecursive is
nonzero.
The IP addresses of the DNS servers are listed in s. The dns_transmit
functions skip IP addresses of 0.0.0.0. The dns_transmit functions
record only a pointer to the contents of s, not a copy of s, so you
must leave s in place and unchanged.
The dns_transmit functions send outgoing packets from a local IP
address of localip.
The dns_transmit functions act asynchronously. They are designed to be
used in an iopause event loop:
if (dns_transmit_start(&dt,s,flagrecursive,q,t,localip) == -1)
return -1;
for (;;) {
int r;
taia_now(&stamp);
taia_addsec(&deadline,&stamp,120);
dns_transmit_io(&dt,x,&deadline);
iopause(x,1,&deadline,&stamp);
r = dns_transmit_get(&dt,x,&stamp);
if (r == -1) return -1;
if (r == 1) break;
}
dosomething(dt.packet,dt.packetlen);
dns_transmit_free(&dt);
return 0;
dns_transmit_start begins the query; it returns 0 on success, or -1 on
failure. dns_transmit_get continues the query; it returns 1 if the
response has arrived, 0 if the response has not yet arrived, or -1 on
failure. Here ‘‘failure’’ means a socket creation failure, a memory
allocation failure, a timeout after the final query attempt, an empty
list of servers (reported as EIO), a query longer than 65535 bytes
(reported as EIO), a malformed response to the final query attempt
(reported as EIO), or a server declaration of failure in response to
the final query attempt (reported as EAGAIN).
The dns_transmit functions communicate through dt. They dynamically
allocate a socket for network communication, memory for the DNS
request, and memory for the DNS response; these resources are freed
when you call dns_transmit_free, or when you call dns_transmit_start
again with the same dt to handle another query. You must zero-
initialize dt before calling dns_transmit_start the first time.
If dns_transmit_get returns 1, the DNS response is a byte string of
length dt.packetlen; dt.packet points to the first byte. The IP
address of the server that provided the response is stored at
dt.servers + 4 * dt.curserver.
Transmission details
The dns_transmit functions send the query by UDP to the first address,
wait 1 second for a response, send the query by UDP to the second
address, wait 1 second for a response, etc.; then send the query by UDP
to each address again, but waiting 3 seconds for each response; then
again, waiting 11 seconds; then one last time, waiting 45 seconds.
Recursive queries skip the 1-second step.
dns_transmit_get does not always return the first packet it sees:
1. If the packet has the wrong ID, shows the wrong query name,
shows the wrong query type, or has qdcount different from 1:
dns_transmit_get discards the packet as irrelevant, and
continues waiting for packets from the same server.
2. If the packet has rcode different from 0 or 3: dns_transmit_get
discards the packet, and moves immediately to the next server.
3. If the packet has the tc bit set: dns_transmit_get tries a TCP
connection to each address, waiting 10 seconds for the
connection and, if a connection is established, 10 more seconds
for a response.
dns_transmit_get does not listen to several servers simultaneously for
responses for the same query. Each query transmission uses a new
random port number and query ID.
SEE ALSO
dns_domain(3), dns_ip4(3), dns_ip4_qualify(3), dns_mx(3), dns_name4(3),
dns_packet(3), dns_random(3), dns_txt(3)
http://cr.yp.to/djbdns/blurb/library.html
dns_transmit_*(3)