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