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