missing check
[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 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 #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 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 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 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, generate the corresponding UDP payload.
433  *
434  * @param p packet to pack
435  * @param max maximum allowed size for the resulting UDP payload
436  * @param buf set to a buffer with the packed message
437  * @param buf_length set to the length of buf
438  * @return GNUNET_SYSERR if 'p' is invalid
439  *         GNUNET_NO if 'p' was truncated (but there is still a result in 'buf')
440  *         GNUNET_OK if 'p' was packed completely into '*buf'
441  */
442 int
443 GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p,
444                        uint16_t max,
445                        char **buf,
446                        size_t *buf_length);
447
448
449 #endif