1 #ifndef __ARES_PRIVATE_H
2 #define __ARES_PRIVATE_H
3 
4 
5 /* Copyright 1998 by the Massachusetts Institute of Technology.
6  * Copyright (C) 2004-2010 by Daniel Stenberg
7  *
8  * Permission to use, copy, modify, and distribute this
9  * software and its documentation for any purpose and without
10  * fee is hereby granted, provided that the above copyright
11  * notice appear in all copies and that both that copyright
12  * notice and this permission notice appear in supporting
13  * documentation, and that the name of M.I.T. not be used in
14  * advertising or publicity pertaining to distribution of the
15  * software without specific, written prior permission.
16  * M.I.T. makes no representations about the suitability of
17  * this software for any purpose.  It is provided "as is"
18  * without express or implied warranty.
19  */
20 
21 /*
22  * Define WIN32 when build target is Win32 API
23  */
24 
25 #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
26 #define WIN32
27 #endif
28 
29 #ifdef HAVE_NETINET_IN_H
30 #include <netinet/in.h>
31 #endif
32 
33 #ifdef WATT32
34 #include <tcp.h>
35 #include <sys/ioctl.h>
36 #define writev(s,v,c)     writev_s(s,v,c)
37 #define HAVE_WRITEV 1
38 #endif
39 
40 #define DEFAULT_TIMEOUT         5000 /* milliseconds */
41 #define DEFAULT_TRIES           4
42 #ifndef INADDR_NONE
43 #define INADDR_NONE 0xffffffff
44 #endif
45 
46 #ifdef CARES_EXPOSE_STATICS
47 /* Make some internal functions visible for testing */
48 #define STATIC_TESTABLE
49 #else
50 #define STATIC_TESTABLE static
51 #endif
52 
53 #if defined(WIN32) && !defined(WATT32)
54 
55 #define WIN_NS_9X            "System\\CurrentControlSet\\Services\\VxD\\MSTCP"
56 #define WIN_NS_NT_KEY        "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
57 #define WIN_DNSCLIENT        "Software\\Policies\\Microsoft\\System\\DNSClient"
58 #define WIN_NT_DNSCLIENT     "Software\\Policies\\Microsoft\\Windows NT\\DNSClient"
59 #define NAMESERVER           "NameServer"
60 #define DHCPNAMESERVER       "DhcpNameServer"
61 #define DATABASEPATH         "DatabasePath"
62 #define WIN_PATH_HOSTS       "\\hosts"
63 #define SEARCHLIST_KEY       "SearchList"
64 #define PRIMARYDNSSUFFIX_KEY "PrimaryDNSSuffix"
65 #define INTERFACES_KEY       "Interfaces"
66 #define DOMAIN_KEY           "Domain"
67 #define DHCPDOMAIN_KEY       "DhcpDomain"
68 
69 #elif defined(WATT32)
70 
71 #define PATH_RESOLV_CONF "/dev/ENV/etc/resolv.conf"
72 
73 #elif defined(NETWARE)
74 
75 #define PATH_RESOLV_CONF "sys:/etc/resolv.cfg"
76 #define PATH_HOSTS              "sys:/etc/hosts"
77 
78 #elif defined(__riscos__)
79 
80 #define PATH_HOSTS             "InetDBase:Hosts"
81 
82 #else
83 
84 #define PATH_RESOLV_CONF        "/etc/resolv.conf"
85 #ifdef ETC_INET
86 #define PATH_HOSTS              "/etc/inet/hosts"
87 #else
88 #define PATH_HOSTS              "/etc/hosts"
89 #endif
90 
91 #endif
92 
93 #define ARES_ID_KEY_LEN 31
94 
95 #include "ares_ipv6.h"
96 #include "ares_llist.h"
97 
98 #ifndef HAVE_GETENV
99 #  include "ares_getenv.h"
100 #  define getenv(ptr) ares_getenv(ptr)
101 #endif
102 
103 #include "ares_strdup.h"
104 #include "ares_strsplit.h"
105 
106 #ifndef HAVE_STRCASECMP
107 #  include "ares_strcasecmp.h"
108 #  define strcasecmp(p1,p2) ares_strcasecmp(p1,p2)
109 #endif
110 
111 #ifndef HAVE_STRNCASECMP
112 #  include "ares_strcasecmp.h"
113 #  define strncasecmp(p1,p2,n) ares_strncasecmp(p1,p2,n)
114 #endif
115 
116 #ifndef HAVE_WRITEV
117 #  include "ares_writev.h"
118 #  define writev(s,ptr,cnt) ares_writev(s,ptr,cnt)
119 #endif
120 
121 /********* EDNS defines section ******/
122 #define EDNSPACKETSZ   1280  /* Reasonable UDP payload size, as suggested
123                                 in RFC2671 */
124 #define MAXENDSSZ      4096  /* Maximum (local) limit for edns packet size */
125 #define EDNSFIXEDSZ    11    /* Size of EDNS header */
126 /********* EDNS defines section ******/
127 
128 struct ares_addr {
129   int family;
130   union {
131     struct in_addr       addr4;
132     struct ares_in6_addr addr6;
133   } addr;
134   int udp_port;  /* stored in network order */
135   int tcp_port;  /* stored in network order */
136 };
137 #define addrV4 addr.addr4
138 #define addrV6 addr.addr6
139 
140 struct query;
141 
142 struct send_request {
143   /* Remaining data to send */
144   const unsigned char *data;
145   size_t len;
146 
147   /* The query for which we're sending this data */
148   struct query* owner_query;
149   /* The buffer we're using, if we have our own copy of the packet */
150   unsigned char *data_storage;
151 
152   /* Next request in queue */
153   struct send_request *next;
154 };
155 
156 struct server_state {
157   struct ares_addr addr;
158   ares_socket_t udp_socket;
159   ares_socket_t tcp_socket;
160 
161   /* Mini-buffer for reading the length word */
162   unsigned char tcp_lenbuf[2];
163   int tcp_lenbuf_pos;
164   int tcp_length;
165 
166   /* Buffer for reading actual TCP data */
167   unsigned char *tcp_buffer;
168   int tcp_buffer_pos;
169 
170   /* TCP output queue */
171   struct send_request *qhead;
172   struct send_request *qtail;
173 
174   /* Which incarnation of this connection is this? We don't want to
175    * retransmit requests into the very same socket, but if the server
176    * closes on us and we re-open the connection, then we do want to
177    * re-send. */
178   int tcp_connection_generation;
179 
180   /* Circular, doubly-linked list of outstanding queries to this server */
181   struct list_node queries_to_server;
182 
183   /* Link back to owning channel */
184   ares_channel channel;
185 
186   /* Is this server broken? We mark connections as broken when a
187    * request that is queued for sending times out.
188    */
189   int is_broken;
190 };
191 
192 /* State to represent a DNS query */
193 struct query {
194   /* Query ID from qbuf, for faster lookup, and current timeout */
195   unsigned short qid;
196   struct timeval timeout;
197 
198   /*
199    * Links for the doubly-linked lists in which we insert a query.
200    * These circular, doubly-linked lists that are hash-bucketed based
201    * the attributes we care about, help making most important
202    * operations O(1).
203    */
204   struct list_node queries_by_qid;    /* hopefully in same cache line as qid */
205   struct list_node queries_by_timeout;
206   struct list_node queries_to_server;
207   struct list_node all_queries;
208 
209   /* Query buf with length at beginning, for TCP transmission */
210   unsigned char *tcpbuf;
211   int tcplen;
212 
213   /* Arguments passed to ares_send() (qbuf points into tcpbuf) */
214   const unsigned char *qbuf;
215   int qlen;
216   ares_callback callback;
217   void *arg;
218 
219   /* Query status */
220   int try_count; /* Number of times we tried this query already. */
221   int server; /* Server this query has last been sent to. */
222   struct query_server_info *server_info;   /* per-server state */
223   int using_tcp;
224   int error_status;
225   int timeouts; /* number of timeouts we saw for this request */
226 };
227 
228 /* Per-server state for a query */
229 struct query_server_info {
230   int skip_server;  /* should we skip server, due to errors, etc? */
231   int tcp_connection_generation;  /* into which TCP connection did we send? */
232 };
233 
234 /* An IP address pattern; matches an IP address X if X & mask == addr */
235 #define PATTERN_MASK 0x1
236 #define PATTERN_CIDR 0x2
237 
238 struct apattern {
239   union
240   {
241     struct in_addr       addr4;
242     struct ares_in6_addr addr6;
243   } addr;
244   union
245   {
246     struct in_addr       addr4;
247     struct ares_in6_addr addr6;
248     unsigned short       bits;
249   } mask;
250   int family;
251   unsigned short type;
252 };
253 
254 typedef struct rc4_key
255 {
256   unsigned char state[256];
257   unsigned char x;
258   unsigned char y;
259 } rc4_key;
260 
261 struct ares_channeldata {
262   /* Configuration data */
263   int flags;
264   int timeout; /* in milliseconds */
265   int tries;
266   int ndots;
267   int rotate; /* if true, all servers specified are used */
268   int udp_port; /* stored in network order */
269   int tcp_port; /* stored in network order */
270   int socket_send_buffer_size;
271   int socket_receive_buffer_size;
272   char **domains;
273   int ndomains;
274   struct apattern *sortlist;
275   int nsort;
276   char *lookups;
277   int ednspsz;
278 
279   /* For binding to local devices and/or IP addresses.  Leave
280    * them null/zero for no binding.
281    */
282   char local_dev_name[32];
283   unsigned int local_ip4;
284   unsigned char local_ip6[16];
285 
286   int optmask; /* the option bitfield passed in at init time */
287 
288   /* Server addresses and communications state */
289   struct server_state *servers;
290   int nservers;
291 
292   /* ID to use for next query */
293   unsigned short next_id;
294   /* key to use when generating new ids */
295   rc4_key id_key;
296 
297   /* Generation number to use for the next TCP socket open/close */
298   int tcp_connection_generation;
299 
300   /* The time at which we last called process_timeouts(). Uses integer seconds
301      just to draw the line somewhere. */
302   time_t last_timeout_processed;
303 
304   /* Last server we sent a query to. */
305   int last_server;
306 
307   /* Circular, doubly-linked list of queries, bucketed various ways.... */
308   /* All active queries in a single list: */
309   struct list_node all_queries;
310   /* Queries bucketed by qid, for quickly dispatching DNS responses: */
311 #define ARES_QID_TABLE_SIZE 2048
312   struct list_node queries_by_qid[ARES_QID_TABLE_SIZE];
313   /* Queries bucketed by timeout, for quickly handling timeouts: */
314 #define ARES_TIMEOUT_TABLE_SIZE 1024
315   struct list_node queries_by_timeout[ARES_TIMEOUT_TABLE_SIZE];
316 
317   ares_sock_state_cb sock_state_cb;
318   void *sock_state_cb_data;
319 
320   ares_sock_create_callback sock_create_cb;
321   void *sock_create_cb_data;
322 
323   ares_sock_config_callback sock_config_cb;
324   void *sock_config_cb_data;
325 
326   const struct ares_socket_functions * sock_funcs;
327   void *sock_func_cb_data;
328 
329   /* Path for resolv.conf file, configurable via ares_options */
330   char *resolvconf_path;
331 };
332 
333 /* Does the domain end in ".onion" or ".onion."? Case-insensitive. */
334 int ares__is_onion_domain(const char *name);
335 
336 /* Memory management functions */
337 extern void *(*ares_malloc)(size_t size);
338 extern void *(*ares_realloc)(void *ptr, size_t size);
339 extern void (*ares_free)(void *ptr);
340 
341 /* return true if now is exactly check time or later */
342 int ares__timedout(struct timeval *now,
343                    struct timeval *check);
344 
345 void ares__send_query(ares_channel channel, struct query *query,
346                       struct timeval *now);
347 void ares__close_sockets(ares_channel channel, struct server_state *server);
348 int ares__get_hostent(FILE *fp, int family, struct hostent **host);
349 int ares__read_line(FILE *fp, char **buf, size_t *bufsize);
350 void ares__free_query(struct query *query);
351 unsigned short ares__generate_new_id(rc4_key* key);
352 struct timeval ares__tvnow(void);
353 int ares__expand_name_for_response(const unsigned char *encoded,
354                                    const unsigned char *abuf, int alen,
355                                    char **s, long *enclen);
356 void ares__init_servers_state(ares_channel channel);
357 void ares__destroy_servers_state(ares_channel channel);
358 #if 0 /* Not used */
359 long ares__tvdiff(struct timeval t1, struct timeval t2);
360 #endif
361 
362 void ares__socket_close(ares_channel, ares_socket_t);
363 
364 #define ARES_SWAP_BYTE(a,b) \
365   { unsigned char swapByte = *(a);  *(a) = *(b);  *(b) = swapByte; }
366 
367 #define SOCK_STATE_CALLBACK(c, s, r, w)                                 \
368   do {                                                                  \
369     if ((c)->sock_state_cb)                                             \
370       (c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w));       \
371   } WHILE_FALSE
372 
373 #ifdef CURLDEBUG
374 /* This is low-level hard-hacking memory leak tracking and similar. Using the
375    libcurl lowlevel code from within library is ugly and only works when
376    c-ares is built and linked with a similarly curldebug-enabled libcurl,
377    but we do this anyway for convenience. */
378 #define HEADER_CURL_SETUP_ONCE_H
379 #include "../lib/memdebug.h"
380 #endif
381 
382 #endif /* __ARES_PRIVATE_H */
383