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