- oops forgot includes
[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 #if __BYTE_ORDER == __LITTLE_ENDIAN
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 #elif __BYTE_ORDER == __BIG_ENDIAN
133   
134   /**
135    * query:0, response:1
136    */
137   unsigned int query_or_response    : 1 GNUNET_PACKED;  
138   
139   /**
140    * See GNUNET_DNSPARSER_OPCODE_ defines.
141    */
142   unsigned int opcode               : 4 GNUNET_PACKED;  
143   
144   /**
145    * Set to 1 if this is an authoritative answer
146    */
147   unsigned int authoritative_answer : 1 GNUNET_PACKED;
148   
149   /**
150    * Set to 1 if message is truncated
151    */
152   unsigned int message_truncated    : 1 GNUNET_PACKED; 
153   
154   /**
155    * Set to 1 if recursion is desired (client -> server)
156    */
157   unsigned int recursion_desired    : 1 GNUNET_PACKED;  
158
159  
160   /**
161    * Set to 1 if recursion is available (server -> client)
162    */
163   unsigned int recursion_available  : 1 GNUNET_PACKED;
164   
165   /**
166    * Always zero.
167    */
168   unsigned int zero                 : 1 GNUNET_PACKED;
169   
170   /**
171    * Response has been cryptographically verified, RFC 4035.
172    */
173   unsigned int authenticated_data   : 1 GNUNET_PACKED;
174   
175   /**
176    * See RFC 4035.
177    */
178   unsigned int checking_disabled    : 1 GNUNET_PACKED; 
179   
180   /**
181    * See GNUNET_DNSPARSER_RETURN_CODE_ defines.
182    */  
183   unsigned int return_code          : 4 GNUNET_PACKED; 
184 #else
185   #error byteorder undefined
186 #endif
187   
188 } GNUNET_GCC_STRUCT_LAYOUT;
189
190
191 /**
192  * A DNS query.
193  */
194 struct GNUNET_DNSPARSER_Query
195 {
196
197   /**
198    * Name of the record that the query is for (0-terminated).
199    */
200   char *name;
201
202   /**
203    * See GNUNET_DNSPARSER_TYPE_*.
204    */
205   uint16_t type;
206
207   /**
208    * See GNUNET_DNSPARSER_CLASS_*.
209    */
210   uint16_t class;
211
212 };
213
214
215 /**
216  * Information from MX records (RFC 1035).
217  */
218 struct GNUNET_DNSPARSER_MxRecord
219 {
220   
221   /**
222    * Preference for this entry (lower value is higher preference).
223    */
224   uint16_t preference;
225
226   /**
227    * Name of the mail server.
228    */
229   char *mxhost;
230
231 };
232
233
234 /**
235  * Information from SRV records (RFC 2782).  The 'service', 'proto'
236  * and 'domain_name' fields together give the DNS-name which for SRV
237  * records is of the form "_$SERVICE._$PROTO.$DOMAIN_NAME".  The DNS
238  * parser provides the full name in 'struct DNSPARSER_Record' and the
239  * individual components in the respective fields of this struct.
240  * When serializing, you CAN set the 'name' field of 'struct
241  * GNUNET_DNSPARSER_Record' to NULL, in which case the DNSPARSER code
242  * will populate 'name' from the 'service', 'proto' and 'domain_name'
243  * fields in this struct.
244  */
245 struct GNUNET_DNSPARSER_SrvRecord
246 {
247   
248   /**
249    * Service name without the underscore (!).  Note that RFC 6335 clarifies the
250    * set of legal characters for service names.
251    */
252   char *service;
253
254   /**
255    * Transport protocol (typcially "tcp" or "udp", but others might be allowed).
256    * Without the underscore (!).
257    */
258   char *proto;
259
260   /**
261    * Domain name for which the record is valid
262    */
263   char *domain_name;
264
265   /**
266    * Hostname offering the service.
267    */
268   char *target;
269
270   /**
271    * Preference for this entry (lower value is higher preference).  Clients
272    * will contact hosts from the lowest-priority group first and fall back
273    * to higher priorities if the low-priority entries are unavailable.
274    */
275   uint16_t priority;
276
277   /**
278    * Relative weight for records with the same priority.  Clients will use
279    * the hosts of the same (lowest) priority with a probability proportional
280    * to the weight given.
281    */
282   uint16_t weight;
283
284   /**
285    * TCP or UDP port of the service.
286    */
287   uint16_t port;
288
289 };
290
291   
292 /**
293  * Information from SOA records (RFC 1035).
294  */
295 struct GNUNET_DNSPARSER_SoaRecord
296 {
297   
298   /**
299    *The domainname of the name server that was the
300    * original or primary source of data for this zone.
301    */
302   char *mname;
303
304   /**
305    * A domainname which specifies the mailbox of the
306    * person responsible for this zone.
307    */
308   char *rname;
309
310   /**
311    * The version number of the original copy of the zone.  
312    */
313   uint32_t serial;
314
315   /**
316    * Time interval before the zone should be refreshed.
317    */
318   uint32_t refresh;
319
320   /**
321    * Time interval that should elapse before a failed refresh should
322    * be retried.
323    */
324   uint32_t retry;
325
326   /**
327    * Time value that specifies the upper limit on the time interval
328    * that can elapse before the zone is no longer authoritative.
329    */
330   uint32_t expire;
331
332   /**
333    * The bit minimum TTL field that should be exported with any RR
334    * from this zone.
335    */
336   uint32_t minimum_ttl;
337   
338 };
339
340
341 /**
342  * Binary record information (unparsed).
343  */
344 struct GNUNET_DNSPARSER_RawRecord
345 {
346
347   /**
348    * Binary record data.
349    */
350   void *data;
351
352   /**
353    * Number of bytes in data.
354    */
355   size_t data_len;
356 };
357
358
359 /**
360  * A DNS response record.
361  */
362 struct GNUNET_DNSPARSER_Record
363 {
364
365   /**
366    * Name of the record that the query is for (0-terminated).
367    */
368   char *name;
369
370   /**
371    * Payload of the record (which one of these is valid depends on the 'type').
372    */
373   union 
374   {
375
376     /**
377      * For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
378      */
379     char *hostname;
380     
381     /**
382      * SOA data for SOA records.
383      */
384     struct GNUNET_DNSPARSER_SoaRecord *soa;
385     
386     /**
387      * MX data for MX records.
388      */
389     struct GNUNET_DNSPARSER_MxRecord *mx;
390
391     /**
392      * SRV data for SRV records.
393      */
394     struct GNUNET_DNSPARSER_SrvRecord *srv;
395
396     /**
397      * Raw data for all other types.
398      */
399     struct GNUNET_DNSPARSER_RawRecord raw;
400
401   } data;
402
403
404   /**
405    * When does the record expire?
406    */
407   struct GNUNET_TIME_Absolute expiration_time;
408
409   /**
410    * See GNUNET_DNSPARSER_TYPE_*.
411    */
412   uint16_t type;
413
414   /**
415    * See GNUNET_DNSPARSER_CLASS_*.
416    */
417   uint16_t class;
418
419 };
420
421
422 /**
423  * Easy-to-process, parsed version of a DNS packet.
424  */
425 struct GNUNET_DNSPARSER_Packet
426 {
427   /**
428    * Array of all queries in the packet, must contain "num_queries" entries.
429    */
430   struct GNUNET_DNSPARSER_Query *queries;
431
432   /**
433    * Array of all answers in the packet, must contain "num_answers" entries.
434    */
435   struct GNUNET_DNSPARSER_Record *answers;
436
437   /**
438    * Array of all authority records in the packet, must contain "num_authority_records" entries.
439    */
440   struct GNUNET_DNSPARSER_Record *authority_records;
441
442   /**
443    * Array of all additional answers in the packet, must contain "num_additional_records" entries.
444    */
445   struct GNUNET_DNSPARSER_Record *additional_records;
446
447   /**
448    * Number of queries in the packet.
449    */
450   unsigned int num_queries;
451
452   /**
453    * Number of answers in the packet, should be 0 for queries.
454    */
455   unsigned int num_answers;
456
457   /**
458    * Number of authoritative answers in the packet, should be 0 for queries.
459    */
460   unsigned int num_authority_records;
461
462   /**
463    * Number of additional records in the packet, should be 0 for queries.
464    */
465   unsigned int num_additional_records;
466
467   /**
468    * Bitfield of DNS flags.
469    */ 
470   struct GNUNET_DNSPARSER_Flags flags;
471
472   /**
473    * DNS ID (to match replies to requests).
474    */
475   uint16_t id;
476
477 };
478
479
480 /**
481  * Parse a UDP payload of a DNS packet in to a nice struct for further
482  * processing and manipulation.
483  *
484  * @param udp_payload wire-format of the DNS packet
485  * @param udp_payload_length number of bytes in udp_payload 
486  * @return NULL on error, otherwise the parsed packet
487  */
488 struct GNUNET_DNSPARSER_Packet *
489 GNUNET_DNSPARSER_parse (const char *udp_payload,
490                         size_t udp_payload_length);
491
492
493 /**
494  * Free memory taken by a packet.
495  *
496  * @param p packet to free
497  */
498 void
499 GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p);
500
501
502 /**
503  * Given a DNS packet, generate the corresponding UDP payload.
504  *
505  * @param p packet to pack
506  * @param max maximum allowed size for the resulting UDP payload
507  * @param buf set to a buffer with the packed message
508  * @param buf_length set to the length of buf
509  * @return GNUNET_SYSERR if 'p' is invalid
510  *         GNUNET_NO if 'p' was truncated (but there is still a result in 'buf')
511  *         GNUNET_OK if 'p' was packed completely into '*buf'
512  */
513 int
514 GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p,
515                        uint16_t max,
516                        char **buf,
517                        size_t *buf_length);
518
519
520 #endif