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