summaryrefslogtreecommitdiff
path: root/src/adns.h
blob: f749f6e5c1a843505f60ec0e8a2992b713b8cb8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/**/

#ifndef ADNS_H_INCLUDED
#define ADNS_H_INCLUDED

#include <sys/socket.h>
#include <netinet/in.h>

typedef struct adns__state *adns_state;
typedef struct adns__query *adns_query;

typedef enum {
  adns_if_noenv=        0x0001, /* do not look at environment */
  adns_if_noerrprint=   0x0002, /* never print output to stderr (_debug overrides) */
  adns_if_noserverwarn= 0x0004, /* do not warn to stderr about duff nameservers etc */
  adns_if_debug=        0x0008, /* enable all output to stderr plus debug msgs */
  adns_if_noautosys=    0x0010, /* do not make syscalls at every opportunity */
} adns_initflags;

typedef enum {
  adns_qf_search=     0x0001, /* use the searchlist */
  adns_qf_usevc=      0x0002, /* use a virtual circuit (TCP connection) */
  adns_qf_anyquote=   0x0004,
  adns_qf_loosecname= 0x0008, /* allow refs to CNAMEs - without, get _s_cname */
  adns_qf_nocname=    0x0010, /* don't follow CNAMEs, instead give _s_cname */
} adns_queryflags;

typedef enum {
  adns__rrt_typemask=  0x0ffff,
  adns__qtf_deref=     0x10000, /* dereference domains and perhaps produce extra data */
  adns__qtf_mail822=   0x20000, /* make mailboxes be in RFC822 rcpt field format */
  adns__qtf_masterfmt= 0x80000, /* convert RRs to master file format, return as str */
  
  adns_r_none=               0,
  
  adns_r_a=                  1,
  adns_r_a_mf=                  adns_r_a|adns__qtf_mf,
  
  adns_r_ns_raw=             2,
  adns_r_ns=                    adns_r_ns_raw|adns__qtf_deref,
  adns_r_ns_mf=                 adns_r_ns_raw|adns__qtf_mf,
  
  adns_r_cname=              5,
  adns_r_cname_mf=              adns_r_cname|adns__qtf_mf,
  
  adns_r_soa_raw=            6,
  adns_r_soa=                   adns_r_soa_raw|adns__qtf_mail822, 
  adns_r_soa_mf=                adns_r_soa_raw|adns__qtf_mf,
  
  adns_r_null=              10,
  adns_r_null_mf=               adns_r_null|adns__qtf_mf,
  
  adns_r_ptr_raw=           12,
  adns_r_ptr=                   adns_r_ptr_raw|adns__qtf_deref,
  adns_r_ptr_mf=                adns_r_ptr_raw|adns__qtf_mf,
  
  adns_r_hinfo=             13,  
  adns_r_hinfo_mf=              adns_r_hinfo|adns__qtf_mf,
  
  adns_r_mx_raw=            15,
  adns_r_mx=                    adns_r_mx_raw|adns__qtf_deref,
  adns_r_mx_mf=                 adns_r_mx_raw|adns__qtf_mf,
  
  adns_r_txt=               16,
  adns_r_txt_mf=                adns_r_txt|adns__qtf_mf,
  
  adns_r_rp_raw=            17,
  adns_r_rp=                    adns_r_rp_raw|adns__qtf_mail822
  adns_r_rp_mf=                 adns_r_rp_raw|adns__qtf_mf,
  
} adns_rrtype;

/* In queries without qtf_anyquote, all domains must have standard
 * legal syntax.  In queries _with_ qtf_anyquote, domains in the query
 * or response may contain any characters, quoted according to
 * RFC1035 5.1.  On input to adns, the char* is a pointer to the
 * interior of a " delimited string, except that " may appear in it,
 * and on output, the char* is a pointer to a string which would be
 * legal either inside or outside " delimiters, and any characters
 * not usually legal in domain names will be quoted as \X
 * (if the character is 33-126 except \ and ") or \DDD.
 *
 * _qtf_anyquote is ignored for _mf queries.
 *
 * Do not ask for _raw records containing mailboxes without
 * specifying _qf_anyquote.
 */

typedef enum {
  adns_s_ok,
  adns_s_timeout,
  adns_s_unknownqtype,
  adns_s_nolocalmem,
  adns_s_allservfail,
  adns_s_max_tempfail= 99,
  adns_s_inconsistent, /* PTR gives domain whose A does not match */
  adns_s_cname, /* CNAME found where data eg A expected (not if _qf_loosecname) */
  adns_s_max_misconfig= 199;
  adns_s_nxdomain,
  adns_s_norecord,
  adns_s_invaliddomain
} adns_status;

typedef struct {
  char *dm;
  adns_status astatus;
  int naddrs; /* temp fail => -1, perm fail => 0, s_ok => >0 */
  struct in_addr *addrs;
} adns_dmaddr;

typedef struct {
  adns_status status;
  char *cname; /* always NULL if query was for CNAME records */
  adns_rrtype type;
  int nrrs;
  union {
    struct in_addr inaddr[1];                                                    /* a */
    char (*str)[1];                     /* ns_raw, cname, ptr, ptr_raw, txt, <any>_mf */
    adns_dmaddr dmaddr[1];                                                      /* ns */
    struct { char *a, *b; } strpair[1];                          /* hinfo, rp, rp_raw */
    struct { int pref; adns_dmaddrs dmaddr; } intdmaddr[1];                     /* mx */
    struct { int pref; char *str; } intstr[1];                              /* mx_raw */
    struct {
      char *ns0, *rp;
      unsigned long serial, refresh, retry, expire, minimum;
    } soa[1];                                                         /* soa, soa_raw */
    /* NULL is empty */
  } rrs;
} adns_answer;

/* Memory management:
 *  adns_state and adns_query are actually pointers to malloc'd state;
 *  On submission questions are copied, including the owner domain;
 *  Answers are malloc'd as a single piece of memory.
 * query_io:
 *  Must always be non-null pointer;
 *  If *query_io is 0 to start with then any query may be returned;
 *  If *query_io is !0 adns_query then only that query may be returned.
 * Errors:
 *  Return values are 0 or an errno value;
 *  Seriously fatal system errors (eg, failure to create sockets,
 *  malloc failure, etc.) return errno values;
 *  Other errors (nameserver failure, timed out connections, &c)
 *  are returned in the status field of the answer.  If status is
 *  nonzero then nrrs will be 0, otherwise it will be >0.
 *  type will always be the type requested;
 *  If no (appropriate) requests are done adns_check returns EWOULDBLOCK;
 *  If no (appropriate) requests are outstanding adns_query and adns_wait return ESRCH;
 *  If malloc failure occurs during internal allocation or processing
 *  ands_check and _wait set *answer to 0.
 */

int adns_init(adns_state *newstate_r, adns_initflags flags, FILE *diagfile/*0=>stderr*/);

int adns_synchronous(adns_state ads,
		     const char *owner,
		     adns_rrtype type,
		     adns_queryflags flags,
		     adns_answer **answer_r);
/* Will not return EINTR. */

/* NB: if you set adns_if_noautosys then _submit and _check do not
 * make any system calls; you must use adns_callback (possibly after
 * adns_interest) to actually get things to happen.
 */

int adns_submit(adns_state ads,
		const char *owner,
		adns_rrtype type,
		adns_queryflags flags,
		void *context,
		adns_query *query_r);

int adns_check(adns_state ads,
	       adns_query *query_io,
	       adns_answer **answer_r,
	       void **context_r);

int adns_wait(adns_state ads,
	      adns_query *query_io,
	      adns_answer **answer_r,
	      void **context_r);
/* Might return EINTR - if so, try again */

void adns_cancel(adns_state ads, adns_query query);

int adns_finish(adns_state);

int adns_callback(adns_state, int maxfd, const fd_set *readfds, const fd_set *writefds,
		  const fd_set *exceptfds);
/* Gives adns flow-of-control for a bit.  This will never block.
 * If maxfd == -1 then adns will check (make nonblocking system calls on)
 * all of its own filedescriptors; otherwise it will only use those
 * < maxfd and specified in the fd_set's, as if select had returned them.
 * Other fd's may be in the fd_sets, and will be ignored.
 * _callback returns how many adns fd's were in the various sets, so
 * you can tell if your select handling code has missed something and is going awol.
 */

void adns_interest(adns_state, int *maxfd_io, fd_set *readfds_io,
		   fd_set *writefds_io, fd_set *exceptfds_io,
		   struct timeval **tv_mod, struct timeval *tv_buf);
/* Find out file descriptors adns is interested in, and when it
 * would like the opportunity to time something out.  If you do not plan to
 * block then tv_mod may be 0.  Otherwise, tv_mod may point to 0 meaning
 * you have no timeout of your own, in which case tv_buf must be non-null and
 * _interest may fill it in and set *tv_mod=tv_buf.
 * readfds, writefds, exceptfds and maxfd may not be 0.
 */

/* Example expected/legal calling sequences:
 *  adns_init
 *  adns_submit 1
 *  adns_submit 2
 *  adns_submit 3
 *  adns_wait 1
 *  adns_check 3 -> EWOULDBLOCK
 *  adns_wait 2
 *  adns_wait 3
 *  ....
 *  adns_finish
 *
 *  adns_init _noautosys
 *  loop {
 *   adns_interest
 *   select
 *   adns_callback
 *   ...
 *   adns_submit / adns_check
 *   ...
 *  }
 */

#endif