ef2ec389f86f3603bfb1eb99f258c388c7d6af41
[oweals/gnunet.git] / src / include / gnunet_dnsparser_lib.h
1 /*
2       This file is part of GNUnet
3       (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors)
4
5       GNUnet is free software; you can redistribute it and/or modify
6       it under the terms of the GNU General Public License as published
7       by the Free Software Foundation; either version 2, or (at your
8       option) any later version.
9
10       GNUnet is distributed in the hope that it will be useful, but
11       WITHOUT ANY WARRANTY; without even the implied warranty of
12       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13       General Public License for more details.
14
15       You should have received a copy of the GNU General Public License
16       along with GNUnet; see the file COPYING.  If not, write to the
17       Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18       Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * @file include/gnunet_dnsparse_lib.h
23  * @brief API for helper library to parse DNS packets. 
24  * @author Philipp Toelke
25  * @author Christian Grothoff
26  */
27 #ifndef GNUNET_DNSPARSER_LIB_H
28 #define GNUNET_DNSPARSER_LIB_H
29
30 #include "platform.h"
31 #include "gnunet_common.h"
32
33 /**
34  * A few common DNS types.
35  */
36 #define GNUNET_DNSPARSER_TYPE_A 1
37 #define GNUNET_DNSPARSER_TYPE_NS 2
38 #define GNUNET_DNSPARSER_TYPE_CNAME 5
39 #define GNUNET_DNSPARSER_TYPE_SOA 6
40 #define GNUNET_DNSPARSER_TYPE_PTR 12
41 #define GNUNET_DNSPARSER_TYPE_MX 15
42 #define GNUNET_DNSPARSER_TYPE_TXT 16
43 #define GNUNET_DNSPARSER_TYPE_AAAA 28
44 #define GNUNET_DNSPARSER_TYPE_IXFR 251
45 #define GNUNET_DNSPARSER_TYPE_AXFR 252
46
47 /**
48  * A few common DNS classes (ok, only one is common, but I list a
49  * couple more to make it clear what we're talking about here).
50  */
51 #define GNUNET_DNSPARSER_CLASS_INTERNET 1
52 #define GNUNET_DNSPARSER_CLASS_CHAOS 3
53 #define GNUNET_DNSPARSER_CLASS_HESIOD 4
54
55 #define GNUNET_DNSPARSER_OPCODE_QUERY 0
56 #define GNUNET_DNSPARSER_OPCODE_INVERSE_QUERY 1
57 #define GNUNET_DNSPARSER_OPCODE_STATUS 2
58
59 /**
60  * RFC 1035 codes.
61  */
62 #define GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR 0
63 #define GNUNET_DNSPARSER_RETURN_CODE_FORMAT_ERROR 1
64 #define GNUNET_DNSPARSER_RETURN_CODE_SERVER_FAILURE 2
65 #define GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR 3
66 #define GNUNET_DNSPARSER_RETURN_CODE_NOT_IMPLEMENTED 4
67 #define GNUNET_DNSPARSER_RETURN_CODE_REFUSED 5
68
69 /**
70  * RFC 2136 codes
71  */
72 #define GNUNET_DNSPARSER_RETURN_CODE_YXDOMAIN 6
73 #define GNUNET_DNSPARSER_RETURN_CODE_YXRRSET 7
74 #define GNUNET_DNSPARSER_RETURN_CODE_NXRRSET 8
75 #define GNUNET_DNSPARSER_RETURN_CODE_NOT_AUTH 9
76 #define GNUNET_DNSPARSER_RETURN_CODE_NOT_ZONE 10
77
78 /**
79  * DNS flags (largely RFC 1035 / RFC 2136).
80  */
81 struct GNUNET_DNSPARSER_Flags
82 {
83   /**
84    * Set to 1 if recursion is desired (client -> server)
85    */
86   unsigned int recursion_desired    : 1 GNUNET_PACKED;  
87   
88   /**
89    * Set to 1 if message is truncated
90    */
91   unsigned int message_truncated    : 1 GNUNET_PACKED; 
92   
93   /**
94    * Set to 1 if this is an authoritative answer
95    */
96   unsigned int authoritative_answer : 1 GNUNET_PACKED;
97   
98   /**
99    * See GNUNET_DNSPARSER_OPCODE_ defines.
100    */
101   unsigned int opcode               : 4 GNUNET_PACKED;  
102   
103   /**
104    * query:0, response:1
105    */
106   unsigned int query_or_response    : 1 GNUNET_PACKED;  
107   
108   /**
109    * See GNUNET_DNSPARSER_RETURN_CODE_ defines.
110    */
111   unsigned int return_code          : 4 GNUNET_PACKED; 
112   
113   /**
114    * See RFC 4035.
115    */
116   unsigned int checking_disabled    : 1 GNUNET_PACKED; 
117   
118   /**
119    * Response has been cryptographically verified, RFC 4035.
120    */
121   unsigned int authenticated_data   : 1 GNUNET_PACKED;
122   
123   /**
124    * Always zero.
125    */
126   unsigned int zero                 : 1 GNUNET_PACKED;
127   
128   /**
129    * Set to 1 if recursion is available (server -> client)
130    */
131   unsigned int recursion_available  : 1 GNUNET_PACKED; 
132   
133 };
134
135
136 /**
137  * A DNS query.
138  */
139 struct GNUNET_DNSPARSER_Query
140 {
141
142   /**
143    * Name of the record that the query is for (0-terminated).
144    */
145   char *name;
146
147   /**
148    * See GNUNET_DNSPARSER_TYPE_*.
149    */
150   uint16_t type;
151
152   /**
153    * See GNUNET_DNSPARSER_CLASS_*.
154    */
155   uint16_t class;
156
157 };
158
159
160 /**
161  * A DNS response record.
162  */
163 struct GNUNET_DNSPARSER_Record
164 {
165
166   /**
167    * Name of the record that the query is for (0-terminated).
168    */
169   char *name;
170
171   /**
172    * Raw data, NOT a 0-terminated string (at least not always).
173    */
174   char *data;
175
176   /**
177    * Number of bytes in data.
178    */
179   size_t data_len;
180
181   /**
182    * When does the record expire?
183    */
184   struct GNUNET_TIME_Absolute expiration_time;
185
186   /**
187    * See GNUNET_DNSPARSER_TYPE_*.
188    */
189   uint16_t type;
190
191   /**
192    * See GNUNET_DNSPARSER_CLASS_*.
193    */
194   uint16_t class;
195
196 };
197
198
199 /**
200  * Easy-to-process, parsed version of a DNS packet.
201  */
202 struct GNUNET_DNSPARSER_Packet
203 {
204   /**
205    * Array of all queries in the packet, must contain "num_queries" entries.
206    */
207   struct GNUNET_DNSPARSER_Query *queries;
208
209   /**
210    * Array of all answers in the packet, must contain "num_answers" entries.
211    */
212   struct GNUNET_DNSPARSER_Record *answers;
213
214   /**
215    * Array of all authority records in the packet, must contain "num_authority_records" entries.
216    */
217   struct GNUNET_DNSPARSER_Record *authority_records;
218
219   /**
220    * Array of all additional answers in the packet, must contain "num_additional_records" entries.
221    */
222   struct GNUNET_DNSPARSER_Record *additional_records;
223
224   /**
225    * Number of queries in the packet.
226    */
227   unsigned int num_queries;
228
229   /**
230    * Number of answers in the packet, should be 0 for queries.
231    */
232   unsigned int num_answers;
233
234   /**
235    * Number of authoritative answers in the packet, should be 0 for queries.
236    */
237   unsigned int num_authority_records;
238
239   /**
240    * Number of additional records in the packet, should be 0 for queries.
241    */
242   unsigned int num_additional_records;
243
244   /**
245    * Bitfield of DNS flags.
246    */ 
247   struct GNUNET_DNSPARSER_Flags flags;
248
249   /**
250    * DNS ID (to match replies to requests).
251    */
252   uint16_t id;
253
254 };
255
256
257 /**
258  * Parse a UDP payload of a DNS packet in to a nice struct for further
259  * processing and manipulation.
260  *
261  * @param udp_payload wire-format of the DNS packet
262  * @param udp_payload_length number of bytes in udp_payload 
263  * @return NULL on error, otherwise the parsed packet
264  */
265 struct GNUNET_DNSPARSER_Packet *
266 GNUNET_DNSPARSER_parse (const char *udp_payload,
267                         size_t udp_payload_length);
268
269
270 /**
271  * Free memory taken by a packet.
272  *
273  * @param p packet to free
274  */
275 void
276 GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p);
277
278
279 /**
280  * Given a DNS packet, generate the corresponding UDP payload.
281  *
282  * @param p packet to pack
283  * @param buf set to a buffer with the packed message
284  * @param buf_length set to the length of buf
285  * @return GNUNET_SYSERR if 'p' is invalid
286  *         GNUNET_NO if 'p' was truncated (but there is still a result in 'buf')
287  *         GNUNET_OK if 'p' was packed completely into '*buf'
288  */
289 int
290 GNUNET_DNSPARSER_pack (struct GNUNET_DNSPARSER_Packet *p,
291                        char **buf,
292                        size_t *buf_length);
293
294
295
296
297 /* legacy API below */
298
299 // DNS-Stuff
300 GNUNET_NETWORK_STRUCT_BEGIN
301
302 struct dns_static
303 {
304   uint16_t id GNUNET_PACKED;
305
306   unsigned rd:1 GNUNET_PACKED;  // recursion desired (client -> server)
307   unsigned tc:1 GNUNET_PACKED;  // message is truncated
308   unsigned aa:1 GNUNET_PACKED;  // authoritative answer
309   unsigned op:4 GNUNET_PACKED;  // query:0, inverse q.:1, status: 2
310   unsigned qr:1 GNUNET_PACKED;  // query:0, response:1
311
312   unsigned rcode:4 GNUNET_PACKED;       // 0 No error
313   // 1 Format error
314   // 2 Server failure
315   // 3 Name Error
316   // 4 Not Implemented
317   // 5 Refused
318   unsigned z:3 GNUNET_PACKED;   // reserved
319   unsigned ra:1 GNUNET_PACKED;  // recursion available (server -> client)
320
321   uint16_t qdcount GNUNET_PACKED;       // number of questions
322   uint16_t ancount GNUNET_PACKED;       // number of answers
323   uint16_t nscount GNUNET_PACKED;       // number of authority-records
324   uint16_t arcount GNUNET_PACKED;       // number of additional records
325 };
326 GNUNET_NETWORK_STRUCT_END
327
328
329 struct dns_pkt
330 {
331   struct dns_static s;
332   unsigned char data[1];
333 };
334
335 struct dns_pkt_parsed
336 {
337   struct dns_static s;
338   struct dns_query **queries;
339   struct dns_record **answers;
340   struct dns_record **nameservers;
341   struct dns_record **additional;
342 };
343
344 struct dns_query_line
345 {
346   uint16_t type;
347   uint16_t class;
348 };
349
350 struct dns_query
351 {
352   char *name;
353   unsigned char namelen;
354   uint16_t qtype;
355   uint16_t qclass;
356 };
357
358 struct dns_record_line
359 {
360   uint16_t type;
361   uint16_t class;
362   uint32_t ttl;
363   uint16_t data_len;
364   unsigned char data;
365 };
366
367 struct dns_record
368 {
369   char *name;
370   unsigned char namelen;
371   uint16_t type;
372   uint16_t class;
373   uint32_t ttl;
374   uint16_t data_len;
375   unsigned char *data;
376 };
377
378
379 struct dns_pkt_parsed *
380 parse_dns_packet (struct dns_pkt *pkt);
381
382 struct dns_pkt *
383 unparse_dns_packet (struct dns_pkt_parsed *pkt);
384
385 void
386 free_parsed_dns_packet (struct dns_pkt_parsed *ppkt);
387
388 #endif