70dc6332631a7f3895e019d2ba1801f0b3d1e27c
[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
45 /**
46  * A few common DNS classes (ok, only one is common, but I list a
47  * couple more to make it clear what we're talking about here).
48  */
49 #define GNUNET_DNSPARSER_CLASS_INTERNET 1
50 #define GNUNET_DNSPARSER_CLASS_CHAOS 3
51 #define GNUNET_DNSPARSER_CLASS_HESIOD 4
52
53 #define GNUNET_DNSPARSER_OPCODE_QUERY 0
54 #define GNUNET_DNSPARSER_OPCODE_INVERSE_QUERY 1
55 #define GNUNET_DNSPARSER_OPCODE_STATUS 2
56
57 /**
58  * RFC 1035 codes.
59  */
60 #define GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR 0
61 #define GNUNET_DNSPARSER_RETURN_CODE_FORMAT_ERROR 1
62 #define GNUNET_DNSPARSER_RETURN_CODE_SERVER_FAILURE 2
63 #define GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR 3
64 #define GNUNET_DNSPARSER_RETURN_CODE_NOT_IMPLEMENTED 4
65 #define GNUNET_DNSPARSER_RETURN_CODE_REFUSED 5
66
67 /**
68  * RFC 2136 codes
69  */
70 #define GNUNET_DNSPARSER_RETURN_CODE_YXDOMAIN 6
71 #define GNUNET_DNSPARSER_RETURN_CODE_YXRRSET 7
72 #define GNUNET_DNSPARSER_RETURN_CODE_NXRRSET 8
73 #define GNUNET_DNSPARSER_RETURN_CODE_NOT_AUTH 9
74 #define GNUNET_DNSPARSER_RETURN_CODE_NOT_ZONE 10
75
76 /**
77  * DNS flags (largely RFC 1035 / RFC 2136).
78  */
79 struct GNUNET_DNSPARSER_Flags
80 {
81   /**
82    * Set to 1 if recursion is desired (client -> server)
83    */
84   unsigned int recursion_desired    : 1 GNUNET_PACKED;  
85   
86   /**
87    * Set to 1 if message is truncated
88    */
89   unsigned int message_truncated    : 1 GNUNET_PACKED; 
90   
91   /**
92    * Set to 1 if this is an authoritative answer
93    */
94   unsigned int authoritative_answer : 1 GNUNET_PACKED;
95   
96   /**
97    * See GNUNET_DNSPARSER_OPCODE_ defines.
98    */
99   unsigned int opcode               : 4 GNUNET_PACKED;  
100   
101   /**
102    * query:0, response:1
103    */
104   unsigned int query_or_response    : 1 GNUNET_PACKED;  
105   
106   /**
107    * See GNUNET_DNSPARSER_RETURN_CODE_ defines.
108    */
109   unsigned int return_code          : 4 GNUNET_PACKED; 
110   
111   /**
112    * See RFC 4035.
113    */
114   unsigned int checking_disabled    : 1 GNUNET_PACKED; 
115   
116   /**
117    * Response has been cryptographically verified, RFC 4035.
118    */
119   unsigned int authenticated_data   : 1 GNUNET_PACKED;
120   
121   /**
122    * Always zero.
123    */
124   unsigned int zero                 : 1 GNUNET_PACKED;
125   
126   /**
127    * Set to 1 if recursion is available (server -> client)
128    */
129   unsigned int recursion_available  : 1 GNUNET_PACKED; 
130   
131 };
132
133
134 /**
135  * A DNS query.
136  */
137 struct GNUNET_DNSPARSER_Query
138 {
139
140   /**
141    * Name of the record that the query is for (0-terminated).
142    */
143   char *name;
144
145   /**
146    * See GNUNET_DNSPARSER_TYPE_*.
147    */
148   uint16_t type;
149
150   /**
151    * See GNUNET_DNSPARSER_CLASS_*.
152    */
153   uint16_t class;
154
155 };
156
157
158 /**
159  * Information from MX records (RFC 1035).
160  */
161 struct GNUNET_DNSPARSER_MxRecord
162 {
163   
164   /**
165    * Preference for this entry (lower value is higher preference).
166    */
167   uint16_t preference;
168
169   /**
170    * Name of the mail server.
171    */
172   char *mxhost;
173
174 };
175
176   
177 /**
178  * Information from SOA records (RFC 1035).
179  */
180 struct GNUNET_DNSPARSER_SoaRecord
181 {
182   
183   /**
184    *The domainname of the name server that was the
185    * original or primary source of data for this zone.
186    */
187   char *mname;
188
189   /**
190    * A domainname which specifies the mailbox of the
191    * person responsible for this zone.
192    */
193   char *rname;
194
195   /**
196    * The version number of the original copy of the zone.  
197    */
198   uint32_t serial;
199
200   /**
201    * Time interval before the zone should be refreshed.
202    */
203   uint32_t refresh;
204
205   /**
206    * Time interval that should elapse before a failed refresh should
207    * be retried.
208    */
209   uint32_t retry;
210
211   /**
212    * Time value that specifies the upper limit on the time interval
213    * that can elapse before the zone is no longer authoritative.
214    */
215   uint32_t expire;
216
217   /**
218    * The bit minimum TTL field that should be exported with any RR
219    * from this zone.
220    */
221   uint32_t minimum_ttl;
222   
223 };
224
225
226 /**
227  * A DNS response record.
228  */
229 struct GNUNET_DNSPARSER_Record
230 {
231
232   /**
233    * Name of the record that the query is for (0-terminated).
234    */
235   char *name;
236
237   union 
238   {
239
240     /**
241      * For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
242      */
243     char *hostname;
244     
245     /**
246      * SOA data for SOA records.
247      */
248     struct GNUNET_DNSPARSER_SoaRecord *soa;
249     
250     /**
251      * MX data for MX records.
252      */
253     struct GNUNET_DNSPARSER_MxRecord *mx;
254
255     /**
256      * Raw data for all other types.
257      */
258     char *raw;
259
260   } data;
261
262   /**
263    * Number of bytes in data.
264    */
265   size_t data_len;
266
267   /**
268    * When does the record expire?
269    */
270   struct GNUNET_TIME_Absolute expiration_time;
271
272   /**
273    * See GNUNET_DNSPARSER_TYPE_*.
274    */
275   uint16_t type;
276
277   /**
278    * See GNUNET_DNSPARSER_CLASS_*.
279    */
280   uint16_t class;
281
282 };
283
284
285 /**
286  * Easy-to-process, parsed version of a DNS packet.
287  */
288 struct GNUNET_DNSPARSER_Packet
289 {
290   /**
291    * Array of all queries in the packet, must contain "num_queries" entries.
292    */
293   struct GNUNET_DNSPARSER_Query *queries;
294
295   /**
296    * Array of all answers in the packet, must contain "num_answers" entries.
297    */
298   struct GNUNET_DNSPARSER_Record *answers;
299
300   /**
301    * Array of all authority records in the packet, must contain "num_authority_records" entries.
302    */
303   struct GNUNET_DNSPARSER_Record *authority_records;
304
305   /**
306    * Array of all additional answers in the packet, must contain "num_additional_records" entries.
307    */
308   struct GNUNET_DNSPARSER_Record *additional_records;
309
310   /**
311    * Number of queries in the packet.
312    */
313   unsigned int num_queries;
314
315   /**
316    * Number of answers in the packet, should be 0 for queries.
317    */
318   unsigned int num_answers;
319
320   /**
321    * Number of authoritative answers in the packet, should be 0 for queries.
322    */
323   unsigned int num_authority_records;
324
325   /**
326    * Number of additional records in the packet, should be 0 for queries.
327    */
328   unsigned int num_additional_records;
329
330   /**
331    * Bitfield of DNS flags.
332    */ 
333   struct GNUNET_DNSPARSER_Flags flags;
334
335   /**
336    * DNS ID (to match replies to requests).
337    */
338   uint16_t id;
339
340 };
341
342
343 /**
344  * Parse a UDP payload of a DNS packet in to a nice struct for further
345  * processing and manipulation.
346  *
347  * @param udp_payload wire-format of the DNS packet
348  * @param udp_payload_length number of bytes in udp_payload 
349  * @return NULL on error, otherwise the parsed packet
350  */
351 struct GNUNET_DNSPARSER_Packet *
352 GNUNET_DNSPARSER_parse (const char *udp_payload,
353                         size_t udp_payload_length);
354
355
356 /**
357  * Free memory taken by a packet.
358  *
359  * @param p packet to free
360  */
361 void
362 GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p);
363
364
365 /**
366  * Given a DNS packet, generate the corresponding UDP payload.
367  *
368  * @param p packet to pack
369  * @param buf set to a buffer with the packed message
370  * @param buf_length set to the length of buf
371  * @return GNUNET_SYSERR if 'p' is invalid
372  *         GNUNET_NO if 'p' was truncated (but there is still a result in 'buf')
373  *         GNUNET_OK if 'p' was packed completely into '*buf'
374  */
375 int
376 GNUNET_DNSPARSER_pack (struct GNUNET_DNSPARSER_Packet *p,
377                        char **buf,
378                        size_t *buf_length);
379
380
381
382
383 /* legacy API below */
384
385 // DNS-Stuff
386 GNUNET_NETWORK_STRUCT_BEGIN
387
388 struct dns_static
389 {
390   uint16_t id GNUNET_PACKED;
391
392   unsigned rd:1 GNUNET_PACKED;  // recursion desired (client -> server)
393   unsigned tc:1 GNUNET_PACKED;  // message is truncated
394   unsigned aa:1 GNUNET_PACKED;  // authoritative answer
395   unsigned op:4 GNUNET_PACKED;  // query:0, inverse q.:1, status: 2
396   unsigned qr:1 GNUNET_PACKED;  // query:0, response:1
397
398   unsigned rcode:4 GNUNET_PACKED;       // 0 No error
399   // 1 Format error
400   // 2 Server failure
401   // 3 Name Error
402   // 4 Not Implemented
403   // 5 Refused
404   unsigned z:3 GNUNET_PACKED;   // reserved
405   unsigned ra:1 GNUNET_PACKED;  // recursion available (server -> client)
406
407   uint16_t qdcount GNUNET_PACKED;       // number of questions
408   uint16_t ancount GNUNET_PACKED;       // number of answers
409   uint16_t nscount GNUNET_PACKED;       // number of authority-records
410   uint16_t arcount GNUNET_PACKED;       // number of additional records
411 };
412 GNUNET_NETWORK_STRUCT_END
413
414
415 struct dns_pkt
416 {
417   struct dns_static s;
418   unsigned char data[1];
419 };
420
421 struct dns_pkt_parsed
422 {
423   struct dns_static s;
424   struct dns_query **queries;
425   struct dns_record **answers;
426   struct dns_record **nameservers;
427   struct dns_record **additional;
428 };
429
430 struct dns_query_line
431 {
432   uint16_t type;
433   uint16_t class;
434 };
435
436 struct dns_query
437 {
438   char *name;
439   unsigned char namelen;
440   uint16_t qtype;
441   uint16_t qclass;
442 };
443
444 struct dns_record_line
445 {
446   uint16_t type;
447   uint16_t class;
448   uint32_t ttl;
449   uint16_t data_len;
450   unsigned char data;
451 };
452
453 struct dns_record
454 {
455   char *name;
456   unsigned char namelen;
457   uint16_t type;
458   uint16_t class;
459   uint32_t ttl;
460   uint16_t data_len;
461   unsigned char *data;
462 };
463
464
465 struct dns_pkt_parsed *
466 parse_dns_packet (struct dns_pkt *pkt);
467
468 struct dns_pkt *
469 unparse_dns_packet (struct dns_pkt_parsed *pkt);
470
471 void
472 free_parsed_dns_packet (struct dns_pkt_parsed *ppkt);
473
474 #endif