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_util_lib.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_CERT 37
57 #define GNUNET_DNSPARSER_TYPE_TLSA 52
63 struct GNUNET_DNSPARSER_Query
67 * Name of the record that the query is for (0-terminated).
68 * In UTF-8 format. The library will convert from and to DNS-IDNA
69 * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an
70 * individual label is well-formed. If a given name is not well-formed,
71 * creating the DNS packet will fail.
76 * See GNUNET_DNSPARSER_TYPE_*.
81 * See GNUNET_TUN_DNS_CLASS_*.
83 uint16_t dns_traffic_class;
89 * Information from MX records (RFC 1035).
91 struct GNUNET_DNSPARSER_MxRecord
95 * Preference for this entry (lower value is higher preference).
100 * Name of the mail server.
101 * In UTF-8 format. The library will convert from and to DNS-IDNA
102 * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an
103 * individual label is well-formed. If a given name is not well-formed,
104 * creating the DNS packet will fail.
112 * Information from SRV records (RFC 2782). The 'service', 'proto'
113 * and 'domain_name' fields together give the DNS-name which for SRV
114 * records is of the form "_$SERVICE._$PROTO.$DOMAIN_NAME". The DNS
115 * parser provides the full name in 'struct DNSPARSER_Record' and the
116 * individual components in the respective fields of this struct.
117 * When serializing, you CAN set the 'name' field of 'struct
118 * GNUNET_DNSPARSER_Record' to NULL, in which case the DNSPARSER code
119 * will populate 'name' from the 'service', 'proto' and 'domain_name'
120 * fields in this struct.
122 struct GNUNET_DNSPARSER_SrvRecord
126 * Service name without the underscore (!). Note that RFC 6335 clarifies the
127 * set of legal characters for service names.
128 * In UTF-8 format. The library will convert from and to DNS-IDNA
129 * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an
130 * individual label is well-formed. If a given name is not well-formed,
131 * creating the DNS packet will fail.
136 * Transport protocol (typcially "tcp" or "udp", but others might be allowed).
137 * Without the underscore (!).
142 * Domain name for which the record is valid
143 * In UTF-8 format. The library will convert from and to DNS-IDNA
144 * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an
145 * individual label is well-formed. If a given name is not well-formed,
146 * creating the DNS packet will fail.
151 * Hostname offering the service.
152 * In UTF-8 format. The library will convert from and to DNS-IDNA
153 * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an
154 * individual label is well-formed. If a given name is not well-formed,
155 * creating the DNS packet will fail.
160 * Preference for this entry (lower value is higher preference). Clients
161 * will contact hosts from the lowest-priority group first and fall back
162 * to higher priorities if the low-priority entries are unavailable.
167 * Relative weight for records with the same priority. Clients will use
168 * the hosts of the same (lowest) priority with a probability proportional
169 * to the weight given.
174 * TCP or UDP port of the service.
182 * DNS CERT types as defined in RFC 4398.
184 enum GNUNET_DNSPARSER_CertType
189 GNUNET_DNSPARSER_CERTTYPE_RESERVED = 0,
192 * An x509 PKIX certificate
194 GNUNET_DNSPARSER_CERTTYPE_PKIX = 1,
199 GNUNET_DNSPARSER_CERTTYPE_SKPI = 2,
204 GNUNET_DNSPARSER_CERTTYPE_PGP = 3,
207 * An x509 PKIX cert URL
209 GNUNET_DNSPARSER_CERTTYPE_IPKIX = 4,
214 GNUNET_DNSPARSER_CERTTYPE_ISKPI = 5,
217 * A PGP cert fingerprint and URL
219 GNUNET_DNSPARSER_CERTTYPE_IPGP = 6,
222 * An attribute Certificate
224 GNUNET_DNSPARSER_CERTTYPE_ACPKIX = 7,
227 * An attribute cert URL
229 GNUNET_DNSPARSER_CERTTYPE_IACKPIX = 8
234 * DNSCERT algorithms as defined in http://www.iana.org/assignments/
235 * dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml, under dns-sec-alg-numbers-1
237 enum GNUNET_DNSPARSER_CertAlgorithm
242 GNUNET_DNSPARSER_CERTALGO_UNDEFINED = 0,
247 GNUNET_DNSPARSER_CERTALGO_RSAMD5 = 1,
252 GNUNET_DNSPARSER_CERTALGO_DH = 2,
257 GNUNET_DNSPARSER_CERTALGO_DSASHA = 3,
262 GNUNET_DNSPARSER_CERTALGO_RSRVD4 = 4,
267 GNUNET_DNSPARSER_CERTALGO_RSASHA = 5,
272 GNUNET_DNSPARSER_CERTALGO_DSANSEC3 = 6,
277 GNUNET_DNSPARSER_CERTALGO_RSANSEC3 = 7,
282 GNUNET_DNSPARSER_CERTALGO_RSASHA256 = 8,
287 GNUNET_DNSPARSER_CERTALGO_RSRVD9 = 9,
292 GNUNET_DNSPARSER_CERTALGO_RSASHA512 = 10,
297 GNUNET_DNSPARSER_CERTALGO_GOST_R34 = 12,
300 * ECDSA Curve P-256/SHA256
302 GNUNET_DNSPARSER_CERTALGO_ECDSA_P256SHA256 = 13,
305 * ECDSA Curve P-384/SHA384
307 GNUNET_DNSPARSER_CERTALGO_ECDSA_P384SHA384 = 14
313 * Information from CERT records (RFC 4034).
315 struct GNUNET_DNSPARSER_CertRecord
321 enum GNUNET_DNSPARSER_CertType cert_type;
331 enum GNUNET_DNSPARSER_CertAlgorithm algorithm;
334 * Number of bytes in @e certificate_data
336 size_t certificate_size;
339 * Data of the certificate.
341 char *certificate_data;
347 * Information from SOA records (RFC 1035).
349 struct GNUNET_DNSPARSER_SoaRecord
353 * The domainname of the name server that was the
354 * original or primary source of data for this zone.
355 * In UTF-8 format. The library will convert from and to DNS-IDNA
356 * as necessary. Use #GNUNET_DNSPARSER_check_label to test if an
357 * individual label is well-formed. If a given name is not well-formed,
358 * creating the DNS packet will fail.
363 * A domainname which specifies the mailbox of the
364 * person responsible for this zone.
365 * In UTF-8 format. The library will convert from and to DNS-IDNA
366 * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an
367 * individual label is well-formed. If a given name is not well-formed,
368 * creating the DNS packet will fail.
373 * The version number of the original copy of the zone.
378 * Time interval before the zone should be refreshed.
383 * Time interval that should elapse before a failed refresh should
389 * Time value that specifies the upper limit on the time interval
390 * that can elapse before the zone is no longer authoritative.
395 * The bit minimum TTL field that should be exported with any RR
398 uint32_t minimum_ttl;
404 * Binary record information (unparsed).
406 struct GNUNET_DNSPARSER_RawRecord
410 * Binary record data.
415 * Number of bytes in data.
422 * A DNS response record.
424 struct GNUNET_DNSPARSER_Record
428 * Name of the record that the query is for (0-terminated).
429 * In UTF-8 format. The library will convert from and to DNS-IDNA
430 * as necessary. Use #GNUNET_DNSPARSER_check_label to test if an
431 * individual label is well-formed. If a given name is not well-formed,
432 * creating the DNS packet will fail.
437 * Payload of the record (which one of these is valid depends on the 'type').
443 * For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
444 * In UTF-8 format. The library will convert from and to DNS-IDNA
445 * as necessary. Use #GNUNET_DNSPARSER_check_label to test if an
446 * individual label is well-formed. If a given name is not well-formed,
447 * creating the DNS packet will fail.
452 * SOA data for SOA records.
454 struct GNUNET_DNSPARSER_SoaRecord *soa;
457 * CERT data for CERT records.
459 struct GNUNET_DNSPARSER_CertRecord *cert;
462 * MX data for MX records.
464 struct GNUNET_DNSPARSER_MxRecord *mx;
467 * SRV data for SRV records.
469 struct GNUNET_DNSPARSER_SrvRecord *srv;
472 * Raw data for all other types.
474 struct GNUNET_DNSPARSER_RawRecord raw;
480 * When does the record expire?
482 struct GNUNET_TIME_Absolute expiration_time;
485 * See GNUNET_DNSPARSER_TYPE_*.
490 * See GNUNET_TUN_DNS_CLASS_*.
492 uint16_t dns_traffic_class;
498 * Easy-to-process, parsed version of a DNS packet.
500 struct GNUNET_DNSPARSER_Packet
503 * Array of all queries in the packet, must contain "num_queries" entries.
505 struct GNUNET_DNSPARSER_Query *queries;
508 * Array of all answers in the packet, must contain "num_answers" entries.
510 struct GNUNET_DNSPARSER_Record *answers;
513 * Array of all authority records in the packet, must contain "num_authority_records" entries.
515 struct GNUNET_DNSPARSER_Record *authority_records;
518 * Array of all additional answers in the packet, must contain "num_additional_records" entries.
520 struct GNUNET_DNSPARSER_Record *additional_records;
523 * Number of queries in the packet.
525 unsigned int num_queries;
528 * Number of answers in the packet, should be 0 for queries.
530 unsigned int num_answers;
533 * Number of authoritative answers in the packet, should be 0 for queries.
535 unsigned int num_authority_records;
538 * Number of additional records in the packet, should be 0 for queries.
540 unsigned int num_additional_records;
543 * Bitfield of DNS flags.
545 struct GNUNET_TUN_DnsFlags flags;
548 * DNS ID (to match replies to requests).
556 * Check if a label in UTF-8 format can be coded into valid IDNA.
557 * This can fail if the ASCII-conversion becomes longer than 63 characters.
559 * @param label label to check (UTF-8 string)
560 * @return #GNUNET_OK if the label can be converted to IDNA,
561 * #GNUNET_SYSERR if the label is not valid for DNS names
564 GNUNET_DNSPARSER_check_label (const char *label);
568 * Check if a hostname in UTF-8 format can be coded into valid IDNA.
569 * This can fail if a label becomes longer than 63 characters or if
570 * the entire name exceeds 253 characters.
572 * @param name name to check (UTF-8 string)
573 * @return #GNUNET_OK if the label can be converted to IDNA,
574 * #GNUNET_SYSERR if the label is not valid for DNS names
577 GNUNET_DNSPARSER_check_name (const char *name);
581 * Parse a UDP payload of a DNS packet in to a nice struct for further
582 * processing and manipulation.
584 * @param udp_payload wire-format of the DNS packet
585 * @param udp_payload_length number of bytes in @a udp_payload
586 * @return NULL on error, otherwise the parsed packet
588 struct GNUNET_DNSPARSER_Packet *
589 GNUNET_DNSPARSER_parse (const char *udp_payload,
590 size_t udp_payload_length);
594 * Free memory taken by a packet.
596 * @param p packet to free
599 GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p);
603 * Given a DNS packet @a p, generate the corresponding UDP payload.
604 * Note that we do not attempt to pack the strings with pointers
605 * as this would complicate the code and this is about being
606 * simple and secure, not fast, fancy and broken like bind.
608 * @param p packet to pack
609 * @param max maximum allowed size for the resulting UDP payload
610 * @param buf set to a buffer with the packed message
611 * @param buf_length set to the length of @a buf
612 * @return #GNUNET_SYSERR if @a p is invalid
613 * #GNUNET_NO if @a p was truncated (but there is still a result in @a buf)
614 * #GNUNET_OK if @a p was packed completely into @a buf
617 GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p,
622 /* ***************** low-level packing API ******************** */
625 * Add a DNS name to the UDP packet at the given location, converting
626 * the name to IDNA notation as necessary.
628 * @param dst where to write the name (UDP packet)
629 * @param dst_len number of bytes in @a dst
630 * @param off pointer to offset where to write the name (increment by bytes used)
631 * must not be changed if there is an error
632 * @param name name to write
633 * @return #GNUNET_SYSERR if @a name is invalid
634 * #GNUNET_NO if @a name did not fit
635 * #GNUNET_OK if @a name was added to @a dst
638 GNUNET_DNSPARSER_builder_add_name (char *dst,
645 * Add a DNS query to the UDP packet at the given location.
647 * @param dst where to write the query
648 * @param dst_len number of bytes in @a dst
649 * @param off pointer to offset where to write the query (increment by bytes used)
650 * must not be changed if there is an error
651 * @param query query to write
652 * @return #GNUNET_SYSERR if @a query is invalid
653 * #GNUNET_NO if @a query did not fit
654 * #GNUNET_OK if @a query was added to @a dst
657 GNUNET_DNSPARSER_builder_add_query (char *dst,
660 const struct GNUNET_DNSPARSER_Query *query);
664 * Add an MX record to the UDP packet at the given location.
666 * @param dst where to write the mx record
667 * @param dst_len number of bytes in @a dst
668 * @param off pointer to offset where to write the mx information (increment by bytes used);
669 * can also change if there was an error
670 * @param mx mx information to write
671 * @return #GNUNET_SYSERR if @a mx is invalid
672 * #GNUNET_NO if @a mx did not fit
673 * #GNUNET_OK if @a mx was added to @a dst
676 GNUNET_DNSPARSER_builder_add_mx (char *dst,
679 const struct GNUNET_DNSPARSER_MxRecord *mx);
683 * Add an SOA record to the UDP packet at the given location.
685 * @param dst where to write the SOA record
686 * @param dst_len number of bytes in @a dst
687 * @param off pointer to offset where to write the SOA information (increment by bytes used)
688 * can also change if there was an error
689 * @param soa SOA information to write
690 * @return #GNUNET_SYSERR if @a soa is invalid
691 * #GNUNET_NO if @a soa did not fit
692 * #GNUNET_OK if @a soa was added to @a dst
695 GNUNET_DNSPARSER_builder_add_soa (char *dst,
698 const struct GNUNET_DNSPARSER_SoaRecord *soa);
702 * Add CERT record to the UDP packet at the given location.
704 * @param dst where to write the CERT record
705 * @param dst_len number of bytes in @a dst
706 * @param off pointer to offset where to write the CERT information (increment by bytes used)
707 * can also change if there was an error
708 * @param cert CERT information to write
709 * @return #GNUNET_SYSERR if @a soa is invalid
710 * #GNUNET_NO if @a soa did not fit
711 * #GNUNET_OK if @a soa was added to @a dst
714 GNUNET_DNSPARSER_builder_add_cert (char *dst,
717 const struct GNUNET_DNSPARSER_CertRecord *cert);
721 * Add an SRV record to the UDP packet at the given location.
723 * @param dst where to write the SRV record
724 * @param dst_len number of bytes in @a dst
725 * @param off pointer to offset where to write the SRV information (increment by bytes used)
726 * can also change if there was an error
727 * @param srv SRV information to write
728 * @return #GNUNET_SYSERR if @a srv is invalid
729 * #GNUNET_NO if @a srv did not fit
730 * #GNUNET_OK if @a srv was added to @a dst
733 GNUNET_DNSPARSER_builder_add_srv (char *dst,
736 const struct GNUNET_DNSPARSER_SrvRecord *srv);
738 /* ***************** low-level parsing API ******************** */
741 * Parse a DNS record entry.
743 * @param udp_payload entire UDP payload
744 * @param udp_payload_length length of @a udp_payload
745 * @param off pointer to the offset of the record to parse in the udp_payload (to be
746 * incremented by the size of the record)
747 * @param r where to write the record information
748 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the record is malformed
751 GNUNET_DNSPARSER_parse_record (const char *udp_payload,
752 size_t udp_payload_length,
754 struct GNUNET_DNSPARSER_Record *r);
758 * Parse name inside of a DNS query or record.
760 * @param udp_payload entire UDP payload
761 * @param udp_payload_length length of @a udp_payload
762 * @param off pointer to the offset of the name to parse in the udp_payload (to be
763 * incremented by the size of the name)
764 * @return name as 0-terminated C string on success, NULL if the payload is malformed
767 GNUNET_DNSPARSER_parse_name (const char *udp_payload,
768 size_t udp_payload_length,
773 * Parse a DNS query entry.
775 * @param udp_payload entire UDP payload
776 * @param udp_payload_length length of @a udp_payload
777 * @param off pointer to the offset of the query to parse in the udp_payload (to be
778 * incremented by the size of the query)
779 * @param q where to write the query information
780 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the query is malformed
783 GNUNET_DNSPARSER_parse_query (const char *udp_payload,
784 size_t udp_payload_length,
786 struct GNUNET_DNSPARSER_Query *q);
790 * Parse a DNS SOA record.
792 * @param udp_payload reference to UDP packet
793 * @param udp_payload_length length of @a udp_payload
794 * @param off pointer to the offset of the query to parse in the SOA record (to be
795 * incremented by the size of the record), unchanged on error
796 * @return the parsed SOA record, NULL on error
798 struct GNUNET_DNSPARSER_SoaRecord *
799 GNUNET_DNSPARSER_parse_soa (const char *udp_payload,
800 size_t udp_payload_length,
805 * Parse a DNS CERT record.
807 * @param udp_payload reference to UDP packet
808 * @param udp_payload_length length of @a udp_payload
809 * @param off pointer to the offset of the query to parse in the CERT record (to be
810 * incremented by the size of the record), unchanged on error
811 * @return the parsed CERT record, NULL on error
813 struct GNUNET_DNSPARSER_CertRecord *
814 GNUNET_DNSPARSER_parse_cert (const char *udp_payload,
815 size_t udp_payload_length,
820 * Parse a DNS MX record.
822 * @param udp_payload reference to UDP packet
823 * @param udp_payload_length length of @a udp_payload
824 * @param off pointer to the offset of the query to parse in the MX record (to be
825 * incremented by the size of the record), unchanged on error
826 * @return the parsed MX record, NULL on error
828 struct GNUNET_DNSPARSER_MxRecord *
829 GNUNET_DNSPARSER_parse_mx (const char *udp_payload,
830 size_t udp_payload_length,
835 * Parse a DNS SRV record.
837 * @param r_name name of the SRV record
838 * @param udp_payload reference to UDP packet
839 * @param udp_payload_length length of @a udp_payload
840 * @param off pointer to the offset of the query to parse in the SRV record (to be
841 * incremented by the size of the record), unchanged on error
842 * @return the parsed SRV record, NULL on error
844 struct GNUNET_DNSPARSER_SrvRecord *
845 GNUNET_DNSPARSER_parse_srv (const char *r_name,
846 const char *udp_payload,
847 size_t udp_payload_length,
850 /* ***************** low-level deallocation API ******************** */
853 * Free the given DNS record.
855 * @param r record to free
858 GNUNET_DNSPARSER_free_record (struct GNUNET_DNSPARSER_Record *r);
862 * Free MX information record.
864 * @param mx record to free
867 GNUNET_DNSPARSER_free_mx (struct GNUNET_DNSPARSER_MxRecord *mx);
871 * Free SRV information record.
873 * @param srv record to free
876 GNUNET_DNSPARSER_free_srv (struct GNUNET_DNSPARSER_SrvRecord *srv);
880 * Free SOA information record.
882 * @param soa record to free
885 GNUNET_DNSPARSER_free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa);
889 * Free CERT information record.
891 * @param cert record to free
894 GNUNET_DNSPARSER_free_cert (struct GNUNET_DNSPARSER_CertRecord *cert);