Annotation of embedaddon/libevent/evdns.h, revision 1.1
1.1 ! misho 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 dedication,
! 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 include
! 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 query.
! 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 query.
! 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 query.
! 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_type 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 query.
! 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_callback_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 *, void *);
! 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_request_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 char *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 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>