0fd74b7cf1a6b09766f5cb9ac293893bbb5843de
[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_dnsparse_lib.h
23  * @brief API for helper library to parse DNS packets. 
24  * @author Philipp Toelke
25  */
26 #ifndef GNUNET_DNSPARSER_LIB_H
27 #define GNUNET_DNSPARSER_LIB_H
28
29 #include "platform.h"
30 #include "gnunet_common.h"
31
32 /**
33  * A few common DNS types.
34  */
35 #define GNUNET_DNSPARSER_TYPE_A 1
36 #define GNUNET_DNSPARSER_TYPE_NS 2
37 #define GNUNET_DNSPARSER_TYPE_CNAME 5
38 #define GNUNET_DNSPARSER_TYPE_SOA 6
39 #define GNUNET_DNSPARSER_TYPE_PTR 12
40 #define GNUNET_DNSPARSER_TYPE_MX 15
41 #define GNUNET_DNSPARSER_TYPE_TXT 16
42 #define GNUNET_DNSPARSER_TYPE_AAAA 28
43 #define GNUNET_DNSPARSER_TYPE_IXFR 251
44 #define GNUNET_DNSPARSER_TYPE_AXFR 252
45
46 /**
47  * A few common DNS classes (ok, only one is common, but I list a
48  * couple more to make it clear what we're talking about here).
49  */
50 #define GNUNET_DNSPARSER_CLASS_INTERNET 1
51 #define GNUNET_DNSPARSER_CLASS_CHAOS 3
52 #define GNUNET_DNSPARSER_CLASS_HESIOD 4
53
54 #define GNUNET_DNSPARSER_OPCODE_QUERY 0
55 #define GNUNET_DNSPARSER_OPCODE_INVERSE_QUERY 1
56 #define GNUNET_DNSPARSER_OPCODE_STATUS 2
57
58 /**
59  * RFC 1035 codes.
60  */
61 #define GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR 0
62 #define GNUNET_DNSPARSER_RETURN_CODE_FORMAT_ERROR 1
63 #define GNUNET_DNSPARSER_RETURN_CODE_SERVER_FAILURE 2
64 #define GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR 3
65 #define GNUNET_DNSPARSER_RETURN_CODE_NOT_IMPLEMENTED 4
66 #define GNUNET_DNSPARSER_RETURN_CODE_REFUSED 5
67
68 /**
69  * RFC 2136 codes
70  */
71 #define GNUNET_DNSPARSER_RETURN_CODE_YXDOMAIN 6
72 #define GNUNET_DNSPARSER_RETURN_CODE_YXRRSET 7
73 #define GNUNET_DNSPARSER_RETURN_CODE_NXRRSET 8
74 #define GNUNET_DNSPARSER_RETURN_CODE_NOT_AUTH 9
75 #define GNUNET_DNSPARSER_RETURN_CODE_NOT_ZONE 10
76
77 /**
78  * DNS flags (largely RFC 1035 / RFC 2136).
79  */
80 struct GNUNET_DNSPARSER_Flags
81 {
82   /**
83    * Set to 1 if recursion is desired (client -> server)
84    */
85   unsigned int recursion_desired    : 1 GNUNET_PACKED;  
86   
87   /**
88    * Set to 1 if message is truncated
89    */
90   unsigned int message_truncated    : 1 GNUNET_PACKED; 
91   
92   /**
93    * Set to 1 if this is an authoritative answer
94    */
95   unsigned int authoritative_answer : 1 GNUNET_PACKED;
96   
97   /**
98    * See GNUNET_DNSPARSER_OPCODE_ defines.
99    */
100   unsigned int opcode               : 4 GNUNET_PACKED;  
101   
102   /**
103    * query:0, response:1
104    */
105   unsigned int query_or_response    : 1 GNUNET_PACKED;  
106   
107   /**
108    * See GNUNET_DNSPARSER_RETURN_CODE_ defines.
109    */
110   unsigned int return_code          : 4 GNUNET_PACKED; 
111   
112   /**
113    * See RFC 4035.
114    */
115   unsigned int checking_disabled    : 1 GNUNET_PACKED; 
116   
117   /**
118    * Response has been cryptographically verified, RFC 4035.
119    */
120   unsigned int authenticated_data   : 1 GNUNET_PACKED;
121   
122   /**
123    * Always zero.
124    */
125   unsigned int zero                 : 1 GNUNET_PACKED;
126   
127   /**
128    * Set to 1 if recursion is available (server -> client)
129    */
130   unsigned int recursion_available  : 1 GNUNET_PACKED; 
131   
132 };
133
134
135 /**
136  * A DNS query.
137  */
138 struct GNUNET_DNSPARSER_Query
139 {
140
141   /**
142    * Name of the record that the query is for (0-terminated).
143    */
144   char *name;
145
146   /**
147    * See GNUNET_DNSPARSER_TYPE_*.
148    */
149   uint16_t type;
150
151   /**
152    * See GNUNET_DNSPARSER_CLASS_*.
153    */
154   uint16_t class;
155
156 };
157
158
159 /**
160  * A DNS response record.
161  */
162 struct GNUNET_DNSPARSER_Record
163 {
164
165   /**
166    * Name of the record that the query is for (0-terminated).
167    */
168   char *name;
169
170   /**
171    * Raw data, NOT a 0-terminated string (at least not always).
172    */
173   char *data;
174
175   /**
176    * Number of bytes in data.
177    */
178   size_t data_len;
179
180   /**
181    * When does the record expire?
182    */
183   struct GNUNET_TIME_Absolute expiration_time;
184
185   /**
186    * See GNUNET_DNSPARSER_TYPE_*.
187    */
188   uint16_t type;
189
190   /**
191    * See GNUNET_DNSPARSER_CLASS_*.
192    */
193   uint16_t class;
194
195 };
196
197
198 /**
199  * Easy-to-process, parsed version of a DNS packet.
200  */
201 struct GNUNET_DNSPARSER_Packet
202 {
203   /**
204    * Array of all queries in the packet, must contain "num_queries" entries.
205    */
206   struct GNUNET_DNSPARSER_Query *queries;
207
208   /**
209    * Array of all answers in the packet, must contain "num_answers" entries.
210    */
211   struct GNUNET_DNSPARSER_Record *answers;
212
213   /**
214    * Array of all authority records in the packet, must contain "num_authority_records" entries.
215    */
216   struct GNUNET_DNSPARSER_Record *authority_records;
217
218   /**
219    * Array of all additional answers in the packet, must contain "num_additional_records" entries.
220    */
221   struct GNUNET_DNSPARSER_Record *additional_records;
222
223   /**
224    * Number of queries in the packet.
225    */
226   unsigned int num_queries;
227
228   /**
229    * Number of answers in the packet, should be 0 for queries.
230    */
231   unsigned int num_answers;
232
233   /**
234    * Number of authoritative answers in the packet, should be 0 for queries.
235    */
236   unsigned int num_authority_records;
237
238   /**
239    * Number of additional records in the packet, should be 0 for queries.
240    */
241   unsigned int num_additional_records;
242
243   /**
244    * Bitfield of DNS flags.
245    */ 
246   struct GNUNET_DNSPARSER_Flags flags;
247
248   /**
249    * DNS ID (to match replies to requests).
250    */
251   uint16_t id;
252
253 };
254
255
256 /**
257  * Parse a UDP payload of a DNS packet in to a nice struct for further
258  * processing and manipulation.
259  *
260  * @param udp_payload wire-format of the DNS packet
261  * @param udp_payload_length number of bytes in udp_payload 
262  * @return NULL on error, otherwise the parsed packet
263  */
264 struct GNUNET_DNSPARSER_Packet *
265 GNUNET_DNSPARSER_parse (const char *udp_payload,
266                         size_t udp_payload_length);
267
268
269 /**
270  * Free memory taken by a packet.
271  *
272  * @param p packet to free
273  */
274 void
275 GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p);
276
277
278 /**
279  * Given a DNS packet, generate the corresponding UDP payload.
280  *
281  * @param p packet to pack
282  * @param buf set to a buffer with the packed message
283  * @param buf_length set to the length of buf
284  * @return GNUNET_SYSERR if 'p' is invalid
285  *         GNUNET_NO if 'p' was truncated (but there is still a result in 'buf')
286  *         GNUNET_OK if 'p' was packed completely into '*buf'
287  */
288 int
289 GNUNET_DNSPARSER_pack (struct GNUNET_DNSPARSER_Packet *p,
290                        char **buf,
291                        size_t *buf_length);
292
293
294
295
296 /* legacy API below */
297
298 // DNS-Stuff
299 GNUNET_NETWORK_STRUCT_BEGIN
300
301 struct dns_static
302 {
303   uint16_t id GNUNET_PACKED;
304
305   unsigned rd:1 GNUNET_PACKED;  // recursion desired (client -> server)
306   unsigned tc:1 GNUNET_PACKED;  // message is truncated
307   unsigned aa:1 GNUNET_PACKED;  // authoritative answer
308   unsigned op:4 GNUNET_PACKED;  // query:0, inverse q.:1, status: 2
309   unsigned qr:1 GNUNET_PACKED;  // query:0, response:1
310
311   unsigned rcode:4 GNUNET_PACKED;       // 0 No error
312   // 1 Format error
313   // 2 Server failure
314   // 3 Name Error
315   // 4 Not Implemented
316   // 5 Refused
317   unsigned z:3 GNUNET_PACKED;   // reserved
318   unsigned ra:1 GNUNET_PACKED;  // recursion available (server -> client)
319
320   uint16_t qdcount GNUNET_PACKED;       // number of questions
321   uint16_t ancount GNUNET_PACKED;       // number of answers
322   uint16_t nscount GNUNET_PACKED;       // number of authority-records
323   uint16_t arcount GNUNET_PACKED;       // number of additional records
324 };
325 GNUNET_NETWORK_STRUCT_END
326
327
328 struct dns_pkt
329 {
330   struct dns_static s;
331   unsigned char data[1];
332 };
333
334 struct dns_pkt_parsed
335 {
336   struct dns_static s;
337   struct dns_query **queries;
338   struct dns_record **answers;
339   struct dns_record **nameservers;
340   struct dns_record **additional;
341 };
342
343 struct dns_query_line
344 {
345   uint16_t type;
346   uint16_t class;
347 };
348
349 struct dns_query
350 {
351   char *name;
352   unsigned char namelen;
353   uint16_t qtype;
354   uint16_t qclass;
355 };
356
357 struct dns_record_line
358 {
359   uint16_t type;
360   uint16_t class;
361   uint32_t ttl;
362   uint16_t data_len;
363   unsigned char data;
364 };
365
366 struct dns_record
367 {
368   char *name;
369   unsigned char namelen;
370   uint16_t type;
371   uint16_t class;
372   uint32_t ttl;
373   uint16_t data_len;
374   unsigned char *data;
375 };
376
377
378 struct dns_pkt_parsed *
379 parse_dns_packet (struct dns_pkt *pkt);
380
381 struct dns_pkt *
382 unparse_dns_packet (struct dns_pkt_parsed *pkt);
383
384 void
385 free_parsed_dns_packet (struct dns_pkt_parsed *ppkt);
386
387 #endif