---
name: "dns_transmit"
section: "3"
platform: "linux"
package: "libdjbdns1-dev"
version: "1.05-5+b1"
release: "Debian 5.0 (Lenny)"
platforms: ["linux"]
url: "https://new.carta.tech/dns_transmit"
---

# dns\_transmit(3)

The dns\_transmit library interface

## 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_domain/3.md), [dns\_ip4(3)](/dns_ip4/3.md), [dns\_ip4\_qualify(3)](/dns_ip4_qualify/3.md), [dns\_mx(3)](/dns_mx/3.md), [dns\_name4(3)](/dns_name4/3.md), [dns\_packet(3)](/dns_packet/3.md), [dns\_random(3)](/dns_random/3.md), [dns\_txt(3)](/dns_txt/3.md)

http://cr.yp.to/djbdns/blurb/library.html
