/* ========================================================================== * lookup.h - Simple DNS Query Interface * -------------------------------------------------------------------------- * Copyright (c) 2004, 2005, 2006 Barracuda Networks, Inc. * Copyright (c) 2006 William Ahern * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to permit * persons to whom the Software is furnished to do so, subject to the * following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * -------------------------------------------------------------------------- * History * * 2006-04-23 * Completely refactored interface in preparation for adding * cancellations. * * 2006-02-14 (william@25thandClement.com) * Published by Barracuda Networks, originally authored by * employee William Ahern (wahern@barracudanetworks.com). * -------------------------------------------------------------------------- * Description * * Simple DNS query state machine which wraps the c-ares asynchronous client * DNS library. Supports compound queries for one or more of the following * record types: PTR, A, AAAA, CNAME, NS, MX, TXT, SOA and SRV. * * ========================================================================== */ #ifndef EVNET_LOOKUP_H #define EVNET_LOOKUP_H #include /* struct timeval */ #if !_WIN32 #include /* struct sockaddr struct sockaddr_storage */ #include /* struct sockaddr_in struct sockaddr_in6 */ #include /* NI_MAXHOST */ #else #include #include #endif #ifndef NI_MAXHOST #define NI_MAXHOST 1024 #endif #define LOOKUP_SUCCESS(e) (!LOOKUP_FAILURE((e))) #define LOOKUP_FAILURE(e) ((e) & LOOKUP_EBOUNDARY) #define LOOKUP_WARNING(e) ((e) & LOOKUP_WBOUNDARY) #define LOOKUP_MESSAGE(e) ((e) & LOOKUP_MBOUNDARY) #define LOOKUP_E2WARNING(e) \ (LOOKUP_WBOUNDARY \ | ((e) \ & (~(LOOKUP_EBOUNDARY | LOOKUP_MBOUNDARY)) \ ) \ ) #define LOOKUP_W2ERROR(e) \ (LOOKUP_EBOUNDARY \ | ((e) \ & (~(LOOKUP_WBOUNDARY | LOOKUP_MBOUNDARY)) \ ) \ ) enum lookup_type { LOOKUP_IN_PTR = 1 << 0, LOOKUP_IN_A = 1 << 1, LOOKUP_IN_AAAA = 1 << 2, LOOKUP_IN_CNAME = 1 << 3, LOOKUP_IN_NS = 1 << 4, LOOKUP_IN_MX = 1 << 5, LOOKUP_IN_TXT = 1 << 6, LOOKUP_IN_SOA = 1 << 7, LOOKUP_IN_SRV = 1 << 8, }; enum lookup_section { LOOKUP_SECTION_LOCAL = 0, LOOKUP_SECTION_ANSWERS = 1 << 0, LOOKUP_SECTION_AUTHORITY = 1 << 1, LOOKUP_SECTION_ADDITIONAL = 1 << 2, }; enum lookup_flag { LOOKUP_PREFER_A = 1 << 0, LOOKUP_PREFER_AAAA = 1 << 1, LOOKUP_FALLBACK = 1 << 2, }; enum lookup_errno { LOOKUP_ESUCCESS = 0, LOOKUP_EBOUNDARY = 0x0020, /* 32 - 63 */ LOOKUP_ESYSTEM, LOOKUP_ETIMEDOUT, LOOKUP_EARES, LOOKUP_EBAD_FAMILY, LOOKUP_EBAD_RESPONSE, LOOKUP_EEMPTY_RESPONSE, LOOKUP_EUNKNOWN_RESPONSE, LOOKUP_EDUPLICATE_RESPONSE, LOOKUP_ENOTFOUND, LOOKUP_ENODATA, LOOKUP_EBAD_REQUEST, LOOKUP_WBOUNDARY = 0x0040, /* 64 - 127 */ LOOKUP_WSYSTEM, LOOKUP_WTIMEDOUT, LOOKUP_WARES, LOOKUP_WBAD_RESPONSE, LOOKUP_WEMPTY_RESPONSE, LOOKUP_WUNKNOWN_RESPONSE, LOOKUP_WDUPLICATE_RESPONSE, LOOKUP_WNOTFOUND, LOOKUP_WNODATA, LOOKUP_WBAD_REQUEST, LOOKUP_MBOUNDARY = 0x0100, /* 128 - 255 */ LOOKUP_NERR, /* Do not move, do not put anything below. */ }; extern const char *lookup_errlist[]; extern const unsigned lookup_nerr; enum lookup_method { LOOKUP_METHOD_BIND = 1, LOOKUP_METHOD_FILE, #if LOOKUP_CACHE_IMPLEMENTED LOOKUP_METHOD_CACHE, #endif }; struct lookup_options { char *resolv; /* Path to resolv file (/etc/resolv.conf). */ char *hosts; /* Path to hosts file (/etc/hosts). */ #if LOOKUP_CACHE_IMPLEMENTED enum lookup_method order[3]; /* Lookup order, usually cache, file, bind. */ #else enum lookup_method order[2]; /* Lookup order, usually file, bind. */ #endif int loan_answers; /* If 0, then lookup_rr structures * will be automatically freed upon * return from the callback. * Otherwise, lookup_rr_free() must * be used to free the answers. */ #if LOOKUP_CACHE_IMPLEMENTED unsigned cache_max; /* Maximum number of queries to cache. */ char *cache_map; /* Path to shared cache memory map. */ #endif unsigned chain_max; /* Maximum length of CNAME chains * tolerated. */ unsigned query_max; /* Maximum number of live queries to * issue per lookup request (limit * excessive work for compound * queries). */ unsigned nchannels; /* Maximum number of C-Ares channels * to employ. Currently ALL are * instantiated up-front, rather * than incrementally. */ }; extern const struct lookup_options lookup_defaults; /* * Query resource record. */ struct lookup_rr { enum lookup_type type; enum lookup_section section; char qname[NI_MAXHOST]; size_t qnamelen; unsigned ttl; union { struct { unsigned short preference; char host[NI_MAXHOST]; size_t hostlen; } mx; struct { union { struct sockaddr sa; struct sockaddr_in sin; #if USE_IPV6 struct sockaddr_in6 sin6; #endif struct sockaddr_storage ss; } sa; size_t salen; } ip; struct { char host[NI_MAXHOST]; size_t hostlen; char mbox[NI_MAXHOST]; size_t mboxlen; unsigned int serial; int refresh; int retry; int expire; unsigned int minimum; } soa; struct { char host[NI_MAXHOST]; size_t hostlen; } ptr; struct { char host[NI_MAXHOST]; size_t hostlen; } ns; struct { char data[NI_MAXHOST]; size_t datalen; } txt; struct { char host[NI_MAXHOST]; size_t hostlen; } cname; struct { unsigned short priority; unsigned short weight; unsigned short port; char host[NI_MAXHOST]; size_t hostlen; } srv; } rr; struct lookup_rr *next; #ifdef LIBEVNET_SOURCE int resolved; int followed; struct lookup_rr *alias; unsigned long srvsum; LIST_ENTRY(lookup_rr) le; #endif }; /* struct lookup_rr */ /* * Synchronous-mode query result. */ struct lookup_result { enum lookup_errno l_errno; int nanswers; struct lookup_rr *answers; int nadditional; struct lookup_rr *additional; #ifdef LIBEVNET_SOURCE struct lookup *lookup; int done; int sys_errno; LIST_HEAD(,lookup_rr) l_answers; LIST_HEAD(,lookup_rr) l_additional; #endif }; /* struct lookup_result */ /* * Helper macro to create timeval structures on-the-fly (and on-the-stack), * using compound literals from C99. */ #if defined(__STDC__) && (__STDC_VERSION__ >= 199901L) #define lookup_tv(s) (&(struct timeval){ (s), 0 }) #endif /* * Declare some structures that might haven't been declared just yet. */ struct lookup; struct arena_prototype; struct event_base; /* * Open and close a lookup resource object. */ struct lookup *lookup_open(const struct lookup_options *, struct event_base *, const struct arena_prototype *); void lookup_close(struct lookup *); /* * Core lookup routine. */ typedef void (*lookup_return)(int, struct lookup_rr *, int, struct lookup_rr *, enum lookup_errno, void *); void lookup_result_free(struct lookup *, struct lookup_result *); void lookup_rr_free(struct lookup *, struct lookup_rr *); struct lookup_result *lookup_rr(struct lookup *, const char *, size_t, int, int, lookup_return, void *, struct timeval *); struct lookup_result *lookup_ptr(struct lookup *, struct sockaddr *, socklen_t, int, lookup_return, void *, struct timeval *); /* * Error descriptions. */ enum lookup_errno lookup_errno(struct lookup *); const char *lookup_strerror(struct lookup *); /* * Simplified, namesake interface. */ enum lookup_errno lookup_init(const struct lookup_options *, struct event_base *, const struct arena_prototype *); enum lookup_errno lookup_reset(const struct lookup_options *, struct event_base *, const struct arena_prototype *); struct lookup_result *lookup(const char *, size_t, int, int, lookup_return, void *, struct timeval *); struct lookup_result *rlookup(struct sockaddr *, socklen_t, int, lookup_return, void *, struct timeval *); #endif /* EVNET_LOOKUP_H */