-adding missing break statements
[oweals/gnunet.git] / src / include / gnunet_dnsparser_lib.h
1 /*
2       This file is part of GNUnet
3       (C) 2010-2013 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 3, 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_util_lib.h"
31 #include "gnunet_tun_lib.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 /**
60  * A DNS query.
61  */
62 struct GNUNET_DNSPARSER_Query
63 {
64
65   /**
66    * Name of the record that the query is for (0-terminated).
67    * In UTF-8 format.  The library will convert from and to DNS-IDNA
68    * as necessary.  Use 'GNUNET_DNSPARSER_check_label' to test if an
69    * individual label is well-formed.  If a given name is not well-formed,
70    * creating the DNS packet will fail.
71    */
72   char *name;
73
74   /**
75    * See GNUNET_DNSPARSER_TYPE_*.
76    */
77   uint16_t type;
78
79   /**
80    * See GNUNET_TUN_DNS_CLASS_*.
81    */
82   uint16_t dns_traffic_class;
83
84 };
85
86
87 /**
88  * Information from MX records (RFC 1035).
89  */
90 struct GNUNET_DNSPARSER_MxRecord
91 {
92
93   /**
94    * Preference for this entry (lower value is higher preference).
95    */
96   uint16_t preference;
97
98   /**
99    * Name of the mail server.
100    * In UTF-8 format.  The library will convert from and to DNS-IDNA
101    * as necessary.  Use 'GNUNET_DNSPARSER_check_label' to test if an
102    * individual label is well-formed.  If a given name is not well-formed,
103    * creating the DNS packet will fail.
104    */
105   char *mxhost;
106
107 };
108
109
110 /**
111  * Information from SRV records (RFC 2782).  The 'service', 'proto'
112  * and 'domain_name' fields together give the DNS-name which for SRV
113  * records is of the form "_$SERVICE._$PROTO.$DOMAIN_NAME".  The DNS
114  * parser provides the full name in 'struct DNSPARSER_Record' and the
115  * individual components in the respective fields of this struct.
116  * When serializing, you CAN set the 'name' field of 'struct
117  * GNUNET_DNSPARSER_Record' to NULL, in which case the DNSPARSER code
118  * will populate 'name' from the 'service', 'proto' and 'domain_name'
119  * fields in this struct.
120  */
121 struct GNUNET_DNSPARSER_SrvRecord
122 {
123
124   /**
125    * Service name without the underscore (!).  Note that RFC 6335 clarifies the
126    * set of legal characters for service names.
127    * In UTF-8 format.  The library will convert from and to DNS-IDNA
128    * as necessary.  Use 'GNUNET_DNSPARSER_check_label' to test if an
129    * individual label is well-formed.  If a given name is not well-formed,
130    * creating the DNS packet will fail.
131    */
132   char *service;
133
134   /**
135    * Transport protocol (typcially "tcp" or "udp", but others might be allowed).
136    * Without the underscore (!).
137    */
138   char *proto;
139
140   /**
141    * Domain name for which the record is valid
142    * In UTF-8 format.  The library will convert from and to DNS-IDNA
143    * as necessary.  Use 'GNUNET_DNSPARSER_check_label' to test if an
144    * individual label is well-formed.  If a given name is not well-formed,
145    * creating the DNS packet will fail.
146    */
147   char *domain_name;
148
149   /**
150    * Hostname offering the service.
151    * In UTF-8 format.  The library will convert from and to DNS-IDNA
152    * as necessary.  Use 'GNUNET_DNSPARSER_check_label' to test if an
153    * individual label is well-formed.  If a given name is not well-formed,
154    * creating the DNS packet will fail.
155    */
156   char *target;
157
158   /**
159    * Preference for this entry (lower value is higher preference).  Clients
160    * will contact hosts from the lowest-priority group first and fall back
161    * to higher priorities if the low-priority entries are unavailable.
162    */
163   uint16_t priority;
164
165   /**
166    * Relative weight for records with the same priority.  Clients will use
167    * the hosts of the same (lowest) priority with a probability proportional
168    * to the weight given.
169    */
170   uint16_t weight;
171
172   /**
173    * TCP or UDP port of the service.
174    */
175   uint16_t port;
176
177 };
178
179
180 /**
181  * Information from SOA records (RFC 1035).
182  */
183 struct GNUNET_DNSPARSER_SoaRecord
184 {
185
186   /**
187    * The domainname of the name server that was the
188    * original or primary source of data for this zone.
189    * In UTF-8 format.  The library will convert from and to DNS-IDNA
190    * as necessary.  Use #GNUNET_DNSPARSER_check_label to test if an
191    * individual label is well-formed.  If a given name is not well-formed,
192    * creating the DNS packet will fail.
193    */
194   char *mname;
195
196   /**
197    * A domainname which specifies the mailbox of the
198    * person responsible for this zone.
199    * In UTF-8 format.  The library will convert from and to DNS-IDNA
200    * as necessary.  Use 'GNUNET_DNSPARSER_check_label' to test if an
201    * individual label is well-formed.  If a given name is not well-formed,
202    * creating the DNS packet will fail.
203    */
204   char *rname;
205
206   /**
207    * The version number of the original copy of the zone.
208    */
209   uint32_t serial;
210
211   /**
212    * Time interval before the zone should be refreshed.
213    */
214   uint32_t refresh;
215
216   /**
217    * Time interval that should elapse before a failed refresh should
218    * be retried.
219    */
220   uint32_t retry;
221
222   /**
223    * Time value that specifies the upper limit on the time interval
224    * that can elapse before the zone is no longer authoritative.
225    */
226   uint32_t expire;
227
228   /**
229    * The bit minimum TTL field that should be exported with any RR
230    * from this zone.
231    */
232   uint32_t minimum_ttl;
233
234 };
235
236
237 /**
238  * Binary record information (unparsed).
239  */
240 struct GNUNET_DNSPARSER_RawRecord
241 {
242
243   /**
244    * Binary record data.
245    */
246   void *data;
247
248   /**
249    * Number of bytes in data.
250    */
251   size_t data_len;
252 };
253
254
255 /**
256  * A DNS response record.
257  */
258 struct GNUNET_DNSPARSER_Record
259 {
260
261   /**
262    * Name of the record that the query is for (0-terminated).
263    * In UTF-8 format.  The library will convert from and to DNS-IDNA
264    * as necessary.  Use #GNUNET_DNSPARSER_check_label to test if an
265    * individual label is well-formed.  If a given name is not well-formed,
266    * creating the DNS packet will fail.
267    */
268   char *name;
269
270   /**
271    * Payload of the record (which one of these is valid depends on the 'type').
272    */
273   union
274   {
275
276     /**
277      * For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
278    * In UTF-8 format.  The library will convert from and to DNS-IDNA
279    * as necessary.  Use #GNUNET_DNSPARSER_check_label to test if an
280    * individual label is well-formed.  If a given name is not well-formed,
281    * creating the DNS packet will fail.
282      */
283     char *hostname;
284
285     /**
286      * SOA data for SOA records.
287      */
288     struct GNUNET_DNSPARSER_SoaRecord *soa;
289
290     /**
291      * MX data for MX records.
292      */
293     struct GNUNET_DNSPARSER_MxRecord *mx;
294
295     /**
296      * SRV data for SRV records.
297      */
298     struct GNUNET_DNSPARSER_SrvRecord *srv;
299
300     /**
301      * Raw data for all other types.
302      */
303     struct GNUNET_DNSPARSER_RawRecord raw;
304
305   } data;
306
307
308   /**
309    * When does the record expire?
310    */
311   struct GNUNET_TIME_Absolute expiration_time;
312
313   /**
314    * See GNUNET_DNSPARSER_TYPE_*.
315    */
316   uint16_t type;
317
318   /**
319    * See GNUNET_TUN_DNS_CLASS_*.
320    */
321   uint16_t dns_traffic_class;
322
323 };
324
325
326 /**
327  * Easy-to-process, parsed version of a DNS packet.
328  */
329 struct GNUNET_DNSPARSER_Packet
330 {
331   /**
332    * Array of all queries in the packet, must contain "num_queries" entries.
333    */
334   struct GNUNET_DNSPARSER_Query *queries;
335
336   /**
337    * Array of all answers in the packet, must contain "num_answers" entries.
338    */
339   struct GNUNET_DNSPARSER_Record *answers;
340
341   /**
342    * Array of all authority records in the packet, must contain "num_authority_records" entries.
343    */
344   struct GNUNET_DNSPARSER_Record *authority_records;
345
346   /**
347    * Array of all additional answers in the packet, must contain "num_additional_records" entries.
348    */
349   struct GNUNET_DNSPARSER_Record *additional_records;
350
351   /**
352    * Number of queries in the packet.
353    */
354   unsigned int num_queries;
355
356   /**
357    * Number of answers in the packet, should be 0 for queries.
358    */
359   unsigned int num_answers;
360
361   /**
362    * Number of authoritative answers in the packet, should be 0 for queries.
363    */
364   unsigned int num_authority_records;
365
366   /**
367    * Number of additional records in the packet, should be 0 for queries.
368    */
369   unsigned int num_additional_records;
370
371   /**
372    * Bitfield of DNS flags.
373    */
374   struct GNUNET_TUN_DnsFlags flags;
375
376   /**
377    * DNS ID (to match replies to requests).
378    */
379   uint16_t id;
380
381 };
382
383
384 /**
385  * Check if a label in UTF-8 format can be coded into valid IDNA.
386  * This can fail if the ASCII-conversion becomes longer than 63 characters.
387  *
388  * @param label label to check (UTF-8 string)
389  * @return #GNUNET_OK if the label can be converted to IDNA,
390  *         #GNUNET_SYSERR if the label is not valid for DNS names
391  */
392 int
393 GNUNET_DNSPARSER_check_label (const char *label);
394
395
396 /**
397  * Check if a hostname in UTF-8 format can be coded into valid IDNA.
398  * This can fail if a label becomes longer than 63 characters or if
399  * the entire name exceeds 253 characters.
400  *
401  * @param name name to check (UTF-8 string)
402  * @return #GNUNET_OK if the label can be converted to IDNA,
403  *         #GNUNET_SYSERR if the label is not valid for DNS names
404  */
405 int
406 GNUNET_DNSPARSER_check_name (const char *name);
407
408
409 /**
410  * Parse a UDP payload of a DNS packet in to a nice struct for further
411  * processing and manipulation.
412  *
413  * @param udp_payload wire-format of the DNS packet
414  * @param udp_payload_length number of bytes in @a udp_payload
415  * @return NULL on error, otherwise the parsed packet
416  */
417 struct GNUNET_DNSPARSER_Packet *
418 GNUNET_DNSPARSER_parse (const char *udp_payload,
419                         size_t udp_payload_length);
420
421
422 /**
423  * Free memory taken by a packet.
424  *
425  * @param p packet to free
426  */
427 void
428 GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p);
429
430
431 /**
432  * Given a DNS packet @a p, generate the corresponding UDP payload.
433  * Note that we do not attempt to pack the strings with pointers
434  * as this would complicate the code and this is about being
435  * simple and secure, not fast, fancy and broken like bind.
436  *
437  * @param p packet to pack
438  * @param max maximum allowed size for the resulting UDP payload
439  * @param buf set to a buffer with the packed message
440  * @param buf_length set to the length of @a buf
441  * @return #GNUNET_SYSERR if @a p is invalid
442  *         #GNUNET_NO if @a p was truncated (but there is still a result in @a buf)
443  *         #GNUNET_OK if @a p was packed completely into @a buf
444  */
445 int
446 GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p,
447                        uint16_t max,
448                        char **buf,
449                        size_t *buf_length);
450
451 /* ***************** low-level packing API ******************** */
452
453 /**
454  * Add a DNS name to the UDP packet at the given location, converting
455  * the name to IDNA notation as necessary.
456  *
457  * @param dst where to write the name (UDP packet)
458  * @param dst_len number of bytes in @a dst
459  * @param off pointer to offset where to write the name (increment by bytes used)
460  *            must not be changed if there is an error
461  * @param name name to write
462  * @return #GNUNET_SYSERR if @a name is invalid
463  *         #GNUNET_NO if @a name did not fit
464  *         #GNUNET_OK if @a name was added to @a dst
465  */
466 int
467 GNUNET_DNSPARSER_builder_add_name (char *dst,
468                                    size_t dst_len,
469                                    size_t *off,
470                                    const char *name);
471
472
473 /**
474  * Add a DNS query to the UDP packet at the given location.
475  *
476  * @param dst where to write the query
477  * @param dst_len number of bytes in @a dst
478  * @param off pointer to offset where to write the query (increment by bytes used)
479  *            must not be changed if there is an error
480  * @param query query to write
481  * @return #GNUNET_SYSERR if @a query is invalid
482  *         #GNUNET_NO if @a query did not fit
483  *         #GNUNET_OK if @a query was added to @a dst
484  */
485 int
486 GNUNET_DNSPARSER_builder_add_query (char *dst,
487                                     size_t dst_len,
488                                     size_t *off,
489                                     const struct GNUNET_DNSPARSER_Query *query);
490
491
492 /**
493  * Add an MX record to the UDP packet at the given location.
494  *
495  * @param dst where to write the mx record
496  * @param dst_len number of bytes in @a dst
497  * @param off pointer to offset where to write the mx information (increment by bytes used);
498  *            can also change if there was an error
499  * @param mx mx information to write
500  * @return #GNUNET_SYSERR if @a mx is invalid
501  *         #GNUNET_NO if @a mx did not fit
502  *         #GNUNET_OK if @a mx was added to @a dst
503  */
504 int
505 GNUNET_DNSPARSER_builder_add_mx (char *dst,
506                                  size_t dst_len,
507                                  size_t *off,
508                                  const struct GNUNET_DNSPARSER_MxRecord *mx);
509
510
511 /**
512  * Add an SOA record to the UDP packet at the given location.
513  *
514  * @param dst where to write the SOA record
515  * @param dst_len number of bytes in @a dst
516  * @param off pointer to offset where to write the SOA information (increment by bytes used)
517  *            can also change if there was an error
518  * @param soa SOA information to write
519  * @return #GNUNET_SYSERR if @a soa is invalid
520  *         #GNUNET_NO if @a soa did not fit
521  *         #GNUNET_OK if @a soa was added to @a dst
522  */
523 int
524 GNUNET_DNSPARSER_builder_add_soa (char *dst,
525                                   size_t dst_len,
526                                   size_t *off,
527                                   const struct GNUNET_DNSPARSER_SoaRecord *soa);
528
529
530 /**
531  * Add an SRV record to the UDP packet at the given location.
532  *
533  * @param dst where to write the SRV record
534  * @param dst_len number of bytes in @a dst
535  * @param off pointer to offset where to write the SRV information (increment by bytes used)
536  *            can also change if there was an error
537  * @param srv SRV information to write
538  * @return #GNUNET_SYSERR if @a srv is invalid
539  *         #GNUNET_NO if @a srv did not fit
540  *         #GNUNET_OK if @a srv was added to @a dst
541  */
542 int
543 GNUNET_DNSPARSER_builder_add_srv (char *dst,
544                                   size_t dst_len,
545                                   size_t *off,
546                                   const struct GNUNET_DNSPARSER_SrvRecord *srv);
547
548 /* ***************** low-level parsing API ******************** */
549
550 /**
551  * Parse a DNS record entry.
552  *
553  * @param udp_payload entire UDP payload
554  * @param udp_payload_length length of @a udp_payload
555  * @param off pointer to the offset of the record to parse in the udp_payload (to be
556  *                    incremented by the size of the record)
557  * @param r where to write the record information
558  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the record is malformed
559  */
560 int
561 GNUNET_DNSPARSER_parse_record (const char *udp_payload,
562                                size_t udp_payload_length,
563                                size_t *off,
564                                struct GNUNET_DNSPARSER_Record *r);
565
566
567 /**
568  * Parse name inside of a DNS query or record.
569  *
570  * @param udp_payload entire UDP payload
571  * @param udp_payload_length length of @a udp_payload
572  * @param off pointer to the offset of the name to parse in the udp_payload (to be
573  *                    incremented by the size of the name)
574  * @return name as 0-terminated C string on success, NULL if the payload is malformed
575  */
576 char *
577 GNUNET_DNSPARSER_parse_name (const char *udp_payload,
578                              size_t udp_payload_length,
579                              size_t *off);
580
581
582 /**
583  * Parse a DNS query entry.
584  *
585  * @param udp_payload entire UDP payload
586  * @param udp_payload_length length of @a udp_payload
587  * @param off pointer to the offset of the query to parse in the udp_payload (to be
588  *                    incremented by the size of the query)
589  * @param q where to write the query information
590  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the query is malformed
591  */
592 int
593 GNUNET_DNSPARSER_parse_query (const char *udp_payload,
594                               size_t udp_payload_length,
595                               size_t *off,
596                               struct GNUNET_DNSPARSER_Query *q);
597
598 /**
599  * Parse a DNS SOA record.
600  *
601  * @param udp_payload reference to UDP packet
602  * @param udp_payload_length length of @a udp_payload
603  * @param off pointer to the offset of the query to parse in the SOA record (to be
604  *                    incremented by the size of the record), unchanged on error
605  * @return the parsed SOA record, NULL on error
606  */
607 struct GNUNET_DNSPARSER_SoaRecord *
608 GNUNET_DNSPARSER_parse_soa (const char *udp_payload,
609                             size_t udp_payload_length,
610                             size_t *off);
611
612
613 /**
614  * Parse a DNS MX record.
615  *
616  * @param udp_payload reference to UDP packet
617  * @param udp_payload_length length of @a udp_payload
618  * @param off pointer to the offset of the query to parse in the MX record (to be
619  *                    incremented by the size of the record), unchanged on error
620  * @return the parsed MX record, NULL on error
621  */
622 struct GNUNET_DNSPARSER_MxRecord *
623 GNUNET_DNSPARSER_parse_mx (const char *udp_payload,
624                            size_t udp_payload_length,
625                            size_t *off);
626
627
628 /**
629  * Parse a DNS SRV record.
630  *
631  * @param r_name name of the SRV record
632  * @param udp_payload reference to UDP packet
633  * @param udp_payload_length length of @a udp_payload
634  * @param off pointer to the offset of the query to parse in the SRV record (to be
635  *                    incremented by the size of the record), unchanged on error
636  * @return the parsed SRV record, NULL on error
637  */
638 struct GNUNET_DNSPARSER_SrvRecord *
639 GNUNET_DNSPARSER_parse_srv (const char *r_name,
640                             const char *udp_payload,
641                             size_t udp_payload_length,
642                             size_t *off);
643
644 /* ***************** low-level deallocation API ******************** */
645
646 /**
647  * Free the given DNS record.
648  *
649  * @param r record to free
650  */
651 void
652 GNUNET_DNSPARSER_free_record (struct GNUNET_DNSPARSER_Record *r);
653
654
655 /**
656  * Free MX information record.
657  *
658  * @param mx record to free
659  */
660 void
661 GNUNET_DNSPARSER_free_mx (struct GNUNET_DNSPARSER_MxRecord *mx);
662
663
664 /**
665  * Free SRV information record.
666  *
667  * @param srv record to free
668  */
669 void
670 GNUNET_DNSPARSER_free_srv (struct GNUNET_DNSPARSER_SrvRecord *srv);
671
672
673 /**
674  * Free SOA information record.
675  *
676  * @param soa record to free
677  */
678 void
679 GNUNET_DNSPARSER_free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa);
680
681
682 #endif