2 This file is part of GNUnet
3 (C) 2010-2013 Christian Grothoff (and other contributing authors)
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.
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.
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.
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
27 #ifndef GNUNET_DNSPARSER_LIB_H
28 #define GNUNET_DNSPARSER_LIB_H
30 #include "gnunet_common.h"
31 #include "gnunet_tun_lib.h"
34 * Maximum length of a label in DNS.
36 #define GNUNET_DNSPARSER_MAX_LABEL_LENGTH 63
39 * Maximum length of a name in DNS.
41 #define GNUNET_DNSPARSER_MAX_NAME_LENGTH 253
45 * A few common DNS types.
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
62 struct GNUNET_DNSPARSER_Query
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.
75 * See GNUNET_DNSPARSER_TYPE_*.
80 * See GNUNET_TUN_DNS_CLASS_*.
82 uint16_t dns_traffic_class;
88 * Information from MX records (RFC 1035).
90 struct GNUNET_DNSPARSER_MxRecord
94 * Preference for this entry (lower value is higher preference).
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.
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.
121 struct GNUNET_DNSPARSER_SrvRecord
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.
135 * Transport protocol (typcially "tcp" or "udp", but others might be allowed).
136 * Without the underscore (!).
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.
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.
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.
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.
173 * TCP or UDP port of the service.
181 * Information from SOA records (RFC 1035).
183 struct GNUNET_DNSPARSER_SoaRecord
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.
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.
207 * The version number of the original copy of the zone.
212 * Time interval before the zone should be refreshed.
217 * Time interval that should elapse before a failed refresh should
223 * Time value that specifies the upper limit on the time interval
224 * that can elapse before the zone is no longer authoritative.
229 * The bit minimum TTL field that should be exported with any RR
232 uint32_t minimum_ttl;
238 * Binary record information (unparsed).
240 struct GNUNET_DNSPARSER_RawRecord
244 * Binary record data.
249 * Number of bytes in data.
256 * A DNS response record.
258 struct GNUNET_DNSPARSER_Record
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.
271 * Payload of the record (which one of these is valid depends on the 'type').
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.
286 * SOA data for SOA records.
288 struct GNUNET_DNSPARSER_SoaRecord *soa;
291 * MX data for MX records.
293 struct GNUNET_DNSPARSER_MxRecord *mx;
296 * SRV data for SRV records.
298 struct GNUNET_DNSPARSER_SrvRecord *srv;
301 * Raw data for all other types.
303 struct GNUNET_DNSPARSER_RawRecord raw;
309 * When does the record expire?
311 struct GNUNET_TIME_Absolute expiration_time;
314 * See GNUNET_DNSPARSER_TYPE_*.
319 * See GNUNET_TUN_DNS_CLASS_*.
321 uint16_t dns_traffic_class;
327 * Easy-to-process, parsed version of a DNS packet.
329 struct GNUNET_DNSPARSER_Packet
332 * Array of all queries in the packet, must contain "num_queries" entries.
334 struct GNUNET_DNSPARSER_Query *queries;
337 * Array of all answers in the packet, must contain "num_answers" entries.
339 struct GNUNET_DNSPARSER_Record *answers;
342 * Array of all authority records in the packet, must contain "num_authority_records" entries.
344 struct GNUNET_DNSPARSER_Record *authority_records;
347 * Array of all additional answers in the packet, must contain "num_additional_records" entries.
349 struct GNUNET_DNSPARSER_Record *additional_records;
352 * Number of queries in the packet.
354 unsigned int num_queries;
357 * Number of answers in the packet, should be 0 for queries.
359 unsigned int num_answers;
362 * Number of authoritative answers in the packet, should be 0 for queries.
364 unsigned int num_authority_records;
367 * Number of additional records in the packet, should be 0 for queries.
369 unsigned int num_additional_records;
372 * Bitfield of DNS flags.
374 struct GNUNET_TUN_DnsFlags flags;
377 * DNS ID (to match replies to requests).
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.
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
393 GNUNET_DNSPARSER_check_label (const char *label);
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.
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
406 GNUNET_DNSPARSER_check_name (const char *name);
410 * Parse a UDP payload of a DNS packet in to a nice struct for further
411 * processing and manipulation.
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
417 struct GNUNET_DNSPARSER_Packet *
418 GNUNET_DNSPARSER_parse (const char *udp_payload,
419 size_t udp_payload_length);
423 * Free memory taken by a packet.
425 * @param p packet to free
428 GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p);
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.
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
446 GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p,
451 /* ***************** low-level packing API ******************** */
454 * Add a DNS name to the UDP packet at the given location, converting
455 * the name to IDNA notation as necessary.
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
467 GNUNET_DNSPARSER_builder_add_name (char *dst,
474 * Add a DNS query to the UDP packet at the given location.
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
486 GNUNET_DNSPARSER_builder_add_query (char *dst,
489 const struct GNUNET_DNSPARSER_Query *query);
493 * Add an MX record to the UDP packet at the given location.
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
505 GNUNET_DNSPARSER_builder_add_mx (char *dst,
508 const struct GNUNET_DNSPARSER_MxRecord *mx);
512 * Add an SOA record to the UDP packet at the given location.
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
524 GNUNET_DNSPARSER_builder_add_soa (char *dst,
527 const struct GNUNET_DNSPARSER_SoaRecord *soa);
531 * Add an SRV record to the UDP packet at the given location.
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
543 GNUNET_DNSPARSER_builder_add_srv (char *dst,
546 const struct GNUNET_DNSPARSER_SrvRecord *srv);
548 /* ***************** low-level parsing API ******************** */
551 * Parse a DNS record entry.
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
561 GNUNET_DNSPARSER_parse_record (const char *udp_payload,
562 size_t udp_payload_length,
564 struct GNUNET_DNSPARSER_Record *r);
568 * Parse name inside of a DNS query or record.
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
577 GNUNET_DNSPARSER_parse_name (const char *udp_payload,
578 size_t udp_payload_length,
583 * Parse a DNS query entry.
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
593 GNUNET_DNSPARSER_parse_query (const char *udp_payload,
594 size_t udp_payload_length,
596 struct GNUNET_DNSPARSER_Query *q);
599 * Parse a DNS SOA record.
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
607 struct GNUNET_DNSPARSER_SoaRecord *
608 GNUNET_DNSPARSER_parse_soa (const char *udp_payload,
609 size_t udp_payload_length,
614 * Parse a DNS MX record.
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
622 struct GNUNET_DNSPARSER_MxRecord *
623 GNUNET_DNSPARSER_parse_mx (const char *udp_payload,
624 size_t udp_payload_length,
629 * Parse a DNS SRV record.
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
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,
644 /* ***************** low-level deallocation API ******************** */
647 * Free the given DNS record.
649 * @param r record to free
652 GNUNET_DNSPARSER_free_record (struct GNUNET_DNSPARSER_Record *r);
656 * Free MX information record.
658 * @param mx record to free
661 GNUNET_DNSPARSER_free_mx (struct GNUNET_DNSPARSER_MxRecord *mx);
665 * Free SRV information record.
667 * @param srv record to free
670 GNUNET_DNSPARSER_free_srv (struct GNUNET_DNSPARSER_SrvRecord *srv);
674 * Free SOA information record.
676 * @param soa record to free
679 GNUNET_DNSPARSER_free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa);