15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* $Id: evdns.c 6979 2006-08-04 18:31:13Z nickm $ */ 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The original version of this module was written by Adam Langley; for 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a history of modifications, check out the subversion logs. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * When editing this module, try to keep it re-mergeable by Adam. Don't 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * reformat the whitespace, add Tor dependencies, or so on. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * TODO: 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - Support IPv6 and PTR records. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - Replace all externally visible magic numbers with #defined constants. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - Write doccumentation for APIs of all external functions. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Async DNS Library 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Adam Langley <agl@imperialviolet.org> 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.imperialviolet.org/eventdns.html 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Public Domain code 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This software is Public Domain. To view a copy of the public domain dedication, 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * I ask and expect, but do not require, that all derivative works contain an 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * attribution similar to: 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parts developed by Adam Langley <agl@imperialviolet.org> 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You may wish to replace the word "Parts" with something else depending on 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the amount of original code. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (Derivative works does not include programs which link against, run or include 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the source verbatim in their source distributions) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version: 0.1b 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_CONFIG_H 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DNS_USE_FTIME_FOR_ID 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/timeb.h> 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef DNS_USE_CPU_CLOCK_FOR_ID 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef DNS_USE_GETTIMEOFDAY_FOR_ID 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef DNS_USE_OPENSSL_FOR_ID 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef DNS_USE_FTIME_FOR_ID 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error Must configure at least one id generation method. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error Please see the documentation. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* #define _POSIX_C_SOURCE 200507 */ 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _GNU_SOURCE 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DNS_USE_CPU_CLOCK_FOR_ID 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DNS_USE_OPENSSL_FOR_ID 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error Multiple id options selected 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DNS_USE_GETTIMEOFDAY_FOR_ID 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error Multiple id options selected 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h> 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DNS_USE_OPENSSL_FOR_ID 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DNS_USE_GETTIMEOFDAY_FOR_ID 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error Multiple id options selected 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/rand.h> 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef _FORTIFY_SOURCE 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _FORTIFY_SOURCE 3 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_TIME_H 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h> 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_STDINT_H 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h> 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h> 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_UNISTD_H 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits.h> 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h> 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h> 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h> 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "evdns.h" 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "evutil.h" 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "log.h" 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winsock2.h> 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iphlpapi.h> 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <io.h> 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h> 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/in.h> 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <arpa/inet.h> 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_NETINET_IN6_H 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/in6.h> 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define EVDNS_LOG_DEBUG 0 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define EVDNS_LOG_WARN 1 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HOST_NAME_MAX 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HOST_NAME_MAX 255 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef MIN 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MIN(a,b) ((a)<(b)?(a):(b)) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __USE_ISOC99B 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* libevent doesn't work without this */ 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef ev_uint8_t u_char; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef unsigned int uint; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "event.h" 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define u64 ev_uint64_t 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define u32 ev_uint32_t 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define u16 ev_uint16_t 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define u8 ev_uint8_t 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define open _open 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define read _read 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define close _close 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define strdup _strdup 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_ADDRS 32 /* maximum number of addresses from a single packet */ 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* which we bother recording */ 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TYPE_A EVDNS_TYPE_A 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TYPE_CNAME 5 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TYPE_PTR EVDNS_TYPE_PTR 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TYPE_AAAA EVDNS_TYPE_AAAA 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CLASS_INET EVDNS_CLASS_INET 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct request { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 *request; /* the dns packet data */ 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int request_len; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int reissue_count; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tx_count; /* the number of times that this packet has been sent */ 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int request_type; /* TYPE_PTR or TYPE_A */ 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_pointer; /* the pointer given to us for this request */ 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_callback_type user_callback; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct nameserver *ns; /* the server which we last sent it */ 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* elements used by the searching code */ 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int search_index; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct search_state *search_state; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *search_origname; /* needs to be free()ed */ 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int search_flags; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* these objects are kept in a circular list */ 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *next, *prev; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct event timeout_event; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 trans_id; /* the transaction id */ 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char request_appended; /* true if the request pointer is data which follows this struct */ 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char transmit_me; /* needs to be transmitted */ 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HAVE_STRUCT_IN6_ADDR 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct in6_addr { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 s6_addr[16]; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct reply { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int type; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int have_answer; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) union { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 addrcount; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 addresses[MAX_ADDRS]; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } a; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 addrcount; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct in6_addr addresses[MAX_ADDRS]; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } aaaa; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char name[HOST_NAME_MAX]; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } ptr; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } data; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct nameserver { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int socket; /* a connected UDP socket */ 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 address; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 port; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int failed_times; /* number of times which we have given this server a chance */ 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int timedout; /* number of times in a row a request has timed out */ 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct event event; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* these objects are kept in a circular list */ 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct nameserver *next, *prev; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct event timeout_event; /* used to keep the timeout for */ 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* when we next probe this server. */ 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Valid if state == 0 */ 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char state; /* zero if we think that this server is down */ 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char choked; /* true if we have an EAGAIN from this server's socket */ 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char write_waiting; /* true if we are waiting for EV_WRITE events */ 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct request *req_head = NULL, *req_waiting_head = NULL; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct nameserver *server_head = NULL; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Represents a local port where we're listening for DNS requests. Right now, */ 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* only UDP is supported. */ 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct evdns_server_port { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int socket; /* socket we use to read queries and write replies. */ 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int refcnt; /* reference count. */ 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char choked; /* Are we currently blocked from writing? */ 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char closing; /* Are we trying to close this port, pending writes? */ 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_request_callback_fn_type user_callback; /* Fn to handle requests */ 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data; /* Opaque pointer passed to user_callback */ 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct event event; /* Read/write event */ 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* circular list of replies that we want to write. */ 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_request *pending_replies; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Represents part of a reply being built. (That is, a single RR.) */ 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct server_reply_item { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_reply_item *next; /* next item in sequence. */ 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *name; /* name part of the RR */ 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 type : 16; /* The RR type */ 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 class : 16; /* The RR class (usually CLASS_INET) */ 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 ttl; /* The RR TTL */ 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char is_name; /* True iff data is a label */ 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 datalen; /* Length of data; -1 if data is a label */ 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *data; /* The contents of the RR */ 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Represents a request that we've received as a DNS server, and holds */ 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* the components of the reply as we're constructing it. */ 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct server_request { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Pointers to the next and previous entries on the list of replies */ 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* that we're waiting to write. Only set if we have tried to respond */ 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* and gotten EAGAIN. */ 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_request *next_pending; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_request *prev_pending; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 trans_id; /* Transaction id. */ 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evdns_server_port *port; /* Which port received this request on? */ 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_storage addr; /* Where to send the response */ 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socklen_t addrlen; /* length of addr */ 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n_answer; /* how many answer RRs have been set? */ 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n_authority; /* how many authority RRs have been set? */ 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n_additional; /* how many additional RRs have been set? */ 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_reply_item *answer; /* linked list of answer RRs */ 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_reply_item *authority; /* linked list of authority RRs */ 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_reply_item *additional; /* linked list of additional RRs */ 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Constructed response. Only set once we're ready to send a reply. */ 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Once this is set, the RR fields are cleared, and no more should be set. */ 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *response; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t response_len; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Caller-visible fields: flags, questions. */ 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evdns_server_request base; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* helper macro */ 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OFFSET_OF(st, member) ((off_t) (((char*)&((st*)0)->member)-(char*)0)) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Given a pointer to an evdns_server_request, get the corresponding */ 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* server_request. */ 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TO_SERVER_REQUEST(base_ptr) \ 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((struct server_request*) \ 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (((char*)(base_ptr) - OFFSET_OF(struct server_request, base)))) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The number of good nameservers that we have */ 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int global_good_nameservers = 0; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* inflight requests are contained in the req_head list */ 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* and are actually going out across the network */ 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int global_requests_inflight = 0; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* requests which aren't inflight are in the waiting list */ 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* and are counted here */ 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int global_requests_waiting = 0; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int global_max_requests_inflight = 64; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct timeval global_timeout = {5, 0}; /* 5 seconds */ 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int global_max_reissues = 1; /* a reissue occurs when we get some errors from the server */ 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int global_max_retransmits = 3; /* number of times we'll retransmit a request which timed out */ 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* number of timeouts in a row before we consider this server to be down */ 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int global_max_nameserver_timeout = 3; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* These are the timeout values for nameservers. If we find a nameserver is down */ 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* we try to probe it at intervals as given below. Values are in seconds. */ 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const struct timeval global_nameserver_timeouts[] = {{10, 0}, {60, 0}, {300, 0}, {900, 0}, {3600, 0}}; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int global_nameserver_timeouts_length = sizeof(global_nameserver_timeouts)/sizeof(struct timeval); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct nameserver *nameserver_pick(void); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void evdns_request_insert(struct request *req, struct request **head); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void nameserver_ready_callback(int fd, short events, void *arg); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int evdns_transmit(void); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int evdns_request_transmit(struct request *req); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void nameserver_send_probe(struct nameserver *const ns); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void search_request_finished(struct request *const); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int search_try_next(struct request *const req); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int search_request_new(int type, const char *const name, int flags, evdns_callback_type user_callback, void *user_arg); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void evdns_requests_pump_waiting_queue(void); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static u16 transaction_id_pick(void); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct request *request_new(int type, const char *name, int flags, evdns_callback_type callback, void *ptr); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void request_submit(struct request *const req); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int server_request_free(struct server_request *req); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void server_request_free_answers(struct server_request *req); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void server_port_free(struct evdns_server_port *port); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void server_port_ready_callback(int fd, short events, void *arg); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int strtoint(const char *const str); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)last_error(int sock) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int optval, optvallen=sizeof(optval); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int err = WSAGetLastError(); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (err == WSAEWOULDBLOCK && sock >= 0) { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &optvallen)) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return err; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (optval) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return optval; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return err; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error_is_eagain(int err) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return err == EAGAIN || err == WSAEWOULDBLOCK; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inet_aton(const char *c, struct in_addr *addr) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ev_uint32_t r; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strcmp(c, "255.255.255.255") == 0) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr->s_addr = 0xffffffffu; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = inet_addr(c); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r == INADDR_NONE) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr->s_addr = r; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define last_error(sock) (errno) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define error_is_eagain(err) ((err) == EAGAIN) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CLOSE_SOCKET(s) EVUTIL_CLOSESOCKET(s) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ISSPACE(c) isspace((int)(unsigned char)(c)) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ISDIGIT(c) isdigit((int)(unsigned char)(c)) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char * 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)debug_ntoa(u32 address) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static char buf[32]; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 a = ntohl(address); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d", 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a>>24)&0xff), 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a>>16)&0xff), 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a>>8 )&0xff), 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a )&0xff)); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buf; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static evdns_debug_log_fn_type evdns_log_fn = NULL; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_set_log_fn(evdns_debug_log_fn_type fn) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_log_fn = fn; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__ 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define EVDNS_LOG_CHECK __attribute__ ((format(printf, 2, 3))) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define EVDNS_LOG_CHECK 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void _evdns_log(int warn, const char *fmt, ...) EVDNS_LOG_CHECK; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_evdns_log(int warn, const char *fmt, ...) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_list args; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static char buf[512]; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!evdns_log_fn) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_start(args,fmt); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_vsnprintf(buf, sizeof(buf), fmt, args); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[sizeof(buf)-1] = '\0'; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_log_fn(warn, buf); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_end(args); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define log _evdns_log 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This walks the list of inflight requests to find the */ 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* one with a matching transaction id. Returns NULL on */ 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* failure */ 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct request * 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)request_find_from_trans_id(u16 trans_id) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *req = req_head, *const started_at = req_head; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req) { 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->trans_id == trans_id) return req; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = req->next; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (req != started_at); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* a libevent callback function which is called when a nameserver */ 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* has gone down and we want to test if it has came back to life yet */ 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nameserver_prod_callback(int fd, short events, void *arg) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct nameserver *const ns = (struct nameserver *) arg; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)fd; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)events; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_send_probe(ns); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* a libevent callback which is called when a nameserver probe (to see if */ 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* it has come back to life) times out. We increment the count of failed_times */ 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* and wait longer to send the next probe packet. */ 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nameserver_probe_failed(struct nameserver *const ns) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct timeval * timeout; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) evtimer_del(&ns->timeout_event); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ns->state == 1) { 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This can happen if the nameserver acts in a way which makes us mark */ 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* it as bad and then starts sending good replies. */ 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timeout = 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &global_nameserver_timeouts[MIN(ns->failed_times, 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_nameserver_timeouts_length - 1)]; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->failed_times++; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evtimer_add(&ns->timeout_event, (struct timeval *) timeout) < 0) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Error from libevent when adding timer event for %s", 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_ntoa(ns->address)); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* ???? Do more? */ 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* called when a nameserver has been deemed to have failed. For example, too */ 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* many packets have timed out etc */ 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nameserver_failed(struct nameserver *const ns, const char *msg) { 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *req, *started_at; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if this nameserver has already been marked as failed */ 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* then don't do anything */ 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ns->state) return; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Nameserver %s has failed: %s", 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_ntoa(ns->address), msg); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_good_nameservers--; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(global_good_nameservers >= 0); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (global_good_nameservers == 0) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "All nameservers have failed"); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->state = 0; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->failed_times = 1; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evtimer_add(&ns->timeout_event, (struct timeval *) &global_nameserver_timeouts[0]) < 0) { 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Error from libevent when adding timer event for %s", 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_ntoa(ns->address)); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* ???? Do more? */ 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* walk the list of inflight requests to see if any can be reassigned to */ 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* a different server. Requests in the waiting queue don't have a */ 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* nameserver assigned yet */ 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if we don't have *any* good nameservers then there's no point */ 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* trying to reassign requests to one */ 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!global_good_nameservers) return; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = req_head; 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_at = req_head; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->tx_count == 0 && req->ns == ns) { 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* still waiting to go out, can be moved */ 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* to another server */ 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ns = nameserver_pick(); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = req->next; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (req != started_at); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nameserver_up(struct nameserver *const ns) { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ns->state) return; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Nameserver %s is back up", 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_ntoa(ns->address)); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evtimer_del(&ns->timeout_event); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->state = 1; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->failed_times = 0; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->timedout = 0; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_good_nameservers++; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)request_trans_id_set(struct request *const req, const u16 trans_id) { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->trans_id = trans_id; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *((u16 *) req->request) = htons(trans_id); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Called to remove a request from a list and dealloc it. */ 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* head is a pointer to the head of the list it should be */ 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* removed from or NULL if the request isn't in a list. */ 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)request_finished(struct request *const req, struct request **head) { 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (head) { 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->next == req) { 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* only item in the list */ 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *head = NULL; 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->next->prev = req->prev; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->prev->next = req->next; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*head == req) *head = req->next; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Removing timeout for request %lx", 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (unsigned long) req); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evtimer_del(&req->timeout_event); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_request_finished(req); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_requests_inflight--; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req->request_appended) { 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* need to free the request data on it's own */ 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->request); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the request data is appended onto the header */ 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* so everything gets free()ed when we: */ 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_requests_pump_waiting_queue(); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This is called when a server returns a funny error code. */ 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* We try the request again with another server. */ 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* */ 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* return: */ 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 0 ok */ 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1 failed/reissue is pointless */ 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)request_reissue(struct request *req) { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct nameserver *const last_ns = req->ns; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the last nameserver should have been marked as failing */ 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* by the caller of this function, therefore pick will try */ 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* not to return it */ 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ns = nameserver_pick(); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->ns == last_ns) { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* ... but pick did return it */ 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* not a lot of point in trying again with the */ 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* same server */ 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->reissue_count++; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->tx_count = 0; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->transmit_me = 1; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* this function looks for space on the inflight queue and promotes */ 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* requests from the waiting queue if it can. */ 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_requests_pump_waiting_queue(void) { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (global_requests_inflight < global_max_requests_inflight && 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_requests_waiting) { 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *req; 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* move a request from the waiting queue to the inflight queue */ 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(req_waiting_head); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req_waiting_head->next == req_waiting_head) { 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* only one item in the queue */ 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = req_waiting_head; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req_waiting_head = NULL; 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = req_waiting_head; 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->next->prev = req->prev; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->prev->next = req->next; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req_waiting_head = req->next; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_requests_waiting--; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_requests_inflight++; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ns = nameserver_pick(); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_trans_id_set(req, transaction_id_pick()); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_request_insert(req, &req_head); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_request_transmit(req); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_transmit(); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)reply_callback(struct request *const req, u32 ttl, u32 err, struct reply *reply) { 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (req->request_type) { 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TYPE_A: 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reply) 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_callback(DNS_ERR_NONE, DNS_IPv4_A, 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply->data.a.addrcount, ttl, 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply->data.a.addresses, 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_pointer); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_callback(err, 0, 0, 0, NULL, req->user_pointer); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TYPE_PTR: 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reply) { 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *name = reply->data.ptr.name; 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_callback(DNS_ERR_NONE, DNS_PTR, 1, ttl, 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &name, req->user_pointer); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_callback(err, 0, 0, 0, NULL, 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_pointer); 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TYPE_AAAA: 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reply) 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_callback(DNS_ERR_NONE, DNS_IPv6_AAAA, 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply->data.aaaa.addrcount, ttl, 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply->data.aaaa.addresses, 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_pointer); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_callback(err, 0, 0, 0, NULL, req->user_pointer); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(0); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* this processes a parsed reply packet */ 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply) { 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error; 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int error_codes[] = { 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DNS_ERR_FORMAT, DNS_ERR_SERVERFAILED, DNS_ERR_NOTEXIST, 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DNS_ERR_NOTIMPL, DNS_ERR_REFUSED 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & 0x020f || !reply || !reply->have_answer) { 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* there was an error */ 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & 0x0200) { 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = DNS_ERR_TRUNCATED; 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 error_code = (flags & 0x000f) - 1; 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_code > 4) { 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = DNS_ERR_UNKNOWN; 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = error_codes[error_code]; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch(error) { 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_NOTIMPL: 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_REFUSED: 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we regard these errors as marking a bad nameserver */ 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->reissue_count < global_max_reissues) { 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char msg[64]; 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_snprintf(msg, sizeof(msg), 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Bad response %d (%s)", 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error, evdns_err_to_string(error)); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_failed(req->ns, msg); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!request_reissue(req)) return; 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_SERVERFAILED: 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* rcode 2 (servfailed) sometimes means "we 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are broken" and sometimes (with some binds) 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * means "that request was very confusing." 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Treat this as a timeout, not a failure. 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Got a SERVERFAILED from nameserver %s; " 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "will allow the request to time out.", 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_ntoa(req->ns->address)); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we got a good reply from the nameserver */ 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_up(req->ns); 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->search_state && req->request_type != TYPE_PTR) { 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if we have a list of domains to search in, 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * try the next one */ 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!search_try_next(req)) { 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* a new request was issued so this 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * request is finished and */ 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the user callback will be made when 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that request (or a */ 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* child of it) finishes. */ 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_finished(req, &req_head); 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* all else failed. Pass the failure up */ 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_callback(req, 0, error, NULL); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_finished(req, &req_head); 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* all ok, tell the user */ 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_callback(req, ttl, 0, reply); 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_up(req->ns); 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_finished(req, &req_head); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) { 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int name_end = -1; 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j = *idx; 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ptr_count = 0; 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GET32(x) do { if (j + 4 > length) goto err; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while(0) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GET16(x) do { if (j + 2 > length) goto err; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while(0) 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while(0) 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *cp = name_out; 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const end = name_out + name_out_len; 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Normally, names are a series of length prefixed strings terminated */ 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* with a length of 0 (the lengths are u8's < 63). */ 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* However, the length can start with a pair of 1 bits and that */ 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* means that the next 14 bits are a pointer within the current */ 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* packet. */ 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(;;) { 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 label_len; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j >= length) return -1; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET8(label_len); 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!label_len) break; 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (label_len & 0xc0) { 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 ptr_low; 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET8(ptr_low); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_end < 0) name_end = j; 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j = (((int)label_len & 0x3f) << 8) + ptr_low; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make sure that the target offset is in-bounds. */ 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j < 0 || j >= length) return -1; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If we've jumped more times than there are characters in the 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * message, we must have a loop. */ 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (++ptr_count > length) return -1; 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (label_len > 63) return -1; 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cp != name_out) { 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cp + 1 >= end) return -1; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cp++ = '.'; 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cp + label_len >= end) return -1; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(cp, packet + j, label_len); 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cp += label_len; 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += label_len; 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cp >= end) return -1; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cp = '\0'; 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_end < 0) 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *idx = j; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *idx = name_end; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err: 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* parses a raw request from a nameserver */ 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)reply_parse(u8 *packet, int length) { 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j = 0, k = 0; /* index into packet */ 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 _t; /* used by the macros */ 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 _t32; /* used by the macros */ 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char tmp_name[256], cmp_name[256]; /* used by the macros */ 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 trans_id, questions, answers, authority, additional, datalength; 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 flags = 0; 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 ttl, ttl_r = 0xffffffff; 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct reply reply; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *req = NULL; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int i; 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(trans_id); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(flags); 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(questions); 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(answers); 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(authority); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(additional); 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) authority; /* suppress "unused variable" warnings. */ 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) additional; /* suppress "unused variable" warnings. */ 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = request_find_from_trans_id(trans_id); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req) return -1; 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&reply, 0, sizeof(reply)); 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If it's not an answer, it doesn't correspond to any request. */ 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(flags & 0x8000)) return -1; /* must be an answer */ 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & 0x020f) { 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* there was an error */ 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err; 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if (!answers) return; */ /* must have an answer of some form */ 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This macro skips a name in the DNS reply. */ 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SKIP_NAME \ 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { tmp_name[0] = '\0'; \ 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0)\ 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err; \ 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while(0) 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TEST_NAME \ 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { tmp_name[0] = '\0'; \ 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmp_name[0] = '\0'; \ 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) k = j; \ 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0)\ 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err; \ 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_parse(req->request, req->request_len, &k, cmp_name, sizeof(cmp_name))<0) \ 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err; \ 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (memcmp(tmp_name, cmp_name, strlen (tmp_name)) != 0) \ 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); /* we ignore mismatching names */ \ 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while(0) 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply.type = req->request_type; 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* skip over each question in the reply */ 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < questions; ++i) { 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the question looks like 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * <label:name><u16:type><u16:class> 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TEST_NAME; 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += 4; 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j > length) goto err; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* now we have the answer section which looks like 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * <label:name><u16:type><u16:class><u32:ttl><u16:len><data...> 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < answers; ++i) { 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 type, class; 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SKIP_NAME; 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(type); 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(class); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET32(ttl); 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(datalength); 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == TYPE_A && class == CLASS_INET) { 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int addrcount, addrtocopy; 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->request_type != TYPE_A) { 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += datalength; continue; 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((datalength & 3) != 0) /* not an even number of As. */ 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err; 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addrcount = datalength >> 2; 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addrtocopy = MIN(MAX_ADDRS - reply.data.a.addrcount, (unsigned)addrcount); 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ttl_r = MIN(ttl_r, ttl); 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we only bother with the first four addresses. */ 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j + 4*addrtocopy > length) goto err; 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&reply.data.a.addresses[reply.data.a.addrcount], 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packet + j, 4*addrtocopy); 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += 4*addrtocopy; 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply.data.a.addrcount += addrtocopy; 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply.have_answer = 1; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reply.data.a.addrcount == MAX_ADDRS) break; 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == TYPE_PTR && class == CLASS_INET) { 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->request_type != TYPE_PTR) { 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += datalength; continue; 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_parse(packet, length, &j, reply.data.ptr.name, 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(reply.data.ptr.name))<0) 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err; 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ttl_r = MIN(ttl_r, ttl); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply.have_answer = 1; 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == TYPE_AAAA && class == CLASS_INET) { 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int addrcount, addrtocopy; 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->request_type != TYPE_AAAA) { 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += datalength; continue; 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((datalength & 15) != 0) /* not an even number of AAAAs. */ 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err; 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addrcount = datalength >> 4; /* each address is 16 bytes long */ 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addrtocopy = MIN(MAX_ADDRS - reply.data.aaaa.addrcount, (unsigned)addrcount); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ttl_r = MIN(ttl_r, ttl); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we only bother with the first four addresses. */ 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j + 16*addrtocopy > length) goto err; 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&reply.data.aaaa.addresses[reply.data.aaaa.addrcount], 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packet + j, 16*addrtocopy); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply.data.aaaa.addrcount += addrtocopy; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += 16*addrtocopy; 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply.have_answer = 1; 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reply.data.aaaa.addrcount == MAX_ADDRS) break; 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* skip over any other type of resource */ 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += datalength; 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_handle(req, flags, ttl_r, &reply); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err: 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req) 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_handle(req, flags, 0, NULL); 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Parse a raw request (packet,length) sent to a nameserver port (port) from */ 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* a DNS client (addr,addrlen), and if it's well-formed, call the corresponding */ 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* callback. */ 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)request_parse(u8 *packet, int length, struct evdns_server_port *port, struct sockaddr *addr, socklen_t addrlen) 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j = 0; /* index into packet */ 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 _t; /* used by the macros */ 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char tmp_name[256]; /* used by the macros */ 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 trans_id, flags, questions, answers, authority, additional; 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_request *server_req = NULL; 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Get the header fields */ 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(trans_id); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(flags); 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(questions); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(answers); 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(authority); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(additional); 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & 0x8000) return -1; /* Must not be an answer. */ 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags &= 0x0110; /* Only RD and CD get preserved. */ 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_req = malloc(sizeof(struct server_request)); 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_req == NULL) return -1; 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(server_req, 0, sizeof(struct server_request)); 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_req->trans_id = trans_id; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&server_req->addr, addr, addrlen); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_req->addrlen = addrlen; 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_req->base.flags = flags; 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_req->base.nquestions = 0; 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_req->base.questions = malloc(sizeof(struct evdns_server_question *) * questions); 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_req->base.questions == NULL) 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err; 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < questions; ++i) { 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 type, class; 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evdns_server_question *q; 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int namelen; 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err; 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(type); 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GET16(class); 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) namelen = strlen(tmp_name); 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) q = malloc(sizeof(struct evdns_server_question) + namelen); 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!q) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err; 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) q->type = type; 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) q->dns_question_class = class; 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(q->name, tmp_name, namelen+1); 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_req->base.questions[server_req->base.nquestions++] = q; 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Ignore answers, authority, and additional. */ 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_req->port = port; 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->refcnt++; 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Only standard queries are supported. */ 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & 0x7800) { 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_server_request_respond(&(server_req->base), DNS_ERR_NOTIMPL); 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->user_callback(&(server_req->base), port->user_data); 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)err: 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_req) { 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_req->base.questions) { 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < server_req->base.nquestions; ++i) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(server_req->base.questions[i]); 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(server_req->base.questions); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(server_req); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef SKIP_NAME 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef GET32 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef GET16 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef GET8 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static u16 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)default_transaction_id_fn(void) 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 trans_id; 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DNS_USE_CPU_CLOCK_FOR_ID 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct timespec ts; 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int clkid = -1; 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (clkid == -1) { 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clkid = CLOCK_REALTIME; 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CLOCK_MONOTONIC 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (clock_gettime(CLOCK_MONOTONIC, &ts) != -1) 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clkid = CLOCK_MONOTONIC; 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (clock_gettime(clkid, &ts) == -1) 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "clock_gettime"); 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans_id = ts.tv_nsec & 0xffff; 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DNS_USE_FTIME_FOR_ID 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct _timeb tb; 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _ftime(&tb); 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans_id = tb.millitm & 0xffff; 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DNS_USE_GETTIMEOFDAY_FOR_ID 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct timeval tv; 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_gettimeofday(&tv, NULL); 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans_id = tv.tv_usec & 0xffff; 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DNS_USE_OPENSSL_FOR_ID 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RAND_pseudo_bytes((u8 *) &trans_id, 2) == -1) { 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* in the case that the RAND call fails we back */ 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* down to using gettimeofday. */ 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct timeval tv; 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_gettimeofday(&tv, NULL); 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans_id = tv.tv_usec & 0xffff; 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) abort(); 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return trans_id; 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static ev_uint16_t (*trans_id_function)(void) = default_transaction_id_fn; 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void)) 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fn) 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans_id_function = fn; 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans_id_function = default_transaction_id_fn; 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Try to choose a strong transaction id which isn't already in flight */ 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static u16 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)transaction_id_pick(void) { 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct request *req = req_head, *started_at; 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 trans_id = trans_id_function(); 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (trans_id == 0xffff) continue; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* now check to see if that id is already inflight */ 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = started_at = req_head; 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req) { 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->trans_id == trans_id) break; 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = req->next; 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (req != started_at); 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we didn't find it, so this is a good id */ 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req == started_at) return trans_id; 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* choose a namesever to use. This function will try to ignore */ 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* nameservers which we think are down and load balance across the rest */ 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* by updating the server_head global each time. */ 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct nameserver * 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nameserver_pick(void) { 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct nameserver *started_at = server_head, *picked; 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!server_head) return NULL; 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if we don't have any good nameservers then there's no */ 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* point in trying to find one. */ 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!global_good_nameservers) { 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_head = server_head->next; 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return server_head; 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* remember that nameservers are in a circular list */ 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_head->state) { 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we think this server is currently good */ 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) picked = server_head; 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_head = server_head->next; 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return picked; 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_head = server_head->next; 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_head == started_at) { 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* all the nameservers seem to be down */ 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* so we just return this one and hope for the */ 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* best */ 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(global_good_nameservers == 0); 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) picked = server_head; 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_head = server_head->next; 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return picked; 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)address_is_correct(struct nameserver *ns, struct sockaddr *sa, socklen_t slen) 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in *sin = (struct sockaddr_in*) sa; 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sa->sa_family != AF_INET || slen != sizeof(struct sockaddr_in)) 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sin->sin_addr.s_addr != ns->address) 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* this is called when a namesever socket is ready for reading */ 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nameserver_read(struct nameserver *ns) { 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 packet[1500]; 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_storage ss; 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socklen_t addrlen = sizeof(ss); 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int r = recvfrom(ns->socket, packet, sizeof(packet), 0, 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (struct sockaddr*)&ss, &addrlen); 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < 0) { 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int err = last_error(ns->socket); 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_is_eagain(err)) return; 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_failed(ns, strerror(err)); 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address_is_correct(ns, (struct sockaddr*)&ss, addrlen)) { 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Address mismatch on received " 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "DNS packet."); 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->timedout = 0; 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_parse(packet, r); 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Read a packet from a DNS client on a server port s, parse it, and */ 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* act accordingly. */ 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)server_port_read(struct evdns_server_port *s) { 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 packet[1500]; 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_storage addr; 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socklen_t addrlen; 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r; 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addrlen = sizeof(struct sockaddr_storage); 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = recvfrom(s->socket, packet, sizeof(packet), 0, 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (struct sockaddr*) &addr, &addrlen); 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < 0) { 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int err = last_error(s->socket); 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_is_eagain(err)) return; 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Error %s (%d) while reading request.", 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strerror(err), err); 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_parse(packet, r, s, (struct sockaddr*) &addr, addrlen); 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Try to write all pending replies on a given DNS server port. */ 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)server_port_flush(struct evdns_server_port *port) 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (port->pending_replies) { 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_request *req = port->pending_replies; 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = sendto(port->socket, req->response, req->response_len, 0, 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (struct sockaddr*) &req->addr, req->addrlen); 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < 0) { 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int err = last_error(port->socket); 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_is_eagain(err)) 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Error %s (%d) while writing response to port; dropping", strerror(err), err); 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_request_free(req)) { 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we released the last reference to req->port. */ 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We have no more pending requests; stop listening for 'writeable' events. */ 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) event_del(&port->event); 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(&port->event, port->socket, EV_READ | EV_PERSIST, 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_port_ready_callback, port); 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_add(&port->event, NULL) < 0) { 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server."); 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* ???? Do more? */ 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* set if we are waiting for the ability to write to this server. */ 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* if waiting is true then we ask libevent for EV_WRITE events, otherwise */ 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* we stop these events. */ 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nameserver_write_waiting(struct nameserver *ns, char waiting) { 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ns->write_waiting == waiting) return; 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->write_waiting = waiting; 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) event_del(&ns->event); 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(&ns->event, ns->socket, EV_READ | (waiting ? EV_WRITE : 0) | EV_PERSIST, 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_ready_callback, ns); 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_add(&ns->event, NULL) < 0) { 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Error from libevent when adding event for %s", 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_ntoa(ns->address)); 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* ???? Do more? */ 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* a callback function. Called by libevent when the kernel says that */ 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* a nameserver socket is ready for writing or reading */ 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nameserver_ready_callback(int fd, short events, void *arg) { 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct nameserver *ns = (struct nameserver *) arg; 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)fd; 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (events & EV_WRITE) { 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->choked = 0; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!evdns_transmit()) { 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_write_waiting(ns, 0); 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (events & EV_READ) { 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_read(ns); 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* a callback function. Called by libevent when the kernel says that */ 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* a server socket is ready for writing or reading. */ 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)server_port_ready_callback(int fd, short events, void *arg) { 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evdns_server_port *port = (struct evdns_server_port *) arg; 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) fd; 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (events & EV_WRITE) { 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->choked = 0; 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_port_flush(port); 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (events & EV_READ) { 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_port_read(port); 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This is an inefficient representation; only use it via the dnslabel_table_* 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * functions, so that is can be safely replaced with something smarter later. */ 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_LABELS 128 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Structures used to implement name compression */ 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct dnslabel_entry { char *v; off_t pos; }; 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct dnslabel_table { 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n_labels; /* number of current entries */ 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* map from name to position in message */ 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dnslabel_entry labels[MAX_LABELS]; 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Initialize dnslabel_table. */ 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dnslabel_table_init(struct dnslabel_table *table) 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) table->n_labels = 0; 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Free all storage held by table, but not the table itself. */ 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dnslabel_clear(struct dnslabel_table *table) 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < table->n_labels; ++i) 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(table->labels[i].v); 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) table->n_labels = 0; 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* return the position of the label in the current message, or -1 if the label */ 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* hasn't been used yet. */ 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dnslabel_table_get_pos(const struct dnslabel_table *table, const char *label) 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < table->n_labels; ++i) { 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!strcmp(label, table->labels[i].v)) 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return table->labels[i].pos; 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* remember that we've used the label at position pos */ 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dnslabel_table_add(struct dnslabel_table *table, const char *label, off_t pos) 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *v; 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int p; 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (table->n_labels == MAX_LABELS) 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v = strdup(label); 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (v == NULL) 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = table->n_labels++; 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) table->labels[p].v = v; 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) table->labels[p].pos = pos; 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Converts a string to a length-prefixed set of DNS labels, starting */ 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* at buf[j]. name and buf must not overlap. name_len should be the length */ 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* of name. table is optional, and is used for compression. */ 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* */ 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Input: abc.def */ 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Output: <3>abc<3>def<0> */ 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* */ 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Returns the first index after the encoded name, or negative on error. */ 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* -1 label was > 63 bytes */ 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* -2 name too long to fit in buffer. */ 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* */ 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static off_t 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dnsname_to_labels(u8 *const buf, size_t buf_len, off_t j, 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *name, const int name_len, 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dnslabel_table *table) { 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *end = name + name_len; 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ref = 0; 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 _t; 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define APPEND16(x) do { \ 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j + 2 > (off_t)buf_len) \ 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto overflow; \ 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _t = htons(x); \ 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf + j, &_t, 2); \ 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += 2; \ 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define APPEND32(x) do { \ 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j + 4 > (off_t)buf_len) \ 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto overflow; \ 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _t32 = htonl(x); \ 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf + j, &_t32, 4); \ 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += 4; \ 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0) 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_len > 255) return -2; 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const start = name; 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (table && (ref = dnslabel_table_get_pos(table, name)) >= 0) { 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(ref | 0xc000); 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return j; 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = strchr(name, '.'); 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!name) { 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned int label_len = end - start; 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (label_len > 63) return -1; 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((size_t)(j+label_len+1) > buf_len) return -2; 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (table) dnslabel_table_add(table, start, j); 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[j++] = label_len; 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf + j, start, end - start); 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += end - start; 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* append length of the label. */ 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned int label_len = name - start; 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (label_len > 63) return -1; 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((size_t)(j+label_len+1) > buf_len) return -2; 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (table) dnslabel_table_add(table, start, j); 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[j++] = label_len; 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf + j, start, name - start); 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += name - start; 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* hop over the '.' */ 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name++; 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the labels must be terminated by a 0. */ 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* It's possible that the name ended in a . */ 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* in which case the zero is already there */ 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!j || buf[j-1]) buf[j++] = 0; 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return j; 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow: 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-2); 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Finds the length of a dns request for a DNS name of the given */ 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* length. The actual request may be smaller than the value returned */ 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* here */ 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_request_len(const int name_len) { 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 96 + /* length of the DNS standard header */ 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_len + 2 + 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4; /* space for the resource type */ 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* build a dns request packet into buf. buf should be at least as long */ 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* as evdns_request_len told you it should be. */ 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* */ 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Returns the amount of space used. Negative on error. */ 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_request_data_build(const char *const name, const int name_len, 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u16 trans_id, const u16 type, const u16 class, 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 *const buf, size_t buf_len) { 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) off_t j = 0; /* current offset into buf */ 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 _t; /* used by the macros */ 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(trans_id); 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(0x0100); /* standard query, recusion needed */ 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(1); /* one question */ 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(0); /* no answers */ 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(0); /* no authority */ 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(0); /* no additional */ 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j = dnsname_to_labels(buf, buf_len, j, name, name_len, NULL); 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j < 0) { 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (int)j; 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(type); 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(class); 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (int)j; 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow: 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct evdns_server_port * 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type cb, void *user_data) 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evdns_server_port *port; 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(port = malloc(sizeof(struct evdns_server_port)))) 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(port, 0, sizeof(struct evdns_server_port)); 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!is_tcp); /* TCP sockets not yet implemented */ 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->socket = socket; 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->refcnt = 1; 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->choked = 0; 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->closing = 0; 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->user_callback = cb; 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->user_data = user_data; 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->pending_replies = NULL; 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(&port->event, port->socket, EV_READ | EV_PERSIST, 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_port_ready_callback, port); 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_add(&port->event, NULL); /* check return. */ 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return port; 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_close_server_port(struct evdns_server_port *port) 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (--port->refcnt == 0) 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_port_free(port); 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->closing = 1; 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_server_request_add_reply(struct evdns_server_request *_req, int section, const char *name, int type, int class, int ttl, int datalen, int is_name, const char *data) 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_request *req = TO_SERVER_REQUEST(_req); 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_reply_item **itemp, *item; 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *countp; 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->response) /* have we already answered? */ 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (section) { 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVDNS_ANSWER_SECTION: 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) itemp = &req->answer; 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) countp = &req->n_answer; 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVDNS_AUTHORITY_SECTION: 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) itemp = &req->authority; 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) countp = &req->n_authority; 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVDNS_ADDITIONAL_SECTION: 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) itemp = &req->additional; 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) countp = &req->n_additional; 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*itemp) { 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) itemp = &((*itemp)->next); 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = malloc(sizeof(struct server_reply_item)); 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!item) 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->next = NULL; 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(item->name = strdup(name))) { 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(item); 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->type = type; 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->dns_question_class = class; 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->ttl = ttl; 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->is_name = is_name != 0; 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->datalen = 0; 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->data = NULL; 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data) { 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item->is_name) { 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(item->data = strdup(data))) { 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(item->name); 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(item); 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->datalen = (u16)-1; 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(item->data = malloc(datalen))) { 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(item->name); 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(item); 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item->datalen = datalen; 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(item->data, data, datalen); 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *itemp = item; 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++(*countp); 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl) 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return evdns_server_request_add_reply( 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req, EVDNS_ANSWER_SECTION, name, TYPE_A, CLASS_INET, 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ttl, n*4, 0, addrs); 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl) 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return evdns_server_request_add_reply( 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req, EVDNS_ANSWER_SECTION, name, TYPE_AAAA, CLASS_INET, 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ttl, n*16, 0, addrs); 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl) 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 a; 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[32]; 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(in || inaddr_name); 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!(in && inaddr_name)); 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (in) { 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a = ntohl(in->s_addr); 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a )&0xff), 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a>>8 )&0xff), 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a>>16)&0xff), 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a>>24)&0xff)); 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inaddr_name = buf; 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return evdns_server_request_add_reply( 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req, EVDNS_ANSWER_SECTION, inaddr_name, TYPE_PTR, CLASS_INET, 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ttl, -1, 1, hostname); 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl) 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return evdns_server_request_add_reply( 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req, EVDNS_ANSWER_SECTION, name, TYPE_CNAME, CLASS_INET, 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ttl, -1, 1, cname); 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_server_request_format_response(struct server_request *req, int err) 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char buf[1500]; 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t buf_len = sizeof(buf); 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) off_t j = 0, r; 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 _t; 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 _t32; 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 flags; 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct dnslabel_table table; 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (err < 0 || err > 15) return -1; 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set response bit and error code; copy OPCODE and RD fields from 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * question; copy RA and AA if set by caller. */ 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags = req->base.flags; 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags |= (0x8000 | err); 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dnslabel_table_init(&table); 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(req->trans_id); 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(flags); 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(req->base.nquestions); 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(req->n_answer); 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(req->n_authority); 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(req->n_additional); 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Add questions. */ 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i < req->base.nquestions; ++i) { 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *s = req->base.questions[i]->name; 16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j = dnsname_to_labels(buf, buf_len, j, s, strlen(s), &table); 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j < 0) { 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dnslabel_clear(&table); 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (int) j; 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(req->base.questions[i]->type); 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(req->base.questions[i]->dns_question_class); 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Add answer, authority, and additional sections. */ 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i<3; ++i) { 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_reply_item *item; 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i==0) 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = req->answer; 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (i==1) 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = req->authority; 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = req->additional; 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (item) { 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = dnsname_to_labels(buf, buf_len, j, item->name, strlen(item->name), &table); 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < 0) 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto overflow; 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j = r; 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(item->type); 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(item->dns_question_class); 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND32(item->ttl); 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item->is_name) { 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) off_t len_idx = j, name_start; 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += 2; 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_start = j; 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = dnsname_to_labels(buf, buf_len, j, item->data, strlen(item->data), &table); 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < 0) 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto overflow; 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j = r; 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _t = htons( (short) (j-name_start) ); 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf+len_idx, &_t, 2); 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) APPEND16(item->datalen); 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j+item->datalen > (off_t)buf_len) 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto overflow; 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf+j, item->data, item->datalen); 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += item->datalen; 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = item->next; 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j > 512) { 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)overflow: 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j = 512; 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[2] |= 0x02; /* set the truncated bit. */ 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->response_len = j; 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(req->response = malloc(req->response_len))) { 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_request_free_answers(req); 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dnslabel_clear(&table); 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(req->response, buf, req->response_len); 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_request_free_answers(req); 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dnslabel_clear(&table); 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_server_request_respond(struct evdns_server_request *_req, int err) 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_request *req = TO_SERVER_REQUEST(_req); 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evdns_server_port *port = req->port; 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r; 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req->response) { 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((r = evdns_server_request_format_response(req, err))<0) 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = sendto(port->socket, req->response, req->response_len, 0, 17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (struct sockaddr*) &req->addr, req->addrlen); 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r<0) { 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sock_err = last_error(port->socket); 17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (! error_is_eagain(sock_err)) 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port->pending_replies) { 17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->prev_pending = port->pending_replies->prev_pending; 17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->next_pending = port->pending_replies; 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->prev_pending->next_pending = 17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->next_pending->prev_pending = req; 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->prev_pending = req->next_pending = req; 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->pending_replies = req; 17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->choked = 1; 17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) event_del(&port->event); 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(&port->event, port->socket, (port->closing?0:EV_READ) | EV_WRITE | EV_PERSIST, server_port_ready_callback, port); 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_add(&port->event, NULL) < 0) { 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server"); 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_request_free(req)) 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port->pending_replies) 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_port_flush(port); 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Free all storage held by RRs in req. */ 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)server_request_free_answers(struct server_request *req) 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_reply_item *victim, *next, **list; 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < 3; ++i) { 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i==0) 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list = &req->answer; 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (i==1) 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list = &req->authority; 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list = &req->additional; 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) victim = *list; 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (victim) { 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next = victim->next; 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(victim->name); 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (victim->data) 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(victim->data); 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(victim); 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) victim = next; 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *list = NULL; 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Free all storage held by req, and remove links to it. */ 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* return true iff we just wound up freeing the server_port. */ 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)server_request_free(struct server_request *req) 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i, rc=1; 18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->base.questions) { 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < req->base.nquestions; ++i) 18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->base.questions[i]); 18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->base.questions); 18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->port) { 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->port->pending_replies == req) { 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->next_pending) 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->port->pending_replies = req->next_pending; 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->port->pending_replies = NULL; 18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = --req->port->refcnt; 18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->response) { 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->response); 18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_request_free_answers(req); 18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->next_pending && req->next_pending != req) { 18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->next_pending->prev_pending = req->prev_pending; 18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->prev_pending->next_pending = req->next_pending; 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rc == 0) { 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_port_free(req->port); 18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req); 18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (1); 18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req); 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Free all storage held by an evdns_server_port. Only called when */ 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)server_port_free(struct evdns_server_port *port) 18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(port); 18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!port->refcnt); 18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!port->pending_replies); 18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port->socket > 0) { 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLOSE_SOCKET(port->socket); 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port->socket = -1; 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) event_del(&port->event); 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* XXXX actually free the port? -NM */ 18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_server_request_drop(struct evdns_server_request *_req) 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_request *req = TO_SERVER_REQUEST(_req); 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_request_free(req); 18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_server_request_get_requesting_addr(struct evdns_server_request *_req, struct sockaddr *sa, int addr_len) 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct server_request *req = TO_SERVER_REQUEST(_req); 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (addr_len < (int)req->addrlen) 18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(sa, &(req->addr), req->addrlen); 18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return req->addrlen; 18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef APPEND16 18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef APPEND32 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* this is a libevent callback function which is called when a request */ 18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* has timed out. */ 18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_request_timeout_callback(int fd, short events, void *arg) { 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *const req = (struct request *) arg; 18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) fd; 18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) events; 18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Request %lx timed out", (unsigned long) arg); 18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ns->timedout++; 18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->ns->timedout > global_max_nameserver_timeout) { 18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ns->timedout = 0; 18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_failed(req->ns, "request timed out."); 18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) evtimer_del(&req->timeout_event); 18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->tx_count >= global_max_retransmits) { 18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* this request has failed */ 18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_callback(req, 0, DNS_ERR_TIMEOUT, NULL); 19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_finished(req, &req_head); 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* retransmit it */ 19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_request_transmit(req); 19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* try to send a request to a given server. */ 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* */ 19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* return: */ 19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 0 ok */ 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1 temporary failure */ 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2 other failure */ 19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_request_transmit_to(struct request *req, struct nameserver *server) { 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in sin; 19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r; 19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&sin, 0, sizeof(sin)); 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sin.sin_addr.s_addr = req->ns->address; 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sin.sin_port = req->ns->port; 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sin.sin_family = AF_INET; 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = sendto(server->socket, req->request, req->request_len, 0, 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (struct sockaddr*)&sin, sizeof(sin)); 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < 0) { 19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int err = last_error(server->socket); 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_is_eagain(err)) return 1; 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_failed(req->ns, strerror(err)); 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 2; 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (r != (int)req->request_len) { 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; /* short write */ 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* try to send a request, updating the fields of the request */ 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* as needed */ 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* */ 19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* return: */ 19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 0 ok */ 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1 failed */ 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_request_transmit(struct request *req) { 19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int retcode = 0, r; 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if we fail to send this packet then this flag marks it */ 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* for evdns_transmit */ 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->transmit_me = 1; 19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->trans_id == 0xffff) abort(); 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->ns->choked) { 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* don't bother trying to write to a socket */ 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* which we have had EAGAIN from */ 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = evdns_request_transmit_to(req, req->ns); 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (r) { 19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 1: 19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* temp failure */ 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ns->choked = 1; 19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_write_waiting(req->ns, 1); 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 2: 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* failed in some other way */ 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retcode = 1; 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* fall through */ 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* all ok */ 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Setting timeout for request %lx", (unsigned long) req); 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evtimer_add(&req->timeout_event, &global_timeout) < 0) { 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Error from libevent when adding timer for request %lx", 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (unsigned long) req); 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* ???? Do more? */ 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->tx_count++; 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->transmit_me = 0; 19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return retcode; 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nameserver_probe_callback(int result, char type, int count, int ttl, void *addresses, void *arg) { 19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct nameserver *const ns = (struct nameserver *) arg; 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) type; 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) count; 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) ttl; 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) addresses; 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == DNS_ERR_NONE || result == DNS_ERR_NOTEXIST) { 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* this is a good reply */ 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nameserver_up(ns); 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else nameserver_probe_failed(ns); 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)nameserver_send_probe(struct nameserver *const ns) { 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *req; 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* here we need to send a probe to a given nameserver */ 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* in the hope that it is up now. */ 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Sending probe to %s", debug_ntoa(ns->address)); 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = request_new(TYPE_A, "www.google.com", DNS_QUERY_NO_SEARCH, nameserver_probe_callback, ns); 20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req) return; 20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we force this into the inflight queue no matter what */ 20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_trans_id_set(req, transaction_id_pick()); 20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ns = ns; 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_submit(req); 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* returns: */ 20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 0 didn't try to transmit anything */ 20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1 tried to transmit something */ 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_transmit(void) { 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char did_try_to_transmit = 0; 20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req_head) { 20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *const started_at = req_head, *req = req_head; 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* first transmit all the requests which are currently waiting */ 20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->transmit_me) { 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) did_try_to_transmit = 1; 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_request_transmit(req); 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = req->next; 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (req != started_at); 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return did_try_to_transmit; 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_count_nameservers(void) 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct nameserver *server = server_head; 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n = 0; 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!server) 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++n; 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server = server->next; 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (server != server_head); 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return n; 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_clear_nameservers_and_suspend(void) 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct nameserver *server = server_head, *started_at = server_head; 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *req = req_head, *req_started_at = req_head; 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!server) 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (1) { 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct nameserver *next = server->next; 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) event_del(&server->event); 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evtimer_initialized(&server->timeout_event)) 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) evtimer_del(&server->timeout_event); 20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server->socket >= 0) 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLOSE_SOCKET(server->socket); 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(server); 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next == started_at) 20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server = next; 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_head = NULL; 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_good_nameservers = 0; 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (req) { 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *next = req->next; 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->tx_count = req->reissue_count = 0; 20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ns = NULL; 20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* ???? What to do about searches? */ 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) evtimer_del(&req->timeout_event); 20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->trans_id = 0; 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->transmit_me = 0; 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_requests_waiting++; 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_request_insert(req, &req_waiting_head); 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We want to insert these suspended elements at the front of 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the waiting queue, since they were pending before any of 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the waiting entries were added. This is a circular list, 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * so we can just shift the start back by one.*/ 20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req_waiting_head = req_waiting_head->prev; 20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next == req_started_at) 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = next; 20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req_head = NULL; 20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_requests_inflight = 0; 20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_resume(void) 21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_requests_pump_waiting_queue(); 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_evdns_nameserver_add_impl(unsigned long int address, int port) { 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* first check to see if we already have this nameserver */ 21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct nameserver *server = server_head, *const started_at = server_head; 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct nameserver *ns; 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int err = 0; 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server) { 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server->address == address) return 3; 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server = server->next; 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (server != started_at); 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns = (struct nameserver *) malloc(sizeof(struct nameserver)); 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ns) return -1; 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(ns, 0, sizeof(struct nameserver)); 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns); 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->socket = socket(PF_INET, SOCK_DGRAM, 0); 21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ns->socket < 0) { err = 1; goto out1; } 21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_make_socket_nonblocking(ns->socket); 21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->address = address; 21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->port = htons(port); 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->state = 1; 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(&ns->event, ns->socket, EV_READ | EV_PERSIST, nameserver_ready_callback, ns); 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_add(&ns->event, NULL) < 0) { 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err = 2; 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out2; 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Added nameserver %s", debug_ntoa(address)); 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* insert this nameserver into the list of them */ 21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!server_head) { 21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->next = ns->prev = ns; 21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_head = ns; 21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->next = server_head->next; 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns->prev = server_head; 21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_head->next = ns; 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_head->prev == server_head) { 21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_head->prev = ns; 21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_good_nameservers++; 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out2: 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLOSE_SOCKET(ns->socket); 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out1: 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(ns); 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Unable to add nameserver %s: error %d", debug_ntoa(address), err); 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return err; 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_nameserver_add(unsigned long int address) { 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return _evdns_nameserver_add_impl(address, 53); 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_nameserver_ip_add(const char *ip_as_string) { 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct in_addr ina; 21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int port; 21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[20]; 21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *cp; 21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cp = strchr(ip_as_string, ':'); 21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (! cp) { 21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cp = ip_as_string; 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port = 53; 21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port = strtoint(cp+1); 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port < 0 || port > 65535) { 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 4; 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((cp-ip_as_string) >= (int)sizeof(buf)) { 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 4; 21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf, ip_as_string, cp-ip_as_string); 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[cp-ip_as_string] = '\0'; 22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cp = buf; 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!inet_aton(cp, &ina)) { 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 4; 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return _evdns_nameserver_add_impl(ina.s_addr, port); 22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* insert into the tail of the queue */ 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_request_insert(struct request *req, struct request **head) { 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!*head) { 22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *head = req; 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->next = req->prev = req; 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->prev = (*head)->prev; 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->prev->next = req; 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->next = *head; 22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*head)->prev = req; 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string_num_dots(const char *s) { 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((s = strchr(s, '.'))) { 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s++; 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count++; 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return count; 22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct request * 22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)request_new(int type, const char *name, int flags, 22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_callback_type callback, void *user_ptr) { 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char issuing_now = 22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (global_requests_inflight < global_max_requests_inflight) ? 1 : 0; 22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int name_len = strlen(name); 22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int request_max_len = evdns_request_len(name_len); 22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u16 trans_id = issuing_now ? transaction_id_pick() : 0xffff; 22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the request data is alloced in a single block with the header */ 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *const req = 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (struct request *) malloc(sizeof(struct request) + request_max_len); 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rlen; 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) flags; 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req) return NULL; 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(req, 0, sizeof(struct request)); 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evtimer_set(&req->timeout_event, evdns_request_timeout_callback, req); 22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* request data lives just after the header */ 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->request = ((u8 *) req) + sizeof(struct request); 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* denotes that the request data shouldn't be free()ed */ 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->request_appended = 1; 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rlen = evdns_request_data_build(name, name_len, trans_id, 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type, CLASS_INET, req->request, request_max_len); 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rlen < 0) 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto err1; 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->request_len = rlen; 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->trans_id = trans_id; 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->tx_count = 0; 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->request_type = type; 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_pointer = user_ptr; 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->user_callback = callback; 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ns = issuing_now ? nameserver_pick() : NULL; 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->next = req->prev = NULL; 22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return req; 22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)err1: 22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req); 22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)request_submit(struct request *const req) { 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->ns) { 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if it has a nameserver assigned then this is going */ 22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* straight into the inflight queue */ 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_request_insert(req, &req_head); 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_requests_inflight++; 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_request_transmit(req); 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_request_insert(req, &req_waiting_head); 22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_requests_waiting++; 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int evdns_resolve_ipv4(const char *name, int flags, 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_callback_type callback, void *ptr) { 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & DNS_QUERY_NO_SEARCH) { 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *const req = 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_new(TYPE_A, name, flags, callback, ptr); 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req == NULL) 22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (1); 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_submit(req); 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (search_request_new(TYPE_A, name, flags, callback, ptr)); 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int evdns_resolve_ipv6(const char *name, int flags, 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_callback_type callback, void *ptr) { 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & DNS_QUERY_NO_SEARCH) { 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *const req = 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_new(TYPE_AAAA, name, flags, callback, ptr); 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req == NULL) 23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (1); 23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_submit(req); 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (search_request_new(TYPE_AAAA, name, flags, callback, ptr)); 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr) { 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[32]; 23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *req; 23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 a; 23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(in); 23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a = ntohl(in->s_addr); 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a )&0xff), 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a>>8 )&0xff), 23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a>>16)&0xff), 23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)(u8)((a>>24)&0xff)); 23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = request_new(TYPE_PTR, buf, flags, callback, ptr); 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req) return 1; 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_submit(req); 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr) { 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 32 nybbles, 32 periods, "ip6.arpa", NUL. */ 23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[73]; 23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *cp; 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *req; 23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(in); 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cp = buf; 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=15; i >= 0; --i) { 23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 byte = in->s6_addr[i]; 23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cp++ = "0123456789abcdef"[byte & 0x0f]; 23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cp++ = '.'; 23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cp++ = "0123456789abcdef"[byte >> 4]; 23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *cp++ = '.'; 23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(cp + strlen("ip6.arpa") < buf+sizeof(buf)); 23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(cp, "ip6.arpa", strlen("ip6.arpa")+1); 23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); 23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = request_new(TYPE_PTR, buf, flags, callback, ptr); 23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req) return 1; 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_submit(req); 23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*/////////////////////////////////////////////////////////////////// */ 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Search support */ 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* */ 23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* the libc resolver has support for searching a number of domains */ 23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* to find a name. If nothing else then it takes the single domain */ 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* from the gethostname() call. */ 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* */ 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* It can also be configured via the domain and search options in a */ 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* resolv.conf. */ 23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* */ 23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The ndots option controls how many dots it takes for the resolver */ 23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* to decide that a name is non-local and so try a raw lookup first. */ 23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct search_domain { 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len; 23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct search_domain *next; 23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the text string is appended to this structure */ 23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct search_state { 23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int refcount; 23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ndots; 23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_domains; 23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct search_domain *head; 23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct search_state *global_search_state = NULL; 23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)search_state_decref(struct search_state *const state) { 23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!state) return; 23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->refcount--; 23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!state->refcount) { 23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct search_domain *next, *dom; 23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (dom = state->head; dom; dom = next) { 23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next = dom->next; 24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(dom); 24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(state); 24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct search_state * 24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)search_state_new(void) { 24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct search_state *state = (struct search_state *) malloc(sizeof(struct search_state)); 24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!state) return NULL; 24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(state, 0, sizeof(struct search_state)); 24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->refcount = 1; 24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->ndots = 1; 24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return state; 24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)search_postfix_clear(void) { 24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_state_decref(global_search_state); 24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_search_state = search_state_new(); 24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_search_clear(void) { 24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_postfix_clear(); 24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)search_postfix_add(const char *domain) { 24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int domain_len; 24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct search_domain *sdomain; 24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (domain[0] == '.') domain++; 24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) domain_len = strlen(domain); 24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!global_search_state) global_search_state = search_state_new(); 24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!global_search_state) return; 24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_search_state->num_domains++; 24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sdomain = (struct search_domain *) malloc(sizeof(struct search_domain) + domain_len); 24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!sdomain) return; 24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy( ((u8 *) sdomain) + sizeof(struct search_domain), domain, domain_len); 24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sdomain->next = global_search_state->head; 24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sdomain->len = domain_len; 24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_search_state->head = sdomain; 24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* reverse the order of members in the postfix list. This is needed because, */ 24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* when parsing resolv.conf we push elements in the wrong order */ 24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)search_reverse(void) { 24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct search_domain *cur, *prev = NULL, *next; 24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = global_search_state->head; 24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (cur) { 24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next = cur->next; 24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur->next = prev; 24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prev = cur; 24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = next; 24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_search_state->head = prev; 24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_search_add(const char *domain) { 24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_postfix_add(domain); 24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_search_ndots_set(const int ndots) { 24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!global_search_state) global_search_state = search_state_new(); 24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!global_search_state) return; 24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_search_state->ndots = ndots; 24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)search_set_from_hostname(void) { 24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char hostname[HOST_NAME_MAX + 1], *domainname; 24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_postfix_clear(); 24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gethostname(hostname, sizeof(hostname))) return; 24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) domainname = strchr(hostname, '.'); 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!domainname) return; 24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_postfix_add(domainname); 24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* warning: returns malloced string */ 24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char * 24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)search_make_new(const struct search_state *const state, int n, const char *const base_name) { 24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int base_len = strlen(base_name); 24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1; 24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct search_domain *dom; 24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (dom = state->head; dom; dom = dom->next) { 24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!n--) { 25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* this is the postfix we want */ 25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the actual postfix string is kept at the end of the structure */ 25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const u8 *const postfix = ((u8 *) dom) + sizeof(struct search_domain); 25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int postfix_len = dom->len; 25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *const newname = (char *) malloc(base_len + need_to_append_dot + postfix_len + 1); 25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!newname) return NULL; 25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(newname, base_name, base_len); 25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (need_to_append_dot) newname[base_len] = '.'; 25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(newname + base_len + need_to_append_dot, postfix, postfix_len); 25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newname[base_len + need_to_append_dot + postfix_len] = 0; 25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return newname; 25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we ran off the end of the list and still didn't find the requested string */ 25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) abort(); 25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; /* unreachable; stops warnings in some compilers. */ 25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)search_request_new(int type, const char *const name, int flags, evdns_callback_type user_callback, void *user_arg) { 25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(type == TYPE_A || type == TYPE_AAAA); 25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( ((flags & DNS_QUERY_NO_SEARCH) == 0) && 25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_search_state && 25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_search_state->num_domains) { 25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we have some domains to search */ 25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *req; 25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (string_num_dots(name) >= global_search_state->ndots) { 25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = request_new(type, name, flags, user_callback, user_arg); 25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req) return 1; 25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->search_index = -1; 25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *const new_name = search_make_new(global_search_state, 0, name); 25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_name) return 1; 25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req = request_new(type, new_name, flags, user_callback, user_arg); 25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(new_name); 25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req) return 1; 25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->search_index = 0; 25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->search_origname = strdup(name); 25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->search_state = global_search_state; 25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->search_flags = flags; 25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_search_state->refcount++; 25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_submit(req); 25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *const req = request_new(type, name, flags, user_callback, user_arg); 25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req) return 1; 25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_submit(req); 25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* this is called when a request has failed to find a name. We need to check */ 25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* if it is part of a search and, if so, try the next name in the list */ 25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* returns: */ 25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 0 another request has been submitted */ 25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1 no more requests needed */ 25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)search_try_next(struct request *const req) { 25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->search_state) { 25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* it is part of a search */ 25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *new_name; 25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct request *newreq; 25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->search_index++; 25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->search_index >= req->search_state->num_domains) { 25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* no more postfixes to try, however we may need to try */ 25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* this name without a postfix */ 25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (string_num_dots(req->search_origname) < req->search_state->ndots) { 25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* yep, we need to try it raw */ 25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newreq = request_new(req->request_type, req->search_origname, req->search_flags, req->user_callback, req->user_pointer); 25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Search: trying raw query %s", req->search_origname); 25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newreq) { 25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_submit(newreq); 25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_name = search_make_new(req->search_state, req->search_index, req->search_origname); 25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_name) return 1; 25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Search: now trying %s (%d)", new_name, req->search_index); 25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newreq = request_new(req->request_type, new_name, req->search_flags, req->user_callback, req->user_pointer); 25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(new_name); 25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!newreq) return 1; 25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newreq->search_origname = req->search_origname; 25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->search_origname = NULL; 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newreq->search_state = req->search_state; 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newreq->search_flags = req->search_flags; 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newreq->search_index = req->search_index; 25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newreq->search_state->refcount++; 25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_submit(newreq); 25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)search_request_finished(struct request *const req) { 26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->search_state) { 26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_state_decref(req->search_state); 26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->search_state = NULL; 26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->search_origname) { 26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->search_origname); 26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->search_origname = NULL; 26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*/////////////////////////////////////////////////////////////////// */ 26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Parsing resolv.conf files */ 26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_resolv_set_defaults(int flags) { 26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if the file isn't found then we assume a local resolver */ 26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & DNS_OPTION_SEARCH) search_set_from_hostname(); 26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & DNS_OPTION_NAMESERVERS) evdns_nameserver_ip_add("127.0.0.1"); 26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HAVE_STRTOK_R 26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char * 26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)strtok_r(char *s, const char *delim, char **state) { 26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return strtok(s, delim); 26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* helper version of atoi which returns -1 on error */ 26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)strtoint(const char *const str) { 26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *endptr; 26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int r = strtol(str, &endptr, 10); 26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*endptr) return -1; 26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* helper version of atoi that returns -1 on error and clips to bounds. */ 26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)strtoint_clipped(const char *const str, int min, int max) 26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = strtoint(str); 26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r == -1) 26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (r<min) 26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return min; 26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (r>max) 26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return max; 26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_set_option(const char *option, const char *val, int flags) 26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!strncmp(option, "ndots:", 6)) { 26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int ndots = strtoint(val); 26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ndots == -1) return -1; 26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(flags & DNS_OPTION_SEARCH)) return 0; 26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Setting ndots to %d", ndots); 26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!global_search_state) global_search_state = search_state_new(); 26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!global_search_state) return -1; 26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_search_state->ndots = ndots; 26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!strncmp(option, "timeout:", 8)) { 26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int timeout = strtoint(val); 26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (timeout == -1) return -1; 26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(flags & DNS_OPTION_MISC)) return 0; 26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Setting timeout to %d", timeout); 26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_timeout.tv_sec = timeout; 26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!strncmp(option, "max-timeouts:", 12)) { 26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int maxtimeout = strtoint_clipped(val, 1, 255); 26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (maxtimeout == -1) return -1; 26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(flags & DNS_OPTION_MISC)) return 0; 26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Setting maximum allowed timeouts to %d", 26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maxtimeout); 26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_max_nameserver_timeout = maxtimeout; 26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!strncmp(option, "max-inflight:", 13)) { 26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int maxinflight = strtoint_clipped(val, 1, 65000); 26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (maxinflight == -1) return -1; 26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(flags & DNS_OPTION_MISC)) return 0; 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Setting maximum inflight requests to %d", 26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maxinflight); 26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_max_requests_inflight = maxinflight; 26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!strncmp(option, "attempts:", 9)) { 26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int retries = strtoint(val); 26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (retries == -1) return -1; 26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (retries > 255) retries = 255; 26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(flags & DNS_OPTION_MISC)) return 0; 26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Setting retries to %d", retries); 26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_max_retransmits = retries; 26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)resolv_conf_parse_line(char *const start, int flags) { 26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *strtok_state; 26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char *const delims = " \t"; 26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state) 26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *const first_token = strtok_r(start, delims, &strtok_state); 27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!first_token) return; 27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!strcmp(first_token, "nameserver") && (flags & DNS_OPTION_NAMESERVERS)) { 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const nameserver = NEXT_TOKEN; 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct in_addr ina; 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inet_aton(nameserver, &ina)) { 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* address is valid */ 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_nameserver_add(ina.s_addr); 27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!strcmp(first_token, "domain") && (flags & DNS_OPTION_SEARCH)) { 27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const domain = NEXT_TOKEN; 27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (domain) { 27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_postfix_clear(); 27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_postfix_add(domain); 27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!strcmp(first_token, "search") && (flags & DNS_OPTION_SEARCH)) { 27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *domain; 27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_postfix_clear(); 27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((domain = NEXT_TOKEN)) { 27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_postfix_add(domain); 27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_reverse(); 27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!strcmp(first_token, "options")) { 27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *option; 27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((option = NEXT_TOKEN)) { 27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *val = strchr(option, ':'); 27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_set_option(option, val ? val+1 : "", flags); 27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef NEXT_TOKEN 27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* exported function */ 27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* returns: */ 27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 0 no errors */ 27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1 failed to open file */ 27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2 failed to stat file */ 27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 3 file too large */ 27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 4 out of memory */ 27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 5 short read from file */ 27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_resolv_conf_parse(int flags, const char *const filename) { 27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct stat st; 27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, n, r; 27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 *resolv; 27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *start; 27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int err = 0; 27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename); 27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fd = open(filename, O_RDONLY); 27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd < 0) { 27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_resolv_set_defaults(flags); 27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fstat(fd, &st)) { err = 2; goto out1; } 27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!st.st_size) { 27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_resolv_set_defaults(flags); 27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err = (flags & DNS_OPTION_NAMESERVERS) ? 6 : 0; 27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out1; 27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (st.st_size > 65535) { err = 3; goto out1; } /* no resolv.conf should be any bigger */ 27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resolv = (u8 *) malloc((size_t)st.st_size + 1); 27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!resolv) { err = 4; goto out1; } 27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n = 0; 27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((r = read(fd, resolv+n, (size_t)st.st_size-n)) > 0) { 27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n += r; 27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n == st.st_size) 27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(n < st.st_size); 27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < 0) { err = 5; goto out2; } 27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resolv[n] = 0; /* we malloced an extra byte; this should be fine. */ 27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start = (char *) resolv; 27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *const newline = strchr(start, '\n'); 27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!newline) { 27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resolv_conf_parse_line(start, flags); 27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *newline = 0; 27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resolv_conf_parse_line(start, flags); 27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start = newline + 1; 27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!server_head && (flags & DNS_OPTION_NAMESERVERS)) { 27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* no nameservers were configured. */ 27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_nameserver_ip_add("127.0.0.1"); 27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err = 6; 27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & DNS_OPTION_SEARCH && (!global_search_state || global_search_state->num_domains == 0)) { 27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) search_set_from_hostname(); 28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out2: 28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(resolv); 28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out1: 28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close(fd); 28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return err; 28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Add multiple nameservers from a space-or-comma-separated list. */ 28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_nameserver_ip_add_line(const char *ips) { 28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *addr; 28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *buf; 28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r; 28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*ips) { 28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (ISSPACE(*ips) || *ips == ',' || *ips == '\t') 28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++ips; 28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr = ips; 28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (ISDIGIT(*ips) || *ips == '.' || *ips == ':') 28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++ips; 28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf = malloc(ips-addr+1); 28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buf) return 4; 28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf, addr, ips-addr); 28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[ips-addr] = '\0'; 28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = evdns_nameserver_ip_add(buf); 28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(buf); 28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r) return r; 28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef DWORD(WINAPI *GetNetworkParams_fn_t)(FIXED_INFO *, DWORD*); 28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Use the windows GetNetworkParams interface in iphlpapi.dll to */ 28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* figure out what our nameservers are. */ 28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)load_nameservers_with_getnetworkparams(void) 28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Based on MSDN examples and inspection of c-ares code. */ 28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FIXED_INFO *fixed; 28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMODULE handle = 0; 28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG size = sizeof(FIXED_INFO); 28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *buf = NULL; 28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int status = 0, r, added_any; 28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IP_ADDR_STRING *ns; 28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetNetworkParams_fn_t fn; 28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(handle = LoadLibrary("iphlpapi.dll"))) { 28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll"); 28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = -1; 28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto done; 28535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(fn = (GetNetworkParams_fn_t) GetProcAddress(handle, "GetNetworkParams"))) { 28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN, "Could not get address of function."); 28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = -1; 28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto done; 28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf = malloc(size); 28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buf) { status = 4; goto done; } 28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fixed = buf; 28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = fn(fixed, &size); 28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r != ERROR_SUCCESS && r != ERROR_BUFFER_OVERFLOW) { 28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = -1; 28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto done; 28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r != ERROR_SUCCESS) { 28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(buf); 28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf = malloc(size); 28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buf) { status = 4; goto done; } 28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fixed = buf; 28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = fn(fixed, &size); 28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r != ERROR_SUCCESS) { 28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "fn() failed."); 28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = -1; 28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto done; 28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(fixed); 28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) added_any = 0; 28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns = &(fixed->DnsServerList); 28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (ns) { 28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = evdns_nameserver_ip_add_line(ns->IpAddress.String); 28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r) { 28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG,"Could not add nameserver %s to list,error: %d", 28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ns->IpAddress.String),(int)GetLastError()); 28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = r; 28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto done; 28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG,"Succesfully added %s as nameserver",ns->IpAddress.String); 28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) added_any++; 28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ns = ns->Next; 28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!added_any) { 29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "No nameservers added."); 29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = -1; 29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done: 29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buf) 29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(buf); 29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle) 29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FreeLibrary(handle); 29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)config_nameserver_from_reg_key(HKEY key, const char *subkey) 29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *buf; 29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD bufsz = 0, type = 0; 29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int status = 0; 29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RegQueryValueEx(key, subkey, 0, &type, NULL, &bufsz) 29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) != ERROR_MORE_DATA) 29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(buf = malloc(bufsz))) 29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz) 29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) == ERROR_SUCCESS && bufsz > 1) { 29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = evdns_nameserver_ip_add_line(buf); 29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(buf); 29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SERVICES_KEY "System\\CurrentControlSet\\Services\\" 29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WIN_NS_9X_KEY SERVICES_KEY "VxD\\MSTCP" 29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WIN_NS_NT_KEY SERVICES_KEY "Tcpip\\Parameters" 29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 29395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)load_nameservers_from_registry(void) 29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int found = 0; 29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r; 29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TRY(k, name) \ 29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!found && config_nameserver_from_reg_key(k,name) == 0) { \ 29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \ 29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = 1; \ 29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!found) { \ 29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG,"Didn't find nameservers in %s/%s", \ 29495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #k,#name); \ 29505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (((int)GetVersion()) > 0) { /* NT */ 29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY nt_key = 0, interfaces_key = 0; 29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, 29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_READ, &nt_key) != ERROR_SUCCESS) { 29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError()); 29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 29595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = RegOpenKeyEx(nt_key, "Interfaces", 0, 29615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, 29625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &interfaces_key); 29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r != ERROR_SUCCESS) { 29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG,"Couldn't open interfaces key, %d",(int)GetLastError()); 29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRY(nt_key, "NameServer"); 29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRY(nt_key, "DhcpNameServer"); 29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRY(interfaces_key, "NameServer"); 29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRY(interfaces_key, "DhcpNameServer"); 29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegCloseKey(interfaces_key); 29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegCloseKey(nt_key); 29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY win_key = 0; 29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0, 29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KEY_READ, &win_key) != ERROR_SUCCESS) { 29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError()); 29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRY(win_key, "NameServer"); 29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegCloseKey(win_key); 29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found == 0) { 29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log(EVDNS_LOG_WARN,"Didn't find any nameservers."); 29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return found ? 0 : -1; 29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef TRY 29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_config_windows_nameservers(void) 29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (load_nameservers_with_getnetworkparams() == 0) 29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 29975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return load_nameservers_from_registry(); 29985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_init(void) 30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res = 0; 30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = evdns_config_windows_nameservers(); 30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf"); 30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (res); 30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 30135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char * 30155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_err_to_string(int err) 30165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (err) { 30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_NONE: return "no error"; 30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_FORMAT: return "misformatted query"; 30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_SERVERFAILED: return "server failed"; 30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_NOTEXIST: return "name does not exist"; 30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_NOTIMPL: return "query not implemented"; 30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_REFUSED: return "refused"; 30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_TRUNCATED: return "reply truncated or ill-formed"; 30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_UNKNOWN: return "unknown"; 30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_TIMEOUT: return "request timed out"; 30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DNS_ERR_SHUTDOWN: return "dns subsystem shut down"; 30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: return "[Unknown error code]"; 30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_shutdown(int fail_requests) 30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct nameserver *server, *server_next; 30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct search_domain *dom, *dom_next; 30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (req_head) { 30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fail_requests) 30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_callback(req_head, 0, DNS_ERR_SHUTDOWN, NULL); 30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_finished(req_head, &req_head); 30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (req_waiting_head) { 30455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fail_requests) 30465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_callback(req_waiting_head, 0, DNS_ERR_SHUTDOWN, NULL); 30475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_finished(req_waiting_head, &req_waiting_head); 30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_requests_inflight = global_requests_waiting = 0; 30505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (server = server_head; server; server = server_next) { 30525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_next = server->next; 30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server->socket >= 0) 30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLOSE_SOCKET(server->socket); 30555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) event_del(&server->event); 30565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server->state == 0) 30575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) event_del(&server->timeout_event); 30585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(server); 30595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_next == server_head) 30605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 30615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_head = NULL; 30635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_good_nameservers = 0; 30645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (global_search_state) { 30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (dom = global_search_state->head; dom; dom = dom_next) { 30675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dom_next = dom->next; 30685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(dom); 30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(global_search_state); 30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_search_state = NULL; 30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_log_fn = NULL; 30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef EVDNS_MAIN 30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)main_callback(int result, char type, int count, int ttl, 30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *addrs, void *orig) { 30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *n = (char*)orig; 30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < count; ++i) { 30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == DNS_IPv4_A) { 30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("%s: %s\n", n, debug_ntoa(((u32*)addrs)[i])); 30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == DNS_PTR) { 30865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("%s: %s\n", n, ((char**)addrs)[i]); 30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!count) { 30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("%s: No answer (%d)\n", n, result); 30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fflush(stdout); 30935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 30945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evdns_server_callback(struct evdns_server_request *req, void *data) 30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i, r; 30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)data; 30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* dummy; give 192.168.11.11 as an answer for all A questions, 31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * give foo.bar.example.com as an answer for all PTR questions. */ 31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < req->nquestions; ++i) { 31025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u32 ans = htonl(0xc0a80b0bUL); 31035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->questions[i]->type == EVDNS_TYPE_A && 31045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->questions[i]->dns_question_class == EVDNS_CLASS_INET) { 31055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" -- replying for %s (A)\n", req->questions[i]->name); 31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = evdns_server_request_add_a_reply(req, req->questions[i]->name, 31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, &ans, 10); 31085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r<0) 31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("eeep, didn't work.\n"); 31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (req->questions[i]->type == EVDNS_TYPE_PTR && 31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->questions[i]->dns_question_class == EVDNS_CLASS_INET) { 31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" -- replying for %s (PTR)\n", req->questions[i]->name); 31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = evdns_server_request_add_ptr_reply(req, NULL, req->questions[i]->name, 31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "foo.bar.example.com", 10); 31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" -- skipping %s [%d %d]\n", req->questions[i]->name, 31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->questions[i]->type, req->questions[i]->dns_question_class); 31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = evdns_request_respond(req, 0); 31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r<0) 31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("eeek, couldn't send reply.\n"); 31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)logfn(int is_warn, const char *msg) { 31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void) is_warn; 31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "%s\n", msg); 31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)main(int c, char **v) { 31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int idx; 31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int reverse = 0, verbose = 1, servertest = 0; 31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (c<2) { 31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "syntax: %s [-x] [-v] hostname\n", v[0]); 31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "syntax: %s [-servertest]\n", v[0]); 31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) idx = 1; 31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (idx < c && v[idx][0] == '-') { 31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!strcmp(v[idx], "-x")) 31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reverse = 1; 31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (!strcmp(v[idx], "-v")) 31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verbose = 1; 31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (!strcmp(v[idx], "-servertest")) 31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) servertest = 1; 31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "Unknown option %s\n", v[idx]); 31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++idx; 31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_init(); 31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (verbose) 31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_set_log_fn(logfn); 31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_resolv_conf_parse(DNS_OPTION_NAMESERVERS, "/etc/resolv.conf"); 31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (servertest) { 31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sock; 31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in my_addr; 31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sock = socket(PF_INET, SOCK_DGRAM, 0); 31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_make_socket_nonblocking(sock); 31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) my_addr.sin_family = AF_INET; 31625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) my_addr.sin_port = htons(10053); 31635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) my_addr.sin_addr.s_addr = INADDR_ANY; 31645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr))<0) { 31655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perror("bind"); 31665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit(1); 31675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_add_server_port(sock, 0, evdns_server_callback, NULL); 31695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; idx < c; ++idx) { 31715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reverse) { 31725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct in_addr addr; 31735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!inet_aton(v[idx], &addr)) { 31745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "Skipping non-IP %s\n", v[idx]); 31755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 31765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "resolving %s...\n",v[idx]); 31785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_resolve_reverse(&addr, 0, main_callback, v[idx]); 31795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 31805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "resolving (fwd) %s...\n",v[idx]); 31815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evdns_resolve_ipv4(v[idx], 0, main_callback, v[idx]); 31825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fflush(stdout); 31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_dispatch(); 31865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 31875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 31885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3189