1 #ifndef DNS_H
2 #define DNS_H
3 
4 #include "sysdeps.h"
5 #include "systime.h"
6 #include "ipv4.h"
7 #include "ipv6.h"
8 #include "str.h"
9 #include "uint16.h"
10 
11 /** True if \c struct \c timeval \c A is less than \c B */
12 #define TV_LESS(A,B) (((A)->tv_sec < (B)->tv_sec) || ((A)->tv_sec == (B)->tv_sec && (A)->tv_usec < (B)->tv_usec))
13 
14 /** \defgroup dns dns: DNS Resolver Library
15 
16 @{
17 
18 The DNS resolver library is a modified copy of the public domain library
19 used in djbdns (http://cr.yp.to/djbdns.html). Many modifications have
20 been made, both to make it fit within the bglibs library and to extend
21 the functionality.
22 
23 Notable enhancements are:
24 
25 - support for IPv6 lookups (both forward and reverse)
26 
27 - qualification support for lookup types other than IPv4 addresses
28 
29 - support for multiple outstanding requests
30 
31 \return Functions that return an \c int return -1 on error and set \c errno.
32 
33 */
34 
35 /** Record class: Internet protocol */
36 #define DNS_C_IN 1
37 /** Record class: Any */
38 #define DNS_C_ANY 255
39 
40 /** Record type: Address (IPv4) */
41 #define DNS_T_A 1
42 /** Record type: Name server */
43 #define DNS_T_NS 2
44 /** Record type: Canonical name (alias) */
45 #define DNS_T_CNAME 5
46 /** Record type: Start of authority */
47 #define DNS_T_SOA 6
48 /** Record type: Pointer */
49 #define DNS_T_PTR 12
50 /** Record type: Host information */
51 #define DNS_T_HINFO 13
52 /** Record type: Mail exchanger */
53 #define DNS_T_MX 15
54 /** Record type: Text */
55 #define DNS_T_TXT 16
56 /** Record type: Responsible person */
57 #define DNS_T_RP 17
58 /** Record type: Signature */
59 #define DNS_T_SIG 24
60 /** Record type: Key record */
61 #define DNS_T_KEY 25
62 /** Record type: Address (IPv6) */
63 #define DNS_T_AAAA 28
64 /** Record type: Authoritative zone transfer */
65 #define DNS_T_AXFR 252
66 /** Record type: Any (all known records) */
67 #define DNS_T_ANY 255
68 
69 /** Size of data used by \c dns_random_init */
70 #define DNS_RANDOM_SEED (32*4)
71 /** Maximum number of IPs returned by \c dns_resolvconfip or used by \c dns_transmit_start */
72 #define DNS_MAX_IPS 16
73 /** Maximum output size of \c dns_name4_domain */
74 #define DNS_NAME4_DOMAIN (4*4+14)
75 /** Maximum output size of \c dns_name6_domain */
76 #define DNS_NAME6_DOMAIN (32*2+10)
77 
78 /** DNS transmission record */
79 struct dns_transmit {
80   /** The transmitted query packet. This will either be \c NULL or dynamically allocated. */
81   char *query;
82   /** The length of the transmitted query packet. */
83   unsigned int querylen;
84   /** The received response packet. This will either be \c NULL or dynamically allocated. */
85   char *packet;
86   /** The length of the received response packet. */
87   unsigned int packetlen;
88   /** The socket file descriptor used for data transmission.  This will
89       either be 0 or 1 + an open file descriptor. The addition is done
90       to allow the uninitialized state to be all zeros. */
91   int s1;
92   /** Current state of the TCP connection.  Valid values are:
93 
94       \li 0 is uninitialized (ie using UDP)
95       \li 1 is connecting
96       \li 2 is connected, sending query
97       \li 3 is query sent, waiting for start of response
98       \li 4 is reading response length
99       \li 5 is read packet length, reading response
100   */
101   int tcpstate;
102   /** Count of number of times the UDP query was sent to each server. */
103   unsigned int udploop;
104   /** Index of the server we are currently sending to. */
105   unsigned int curserver;
106   /** Deadline for considering a request timed out. */
107   struct timeval deadline;
108   /** Current sending/receiving position within the buffer, for TCP transmissions. */
109   unsigned int pos;
110   /** The list of servers to try. */
111   const ipv4addr *servers;
112   /** The local IP address to transmit with. */
113   ipv4addr localip;
114   /** The requested query type. */
115   uint16 qtype;
116 };
117 
118 /** An individual result from a \c dns_mx query. */
119 struct dns_mx
120 {
121   /** The distance (or preference) number for this MX. */
122   uint16 distance;
123   /** The domain name of this MX. */
124   char* name;
125 };
126 
127 union dns_result_rrs
128 {
129   void* __ptr;
130   ipv4addr* ip4;
131   ipv6addr* ip6;
132   struct dns_mx* mx;
133   char** name;
134 };
135 
136 /** DNS query results. */
137 struct dns_result
138 {
139   /** The number of results present. */
140   int count;
141   /** The record type of the results. */
142   int type;
143   /** The individual record arrays. */
144   union dns_result_rrs rr;
145   /** Internal use buffer pointer. */
146   void* __buffer;
147 };
148 
149 extern int dns_result_alloc(struct dns_result* d, int type, int count, int size);
150 extern void dns_result_free(struct dns_result* d);
151 
152 extern void dns_random_init(const char [DNS_RANDOM_SEED]);
153 extern unsigned int dns_random(unsigned int);
154 
155 extern void dns_rotate(unsigned char*, unsigned int n, unsigned int shift);
156 extern void dns_rotateipv4(ipv4addr*, unsigned int);
157 extern void dns_rotateipv6(ipv6addr*, unsigned int);
158 
159 extern void dns_sort_mx(struct dns_mx* mxs, int count);
160 
161 extern void dns_domain_free(char **);
162 extern int dns_domain_copy(char **,const char *);
163 extern unsigned int dns_domain_length(const char *);
164 extern int dns_domain_equal(const char *,const char *);
165 extern int dns_domain_suffix(const char *,const char *);
166 extern unsigned int dns_domain_suffixpos(const char *,const char *);
167 extern int dns_domain_fromdot(char **,const char *,unsigned int);
168 extern int dns_domain_todot_cat(str *,const char *);
169 
170 extern unsigned int dns_packet_copy(const char *,unsigned int,unsigned int,unsigned char *,unsigned int);
171 extern unsigned int dns_packet_getname(const char *,unsigned int,unsigned int,char **);
172 extern unsigned int dns_packet_skipname(const char *,unsigned int,unsigned int);
173 extern int dns_packet_extract(struct dns_result* out, const char* buf, unsigned int len, uint16 rrtype, uint16 rrclass,
174 			      int (*sizefn)(const char* buf, unsigned int len, unsigned int pos, uint16 datalen),
175 			      int (*copy)(struct dns_result* out, unsigned int index, unsigned int offset,
176 					  const char* buf, unsigned int len, unsigned int pos, uint16 datalen));
177 
178 extern int dns_transmit_start(struct dns_transmit *,const ipv4addr [DNS_MAX_IPS],int,const char *,uint16,const ipv4addr *);
179 extern void dns_transmit_free(struct dns_transmit *);
180 extern void dns_transmit_io(const struct dns_transmit *,iopoll_fd *,struct timeval *);
181 extern int dns_transmit_get(struct dns_transmit *,const iopoll_fd *,const struct timeval *);
182 
183 extern int dns_read_resolvconf(str *out);
184 extern int dns_resolvconfip(ipv4addr [DNS_MAX_IPS]);
185 extern int dns_resolve(struct dns_transmit *,const char *,uint16);
186 
187 extern int dns_ip4_packet(struct dns_result*, const char*, unsigned int);
188 extern int dns_ip4_r(struct dns_transmit*, struct dns_result*, const char *);
189 extern int dns_ip4(struct dns_result*, const char *);
190 extern int dns_ip6_packet(struct dns_result*, const char*, unsigned int);
191 extern int dns_ip6_r(struct dns_transmit*, struct dns_result*, const char *);
192 extern int dns_ip6(struct dns_result*, const char*);
193 extern int dns_name_packet(struct dns_result*, const char *,unsigned int);
194 extern void dns_name4_domain(char [DNS_NAME4_DOMAIN],const ipv4addr *);
195 extern void dns_name6_domain(char [DNS_NAME6_DOMAIN],const ipv6addr *);
196 extern int dns_name4_r(struct dns_transmit*, struct dns_result*, const ipv4addr*);
197 extern int dns_name4(struct dns_result*, const ipv4addr*);
198 extern int dns_name6_r(struct dns_transmit*, struct dns_result*, const ipv6addr*);
199 extern int dns_name6(struct dns_result*, const ipv6addr*);
200 extern int dns_txt_packet(struct dns_result*, const char *,unsigned int);
201 extern int dns_txt_r(struct dns_transmit *,struct dns_result*, const char *);
202 extern int dns_txt(struct dns_result*, const char *);
203 extern int dns_mx_packet(struct dns_result*, const char *,unsigned int);
204 extern int dns_mx_r(struct dns_transmit *,struct dns_result*, const char *);
205 extern int dns_mx(struct dns_result*, const char *);
206 
207 extern int dns_resolvconfrewrite(str *);
208 extern int dns_qualify_rules(struct dns_result*,str *,const char *,const str *,
209 			     int (*)(struct dns_transmit*, struct dns_result*, const char*));
210 extern int dns_qualify(struct dns_result*,str *,const char *,
211 		       int (*)(struct dns_transmit*, struct dns_result*, const char*));
212 
213 extern unsigned fmt_dns_domain(char*, const char*);
214 
215 /** Wrapper macro to create a non-reentrant function from a \c dns_*_r function. */
216 #define DNS_R_FN_WRAP(NAME,TYPE)			\
217   int dns_##NAME(struct dns_result* out,TYPE in)	\
218   {							\
219     struct dns_transmit tx = {0};			\
220     int r = dns_##NAME##_r(&tx,out,in);			\
221     dns_transmit_free(&tx);				\
222     return r;						\
223   }
224 
225 /** @} */
226 
227 #endif
228