Home | History | Annotate | Download | only in c-ares
      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 #include <stdio.h>
     30 #include <sys/types.h>
     31 
     32 #ifdef HAVE_NETINET_IN_H
     33 #include <netinet/in.h>
     34 #endif
     35 
     36 #ifdef WATT32
     37 #include <tcp.h>
     38 #include <sys/ioctl.h>
     39 #define writev(s,v,c)     writev_s(s,v,c)
     40 #define HAVE_WRITEV 1
     41 #endif
     42 
     43 #ifdef NETWARE
     44 #include <time.h>
     45 #endif
     46 
     47 #define DEFAULT_TIMEOUT         5000 /* milliseconds */
     48 #define DEFAULT_TRIES           4
     49 #ifndef INADDR_NONE
     50 #define INADDR_NONE 0xffffffff
     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 NAMESERVER     "NameServer"
     58 #define DHCPNAMESERVER "DhcpNameServer"
     59 #define DATABASEPATH   "DatabasePath"
     60 #define WIN_PATH_HOSTS  "\\hosts"
     61 
     62 #elif defined(WATT32)
     63 
     64 #define PATH_RESOLV_CONF "/dev/ENV/etc/resolv.conf"
     65 
     66 #elif defined(NETWARE)
     67 
     68 #define PATH_RESOLV_CONF "sys:/etc/resolv.cfg"
     69 #define PATH_HOSTS              "sys:/etc/hosts"
     70 
     71 #elif defined(__riscos__)
     72 
     73 #define PATH_HOSTS             "InetDBase:Hosts"
     74 
     75 #else
     76 
     77 #define PATH_RESOLV_CONF        "/etc/resolv.conf"
     78 #ifdef ETC_INET
     79 #define PATH_HOSTS              "/etc/inet/hosts"
     80 #else
     81 #define PATH_HOSTS              "/etc/hosts"
     82 #endif
     83 
     84 #endif
     85 
     86 #define ARES_ID_KEY_LEN 31
     87 
     88 #include "ares_ipv6.h"
     89 #include "ares_llist.h"
     90 
     91 #ifndef HAVE_GETENV
     92 #  include "ares_getenv.h"
     93 #  define getenv(ptr) ares_getenv(ptr)
     94 #endif
     95 
     96 #ifndef HAVE_STRDUP
     97 #  include "ares_strdup.h"
     98 #  define strdup(ptr) ares_strdup(ptr)
     99 #endif
    100 
    101 #ifndef HAVE_STRCASECMP
    102 #  include "ares_strcasecmp.h"
    103 #  define strcasecmp(p1,p2) ares_strcasecmp(p1,p2)
    104 #endif
    105 
    106 #ifndef HAVE_STRNCASECMP
    107 #  include "ares_strcasecmp.h"
    108 #  define strncasecmp(p1,p2,n) ares_strncasecmp(p1,p2,n)
    109 #endif
    110 
    111 #ifndef HAVE_WRITEV
    112 #  include "ares_writev.h"
    113 #  define writev(s,ptr,cnt) ares_writev(s,ptr,cnt)
    114 #endif
    115 
    116 struct ares_addr {
    117   int family;
    118   union {
    119     struct in_addr       addr4;
    120     struct ares_in6_addr addr6;
    121   } addr;
    122 };
    123 #define addrV4 addr.addr4
    124 #define addrV6 addr.addr6
    125 
    126 struct query;
    127 
    128 struct send_request {
    129   /* Remaining data to send */
    130   const unsigned char *data;
    131   size_t len;
    132 
    133   /* The query for which we're sending this data */
    134   struct query* owner_query;
    135   /* The buffer we're using, if we have our own copy of the packet */
    136   unsigned char *data_storage;
    137 
    138   /* Next request in queue */
    139   struct send_request *next;
    140 };
    141 
    142 struct server_state {
    143   struct ares_addr addr;
    144   ares_socket_t udp_socket;
    145   ares_socket_t tcp_socket;
    146 
    147   /* Mini-buffer for reading the length word */
    148   unsigned char tcp_lenbuf[2];
    149   int tcp_lenbuf_pos;
    150   int tcp_length;
    151 
    152   /* Buffer for reading actual TCP data */
    153   unsigned char *tcp_buffer;
    154   int tcp_buffer_pos;
    155 
    156   /* TCP output queue */
    157   struct send_request *qhead;
    158   struct send_request *qtail;
    159 
    160   /* Which incarnation of this connection is this? We don't want to
    161    * retransmit requests into the very same socket, but if the server
    162    * closes on us and we re-open the connection, then we do want to
    163    * re-send. */
    164   int tcp_connection_generation;
    165 
    166   /* Circular, doubly-linked list of outstanding queries to this server */
    167   struct list_node queries_to_server;
    168 
    169   /* Link back to owning channel */
    170   ares_channel channel;
    171 
    172   /* Is this server broken? We mark connections as broken when a
    173    * request that is queued for sending times out.
    174    */
    175   int is_broken;
    176 };
    177 
    178 /* State to represent a DNS query */
    179 struct query {
    180   /* Query ID from qbuf, for faster lookup, and current timeout */
    181   unsigned short qid;
    182   struct timeval timeout;
    183 
    184   /*
    185    * Links for the doubly-linked lists in which we insert a query.
    186    * These circular, doubly-linked lists that are hash-bucketed based
    187    * the attributes we care about, help making most important
    188    * operations O(1).
    189    */
    190   struct list_node queries_by_qid;    /* hopefully in same cache line as qid */
    191   struct list_node queries_by_timeout;
    192   struct list_node queries_to_server;
    193   struct list_node all_queries;
    194 
    195   /* Query buf with length at beginning, for TCP transmission */
    196   unsigned char *tcpbuf;
    197   int tcplen;
    198 
    199   /* Arguments passed to ares_send() (qbuf points into tcpbuf) */
    200   const unsigned char *qbuf;
    201   int qlen;
    202   ares_callback callback;
    203   void *arg;
    204 
    205   /* Query status */
    206   int try_count; /* Number of times we tried this query already. */
    207   int server; /* Server this query has last been sent to. */
    208   struct query_server_info *server_info;   /* per-server state */
    209   int using_tcp;
    210   int error_status;
    211   int timeouts; /* number of timeouts we saw for this request */
    212 };
    213 
    214 /* Per-server state for a query */
    215 struct query_server_info {
    216   int skip_server;  /* should we skip server, due to errors, etc? */
    217   int tcp_connection_generation;  /* into which TCP connection did we send? */
    218 };
    219 
    220 /* An IP address pattern; matches an IP address X if X & mask == addr */
    221 #define PATTERN_MASK 0x1
    222 #define PATTERN_CIDR 0x2
    223 
    224 struct apattern {
    225   union
    226   {
    227     struct in_addr       addr4;
    228     struct ares_in6_addr addr6;
    229   } addr;
    230   union
    231   {
    232     struct in_addr       addr4;
    233     struct ares_in6_addr addr6;
    234     unsigned short       bits;
    235   } mask;
    236   int family;
    237   unsigned short type;
    238 };
    239 
    240 typedef struct rc4_key
    241 {
    242   unsigned char state[256];
    243   unsigned char x;
    244   unsigned char y;
    245 } rc4_key;
    246 
    247 struct ares_channeldata {
    248   /* Configuration data */
    249   int flags;
    250   int timeout; /* in milliseconds */
    251   int tries;
    252   int ndots;
    253   int rotate; /* if true, all servers specified are used */
    254   int udp_port;
    255   int tcp_port;
    256   int socket_send_buffer_size;
    257   int socket_receive_buffer_size;
    258   char **domains;
    259   int ndomains;
    260   struct apattern *sortlist;
    261   int nsort;
    262   char *lookups;
    263 
    264   /* For binding to local devices and/or IP addresses.  Leave
    265    * them null/zero for no binding.
    266    */
    267   char local_dev_name[32];
    268   unsigned int local_ip4;
    269   unsigned char local_ip6[16];
    270 
    271   int optmask; /* the option bitfield passed in at init time */
    272 
    273   /* Server addresses and communications state */
    274   struct server_state *servers;
    275   int nservers;
    276 
    277   /* ID to use for next query */
    278   unsigned short next_id;
    279   /* key to use when generating new ids */
    280   rc4_key id_key;
    281 
    282   /* Generation number to use for the next TCP socket open/close */
    283   int tcp_connection_generation;
    284 
    285   /* The time at which we last called process_timeouts(). Uses integer seconds
    286      just to draw the line somewhere. */
    287   time_t last_timeout_processed;
    288 
    289   /* Last server we sent a query to. */
    290   int last_server;
    291 
    292   /* Circular, doubly-linked list of queries, bucketed various ways.... */
    293   /* All active queries in a single list: */
    294   struct list_node all_queries;
    295   /* Queries bucketed by qid, for quickly dispatching DNS responses: */
    296 #define ARES_QID_TABLE_SIZE 2048
    297   struct list_node queries_by_qid[ARES_QID_TABLE_SIZE];
    298   /* Queries bucketed by timeout, for quickly handling timeouts: */
    299 #define ARES_TIMEOUT_TABLE_SIZE 1024
    300   struct list_node queries_by_timeout[ARES_TIMEOUT_TABLE_SIZE];
    301 
    302   ares_sock_state_cb sock_state_cb;
    303   void *sock_state_cb_data;
    304 
    305   ares_sock_create_callback sock_create_cb;
    306   void *sock_create_cb_data;
    307 };
    308 
    309 /* return true if now is exactly check time or later */
    310 int ares__timedout(struct timeval *now,
    311                    struct timeval *check);
    312 /* add the specific number of milliseconds to the time in the first argument */
    313 int ares__timeadd(struct timeval *now,
    314                   int millisecs);
    315 /* return time offset between now and (future) check, in milliseconds */
    316 long ares__timeoffset(struct timeval *now,
    317                       struct timeval *check);
    318 /* returns ARES_SUCCESS if library has been initialized */
    319 int ares_library_initialized(void);
    320 void ares__rc4(rc4_key* key,unsigned char *buffer_ptr, int buffer_len);
    321 void ares__send_query(ares_channel channel, struct query *query,
    322                       struct timeval *now);
    323 void ares__close_sockets(ares_channel channel, struct server_state *server);
    324 int ares__get_hostent(FILE *fp, int family, struct hostent **host);
    325 int ares__read_line(FILE *fp, char **buf, size_t *bufsize);
    326 void ares__free_query(struct query *query);
    327 unsigned short ares__generate_new_id(rc4_key* key);
    328 struct timeval ares__tvnow(void);
    329 int ares__expand_name_for_response(const unsigned char *encoded,
    330                                    const unsigned char *abuf, int alen,
    331                                    char **s, long *enclen);
    332 void ares__init_servers_state(ares_channel channel);
    333 void ares__destroy_servers_state(ares_channel channel);
    334 #if 0 /* Not used */
    335 long ares__tvdiff(struct timeval t1, struct timeval t2);
    336 #endif
    337 
    338 #define ARES_SWAP_BYTE(a,b) \
    339   { unsigned char swapByte = *(a);  *(a) = *(b);  *(b) = swapByte; }
    340 
    341 #define SOCK_STATE_CALLBACK(c, s, r, w)                                 \
    342   do {                                                                  \
    343     if ((c)->sock_state_cb)                                             \
    344       (c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w));       \
    345   } while (0)
    346 
    347 #ifdef CURLDEBUG
    348 /* This is low-level hard-hacking memory leak tracking and similar. Using the
    349    libcurl lowlevel code from within library is ugly and only works when
    350    c-ares is built and linked with a similarly curldebug-enabled libcurl,
    351    but we do this anyway for convenience. */
    352 #include "../lib/memdebug.h"
    353 #endif
    354 
    355 #endif /* __ARES_PRIVATE_H */
    356