OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2006 Niels Provos <provos@citi.umich.edu> | |
3 * All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
28 /* | |
29 * The original DNS code is due to Adam Langley with heavy | |
30 * modifications by Nick Mathewson. Adam put his DNS software in the | |
31 * public domain. You can find his original copyright below. Please, | |
32 * aware that the code as part of libevent is governed by the 3-clause | |
33 * BSD license above. | |
34 * | |
35 * This software is Public Domain. To view a copy of the public domain dedicatio
n, | |
36 * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to | |
37 * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. | |
38 * | |
39 * I ask and expect, but do not require, that all derivative works contain an | |
40 * attribution similar to: | |
41 * Parts developed by Adam Langley <agl@imperialviolet.org> | |
42 * | |
43 * You may wish to replace the word "Parts" with something else depending on | |
44 * the amount of original code. | |
45 * | |
46 * (Derivative works does not include programs which link against, run or includ
e | |
47 * the source verbatim in their source distributions) | |
48 */ | |
49 | |
50 /** @file evdns.h | |
51 * | |
52 * Welcome, gentle reader | |
53 * | |
54 * Async DNS lookups are really a whole lot harder than they should be, | |
55 * mostly stemming from the fact that the libc resolver has never been | |
56 * very good at them. Before you use this library you should see if libc | |
57 * can do the job for you with the modern async call getaddrinfo_a | |
58 * (see http://www.imperialviolet.org/page25.html#e498). Otherwise, | |
59 * please continue. | |
60 * | |
61 * This code is based on libevent and you must call event_init before | |
62 * any of the APIs in this file. You must also seed the OpenSSL random | |
63 * source if you are using OpenSSL for ids (see below). | |
64 * | |
65 * This library is designed to be included and shipped with your source | |
66 * code. You statically link with it. You should also test for the | |
67 * existence of strtok_r and define HAVE_STRTOK_R if you have it. | |
68 * | |
69 * The DNS protocol requires a good source of id numbers and these | |
70 * numbers should be unpredictable for spoofing reasons. There are | |
71 * three methods for generating them here and you must define exactly | |
72 * one of them. In increasing order of preference: | |
73 * | |
74 * DNS_USE_GETTIMEOFDAY_FOR_ID: | |
75 * Using the bottom 16 bits of the usec result from gettimeofday. This | |
76 * is a pretty poor solution but should work anywhere. | |
77 * DNS_USE_CPU_CLOCK_FOR_ID: | |
78 * Using the bottom 16 bits of the nsec result from the CPU's time | |
79 * counter. This is better, but may not work everywhere. Requires | |
80 * POSIX realtime support and you'll need to link against -lrt on | |
81 * glibc systems at least. | |
82 * DNS_USE_OPENSSL_FOR_ID: | |
83 * Uses the OpenSSL RAND_bytes call to generate the data. You must | |
84 * have seeded the pool before making any calls to this library. | |
85 * | |
86 * The library keeps track of the state of nameservers and will avoid | |
87 * them when they go down. Otherwise it will round robin between them. | |
88 * | |
89 * Quick start guide: | |
90 * #include "evdns.h" | |
91 * void callback(int result, char type, int count, int ttl, | |
92 * void *addresses, void *arg); | |
93 * evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf"); | |
94 * evdns_resolve("www.hostname.com", 0, callback, NULL); | |
95 * | |
96 * When the lookup is complete the callback function is called. The | |
97 * first argument will be one of the DNS_ERR_* defines in evdns.h. | |
98 * Hopefully it will be DNS_ERR_NONE, in which case type will be | |
99 * DNS_IPv4_A, count will be the number of IP addresses, ttl is the time | |
100 * which the data can be cached for (in seconds), addresses will point | |
101 * to an array of uint32_t's and arg will be whatever you passed to | |
102 * evdns_resolve. | |
103 * | |
104 * Searching: | |
105 * | |
106 * In order for this library to be a good replacement for glibc's resolver it | |
107 * supports searching. This involves setting a list of default domains, in | |
108 * which names will be queried for. The number of dots in the query name | |
109 * determines the order in which this list is used. | |
110 * | |
111 * Searching appears to be a single lookup from the point of view of the API, | |
112 * although many DNS queries may be generated from a single call to | |
113 * evdns_resolve. Searching can also drastically slow down the resolution | |
114 * of names. | |
115 * | |
116 * To disable searching: | |
117 * 1. Never set it up. If you never call evdns_resolv_conf_parse or | |
118 * evdns_search_add then no searching will occur. | |
119 * | |
120 * 2. If you do call evdns_resolv_conf_parse then don't pass | |
121 * DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it). | |
122 * | |
123 * 3. When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag. | |
124 * | |
125 * The order of searches depends on the number of dots in the name. If the | |
126 * number is greater than the ndots setting then the names is first tried | |
127 * globally. Otherwise each search domain is appended in turn. | |
128 * | |
129 * The ndots setting can either be set from a resolv.conf, or by calling | |
130 * evdns_search_ndots_set. | |
131 * | |
132 * For example, with ndots set to 1 (the default) and a search domain list of | |
133 * ["myhome.net"]: | |
134 * Query: www | |
135 * Order: www.myhome.net, www. | |
136 * | |
137 * Query: www.abc | |
138 * Order: www.abc., www.abc.myhome.net | |
139 * | |
140 * Internals: | |
141 * | |
142 * Requests are kept in two queues. The first is the inflight queue. In | |
143 * this queue requests have an allocated transaction id and nameserver. | |
144 * They will soon be transmitted if they haven't already been. | |
145 * | |
146 * The second is the waiting queue. The size of the inflight ring is | |
147 * limited and all other requests wait in waiting queue for space. This | |
148 * bounds the number of concurrent requests so that we don't flood the | |
149 * nameserver. Several algorithms require a full walk of the inflight | |
150 * queue and so bounding its size keeps thing going nicely under huge | |
151 * (many thousands of requests) loads. | |
152 * | |
153 * If a nameserver loses too many requests it is considered down and we | |
154 * try not to use it. After a while we send a probe to that nameserver | |
155 * (a lookup for google.com) and, if it replies, we consider it working | |
156 * again. If the nameserver fails a probe we wait longer to try again | |
157 * with the next probe. | |
158 */ | |
159 | |
160 #ifndef EVENTDNS_H | |
161 #define EVENTDNS_H | |
162 | |
163 #ifdef __cplusplus | |
164 extern "C" { | |
165 #endif | |
166 | |
167 /* For integer types. */ | |
168 #include "evutil.h" | |
169 | |
170 /** Error codes 0-5 are as described in RFC 1035. */ | |
171 #define DNS_ERR_NONE 0 | |
172 /** The name server was unable to interpret the query */ | |
173 #define DNS_ERR_FORMAT 1 | |
174 /** The name server was unable to process this query due to a problem with the | |
175 * name server */ | |
176 #define DNS_ERR_SERVERFAILED 2 | |
177 /** The domain name does not exist */ | |
178 #define DNS_ERR_NOTEXIST 3 | |
179 /** The name server does not support the requested kind of query */ | |
180 #define DNS_ERR_NOTIMPL 4 | |
181 /** The name server refuses to reform the specified operation for policy | |
182 * reasons */ | |
183 #define DNS_ERR_REFUSED 5 | |
184 /** The reply was truncated or ill-formated */ | |
185 #define DNS_ERR_TRUNCATED 65 | |
186 /** An unknown error occurred */ | |
187 #define DNS_ERR_UNKNOWN 66 | |
188 /** Communication with the server timed out */ | |
189 #define DNS_ERR_TIMEOUT 67 | |
190 /** The request was canceled because the DNS subsystem was shut down. */ | |
191 #define DNS_ERR_SHUTDOWN 68 | |
192 | |
193 #define DNS_IPv4_A 1 | |
194 #define DNS_PTR 2 | |
195 #define DNS_IPv6_AAAA 3 | |
196 | |
197 #define DNS_QUERY_NO_SEARCH 1 | |
198 | |
199 #define DNS_OPTION_SEARCH 1 | |
200 #define DNS_OPTION_NAMESERVERS 2 | |
201 #define DNS_OPTION_MISC 4 | |
202 #define DNS_OPTIONS_ALL 7 | |
203 | |
204 /** | |
205 * The callback that contains the results from a lookup. | |
206 * - type is either DNS_IPv4_A or DNS_PTR or DNS_IPv6_AAAA | |
207 * - count contains the number of addresses of form type | |
208 * - ttl is the number of seconds the resolution may be cached for. | |
209 * - addresses needs to be cast according to type | |
210 */ | |
211 typedef void (*evdns_callback_type) (int result, char type, int count, int ttl,
void *addresses, void *arg); | |
212 | |
213 /** | |
214 Initialize the asynchronous DNS library. | |
215 | |
216 This function initializes support for non-blocking name resolution by | |
217 calling evdns_resolv_conf_parse() on UNIX and | |
218 evdns_config_windows_nameservers() on Windows. | |
219 | |
220 @return 0 if successful, or -1 if an error occurred | |
221 @see evdns_shutdown() | |
222 */ | |
223 int evdns_init(void); | |
224 | |
225 | |
226 /** | |
227 Shut down the asynchronous DNS resolver and terminate all active requests. | |
228 | |
229 If the 'fail_requests' option is enabled, all active requests will return | |
230 an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise, | |
231 the requests will be silently discarded. | |
232 | |
233 @param fail_requests if zero, active requests will be aborted; if non-zero, | |
234 active requests will return DNS_ERR_SHUTDOWN. | |
235 @see evdns_init() | |
236 */ | |
237 void evdns_shutdown(int fail_requests); | |
238 | |
239 | |
240 /** | |
241 Convert a DNS error code to a string. | |
242 | |
243 @param err the DNS error code | |
244 @return a string containing an explanation of the error code | |
245 */ | |
246 const char *evdns_err_to_string(int err); | |
247 | |
248 | |
249 /** | |
250 Add a nameserver. | |
251 | |
252 The address should be an IPv4 address in network byte order. | |
253 The type of address is chosen so that it matches in_addr.s_addr. | |
254 | |
255 @param address an IP address in network byte order | |
256 @return 0 if successful, or -1 if an error occurred | |
257 @see evdns_nameserver_ip_add() | |
258 */ | |
259 int evdns_nameserver_add(unsigned long int address); | |
260 | |
261 | |
262 /** | |
263 Get the number of configured nameservers. | |
264 | |
265 This returns the number of configured nameservers (not necessarily the | |
266 number of running nameservers). This is useful for double-checking | |
267 whether our calls to the various nameserver configuration functions | |
268 have been successful. | |
269 | |
270 @return the number of configured nameservers | |
271 @see evdns_nameserver_add() | |
272 */ | |
273 int evdns_count_nameservers(void); | |
274 | |
275 | |
276 /** | |
277 Remove all configured nameservers, and suspend all pending resolves. | |
278 | |
279 Resolves will not necessarily be re-attempted until evdns_resume() is called. | |
280 | |
281 @return 0 if successful, or -1 if an error occurred | |
282 @see evdns_resume() | |
283 */ | |
284 int evdns_clear_nameservers_and_suspend(void); | |
285 | |
286 | |
287 /** | |
288 Resume normal operation and continue any suspended resolve requests. | |
289 | |
290 Re-attempt resolves left in limbo after an earlier call to | |
291 evdns_clear_nameservers_and_suspend(). | |
292 | |
293 @return 0 if successful, or -1 if an error occurred | |
294 @see evdns_clear_nameservers_and_suspend() | |
295 */ | |
296 int evdns_resume(void); | |
297 | |
298 | |
299 /** | |
300 Add a nameserver. | |
301 | |
302 This wraps the evdns_nameserver_add() function by parsing a string as an IP | |
303 address and adds it as a nameserver. | |
304 | |
305 @return 0 if successful, or -1 if an error occurred | |
306 @see evdns_nameserver_add() | |
307 */ | |
308 int evdns_nameserver_ip_add(const char *ip_as_string); | |
309 | |
310 | |
311 /** | |
312 Lookup an A record for a given name. | |
313 | |
314 @param name a DNS hostname | |
315 @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this qu
ery. | |
316 @param callback a callback function to invoke when the request is completed | |
317 @param ptr an argument to pass to the callback function | |
318 @return 0 if successful, or -1 if an error occurred | |
319 @see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6
() | |
320 */ | |
321 int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback
, void *ptr); | |
322 | |
323 | |
324 /** | |
325 Lookup an AAAA record for a given name. | |
326 | |
327 @param name a DNS hostname | |
328 @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this qu
ery. | |
329 @param callback a callback function to invoke when the request is completed | |
330 @param ptr an argument to pass to the callback function | |
331 @return 0 if successful, or -1 if an error occurred | |
332 @see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6
() | |
333 */ | |
334 int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback
, void *ptr); | |
335 | |
336 struct in_addr; | |
337 struct in6_addr; | |
338 | |
339 /** | |
340 Lookup a PTR record for a given IP address. | |
341 | |
342 @param in an IPv4 address | |
343 @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this qu
ery. | |
344 @param callback a callback function to invoke when the request is completed | |
345 @param ptr an argument to pass to the callback function | |
346 @return 0 if successful, or -1 if an error occurred | |
347 @see evdns_resolve_reverse_ipv6() | |
348 */ | |
349 int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_ty
pe callback, void *ptr); | |
350 | |
351 | |
352 /** | |
353 Lookup a PTR record for a given IPv6 address. | |
354 | |
355 @param in an IPv6 address | |
356 @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this qu
ery. | |
357 @param callback a callback function to invoke when the request is completed | |
358 @param ptr an argument to pass to the callback function | |
359 @return 0 if successful, or -1 if an error occurred | |
360 @see evdns_resolve_reverse_ipv6() | |
361 */ | |
362 int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callb
ack_type callback, void *ptr); | |
363 | |
364 | |
365 /** | |
366 Set the value of a configuration option. | |
367 | |
368 The currently available configuration options are: | |
369 | |
370 ndots, timeout, max-timeouts, max-inflight, and attempts | |
371 | |
372 @param option the name of the configuration option to be modified | |
373 @param val the value to be set | |
374 @param flags either 0 | DNS_OPTION_SEARCH | DNS_OPTION_MISC | |
375 @return 0 if successful, or -1 if an error occurred | |
376 */ | |
377 int evdns_set_option(const char *option, const char *val, int flags); | |
378 | |
379 | |
380 /** | |
381 Parse a resolv.conf file. | |
382 | |
383 The 'flags' parameter determines what information is parsed from the | |
384 resolv.conf file. See the man page for resolv.conf for the format of this | |
385 file. | |
386 | |
387 The following directives are not parsed from the file: sortlist, rotate, | |
388 no-check-names, inet6, debug. | |
389 | |
390 If this function encounters an error, the possible return values are: 1 = | |
391 failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of | |
392 memory, 5 = short read from file, 6 = no nameservers listed in the file | |
393 | |
394 @param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC| | |
395 DNS_OPTIONS_ALL | |
396 @param filename the path to the resolv.conf file | |
397 @return 0 if successful, or various positive error codes if an error | |
398 occurred (see above) | |
399 @see resolv.conf(3), evdns_config_windows_nameservers() | |
400 */ | |
401 int evdns_resolv_conf_parse(int flags, const char *const filename); | |
402 | |
403 | |
404 /** | |
405 Obtain nameserver information using the Windows API. | |
406 | |
407 Attempt to configure a set of nameservers based on platform settings on | |
408 a win32 host. Preferentially tries to use GetNetworkParams; if that fails, | |
409 looks in the registry. | |
410 | |
411 @return 0 if successful, or -1 if an error occurred | |
412 @see evdns_resolv_conf_parse() | |
413 */ | |
414 #ifdef WIN32 | |
415 int evdns_config_windows_nameservers(void); | |
416 #endif | |
417 | |
418 | |
419 /** | |
420 Clear the list of search domains. | |
421 */ | |
422 void evdns_search_clear(void); | |
423 | |
424 | |
425 /** | |
426 Add a domain to the list of search domains | |
427 | |
428 @param domain the domain to be added to the search list | |
429 */ | |
430 void evdns_search_add(const char *domain); | |
431 | |
432 | |
433 /** | |
434 Set the 'ndots' parameter for searches. | |
435 | |
436 Sets the number of dots which, when found in a name, causes | |
437 the first query to be without any search domain. | |
438 | |
439 @param ndots the new ndots parameter | |
440 */ | |
441 void evdns_search_ndots_set(const int ndots); | |
442 | |
443 /** | |
444 A callback that is invoked when a log message is generated | |
445 | |
446 @param is_warning indicates if the log message is a 'warning' | |
447 @param msg the content of the log message | |
448 */ | |
449 typedef void (*evdns_debug_log_fn_type)(int is_warning, const char *msg); | |
450 | |
451 | |
452 /** | |
453 Set the callback function to handle log messages. | |
454 | |
455 @param fn the callback to be invoked when a log message is generated | |
456 */ | |
457 void evdns_set_log_fn(evdns_debug_log_fn_type fn); | |
458 | |
459 /** | |
460 Set a callback that will be invoked to generate transaction IDs. By | |
461 default, we pick transaction IDs based on the current clock time. | |
462 | |
463 @param fn the new callback, or NULL to use the default. | |
464 */ | |
465 void evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void)); | |
466 | |
467 #define DNS_NO_SEARCH 1 | |
468 | |
469 /* | |
470 * Structures and functions used to implement a DNS server. | |
471 */ | |
472 | |
473 struct evdns_server_request { | |
474 int flags; | |
475 int nquestions; | |
476 struct evdns_server_question **questions; | |
477 }; | |
478 struct evdns_server_question { | |
479 int type; | |
480 #ifdef __cplusplus | |
481 int dns_question_class; | |
482 #else | |
483 /* You should refer to this field as "dns_question_class". The | |
484 * name "class" works in C for backward compatibility, and will be | |
485 * removed in a future version. (1.5 or later). */ | |
486 int class; | |
487 #define dns_question_class class | |
488 #endif | |
489 char name[1]; | |
490 }; | |
491 typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, vo
id *); | |
492 #define EVDNS_ANSWER_SECTION 0 | |
493 #define EVDNS_AUTHORITY_SECTION 1 | |
494 #define EVDNS_ADDITIONAL_SECTION 2 | |
495 | |
496 #define EVDNS_TYPE_A 1 | |
497 #define EVDNS_TYPE_NS 2 | |
498 #define EVDNS_TYPE_CNAME 5 | |
499 #define EVDNS_TYPE_SOA 6 | |
500 #define EVDNS_TYPE_PTR 12 | |
501 #define EVDNS_TYPE_MX 15 | |
502 #define EVDNS_TYPE_TXT 16 | |
503 #define EVDNS_TYPE_AAAA 28 | |
504 | |
505 #define EVDNS_QTYPE_AXFR 252 | |
506 #define EVDNS_QTYPE_ALL 255 | |
507 | |
508 #define EVDNS_CLASS_INET 1 | |
509 | |
510 struct evdns_server_port *evdns_add_server_port(int socket, int is_tcp, evdns_re
quest_callback_fn_type callback, void *user_data); | |
511 void evdns_close_server_port(struct evdns_server_port *port); | |
512 | |
513 int evdns_server_request_add_reply(struct evdns_server_request *req, int section
, const char *name, int type, int dns_class, int ttl, int datalen, int is_name,
const char *data); | |
514 int evdns_server_request_add_a_reply(struct evdns_server_request *req, const cha
r *name, int n, void *addrs, int ttl); | |
515 int evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const
char *name, int n, void *addrs, int ttl); | |
516 int evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct
in_addr *in, const char *inaddr_name, const char *hostname, int ttl); | |
517 int evdns_server_request_add_cname_reply(struct evdns_server_request *req, const
char *name, const char *cname, int ttl); | |
518 | |
519 int evdns_server_request_respond(struct evdns_server_request *req, int err); | |
520 int evdns_server_request_drop(struct evdns_server_request *req); | |
521 struct sockaddr; | |
522 int evdns_server_request_get_requesting_addr(struct evdns_server_request *_req,
struct sockaddr *sa, int addr_len); | |
523 | |
524 #ifdef __cplusplus | |
525 } | |
526 #endif | |
527 | |
528 #endif /* !EVENTDNS_H */ | |
OLD | NEW |