extend API to enalbe exclusive port ranges to be specified for testing-system objects
[oweals/gnunet.git] / src / include / gnunet_dnsparser_lib.h
index a9ed5b3b2a986034d218f128e63d108e865992b1..328a2286a605d907321907a994268e91cb5b2b87 100644 (file)
-#ifndef _GNVPN_DNSP_H_
-#define _GNVPN_DNSP_H_
+/*
+      This file is part of GNUnet
+      (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors)
+
+      GNUnet is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published
+      by the Free Software Foundation; either version 2, or (at your
+      option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with GNUnet; see the file COPYING.  If not, write to the
+      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+      Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file include/gnunet_dnsparser_lib.h
+ * @brief API for helper library to parse DNS packets. 
+ * @author Philipp Toelke
+ * @author Christian Grothoff
+ */
+#ifndef GNUNET_DNSPARSER_LIB_H
+#define GNUNET_DNSPARSER_LIB_H
 
 #include "platform.h"
 #include "gnunet_common.h"
 
-// DNS-Stuff
-GNUNET_NETWORK_STRUCT_BEGIN
+/**
+ * A few common DNS types.
+ */
+#define GNUNET_DNSPARSER_TYPE_A 1
+#define GNUNET_DNSPARSER_TYPE_NS 2
+#define GNUNET_DNSPARSER_TYPE_CNAME 5
+#define GNUNET_DNSPARSER_TYPE_SOA 6
+#define GNUNET_DNSPARSER_TYPE_PTR 12
+#define GNUNET_DNSPARSER_TYPE_MX 15
+#define GNUNET_DNSPARSER_TYPE_TXT 16
+#define GNUNET_DNSPARSER_TYPE_AAAA 28
+#define GNUNET_DNSPARSER_TYPE_SRV 33
+#define GNUNET_DNSPARSER_TYPE_TLSA 52
+
+/**
+ * A few common DNS classes (ok, only one is common, but I list a
+ * couple more to make it clear what we're talking about here).
+ */
+#define GNUNET_DNSPARSER_CLASS_INTERNET 1
+#define GNUNET_DNSPARSER_CLASS_CHAOS 3
+#define GNUNET_DNSPARSER_CLASS_HESIOD 4
 
-struct dns_static
+#define GNUNET_DNSPARSER_OPCODE_QUERY 0
+#define GNUNET_DNSPARSER_OPCODE_INVERSE_QUERY 1
+#define GNUNET_DNSPARSER_OPCODE_STATUS 2
+
+/**
+ * RFC 1035 codes.
+ */
+#define GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR 0
+#define GNUNET_DNSPARSER_RETURN_CODE_FORMAT_ERROR 1
+#define GNUNET_DNSPARSER_RETURN_CODE_SERVER_FAILURE 2
+#define GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR 3
+#define GNUNET_DNSPARSER_RETURN_CODE_NOT_IMPLEMENTED 4
+#define GNUNET_DNSPARSER_RETURN_CODE_REFUSED 5
+
+/**
+ * RFC 2136 codes
+ */
+#define GNUNET_DNSPARSER_RETURN_CODE_YXDOMAIN 6
+#define GNUNET_DNSPARSER_RETURN_CODE_YXRRSET 7
+#define GNUNET_DNSPARSER_RETURN_CODE_NXRRSET 8
+#define GNUNET_DNSPARSER_RETURN_CODE_NOT_AUTH 9
+#define GNUNET_DNSPARSER_RETURN_CODE_NOT_ZONE 10
+
+/**
+ * DNS flags (largely RFC 1035 / RFC 2136).
+ */
+struct GNUNET_DNSPARSER_Flags
 {
-  uint16_t id GNUNET_PACKED;
-
-  unsigned rd:1 GNUNET_PACKED;  // recursion desired (client -> server)
-  unsigned tc:1 GNUNET_PACKED;  // message is truncated
-  unsigned aa:1 GNUNET_PACKED;  // authoritative answer
-  unsigned op:4 GNUNET_PACKED;  // query:0, inverse q.:1, status: 2
-  unsigned qr:1 GNUNET_PACKED;  // query:0, response:1
-
-  unsigned rcode:4 GNUNET_PACKED;       // 0 No error
-  // 1 Format error
-  // 2 Server failure
-  // 3 Name Error
-  // 4 Not Implemented
-  // 5 Refused
-  unsigned z:3 GNUNET_PACKED;   // reserved
-  unsigned ra:1 GNUNET_PACKED;  // recursion available (server -> client)
-
-  uint16_t qdcount GNUNET_PACKED;       // number of questions
-  uint16_t ancount GNUNET_PACKED;       // number of answers
-  uint16_t nscount GNUNET_PACKED;       // number of authority-records
-  uint16_t arcount GNUNET_PACKED;       // number of additional records
-};
-GNUNET_NETWORK_STRUCT_END
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  /**
+   * Set to 1 if recursion is desired (client -> server)
+   */
+  unsigned int recursion_desired    : 1 GNUNET_PACKED;  
+  
+  /**
+   * Set to 1 if message is truncated
+   */
+  unsigned int message_truncated    : 1 GNUNET_PACKED; 
+  
+  /**
+   * Set to 1 if this is an authoritative answer
+   */
+  unsigned int authoritative_answer : 1 GNUNET_PACKED;
+  
+  /**
+   * See GNUNET_DNSPARSER_OPCODE_ defines.
+   */
+  unsigned int opcode               : 4 GNUNET_PACKED;  
+  
+  /**
+   * query:0, response:1
+   */
+  unsigned int query_or_response    : 1 GNUNET_PACKED;  
+  
+  /**
+   * See GNUNET_DNSPARSER_RETURN_CODE_ defines.
+   */
+  unsigned int return_code          : 4 GNUNET_PACKED; 
+  
+  /**
+   * See RFC 4035.
+   */
+  unsigned int checking_disabled    : 1 GNUNET_PACKED; 
+  
+  /**
+   * Response has been cryptographically verified, RFC 4035.
+   */
+  unsigned int authenticated_data   : 1 GNUNET_PACKED;
+  
+  /**
+   * Always zero.
+   */
+  unsigned int zero                 : 1 GNUNET_PACKED;
+  
+  /**
+   * Set to 1 if recursion is available (server -> client)
+   */
+  unsigned int recursion_available  : 1 GNUNET_PACKED; 
+#elif __BYTE_ORDER == __BIG_ENDIAN
+  
+  /**
+   * query:0, response:1
+   */
+  unsigned int query_or_response    : 1 GNUNET_PACKED;  
+  
+  /**
+   * See GNUNET_DNSPARSER_OPCODE_ defines.
+   */
+  unsigned int opcode               : 4 GNUNET_PACKED;  
+  
+  /**
+   * Set to 1 if this is an authoritative answer
+   */
+  unsigned int authoritative_answer : 1 GNUNET_PACKED;
+  
+  /**
+   * Set to 1 if message is truncated
+   */
+  unsigned int message_truncated    : 1 GNUNET_PACKED; 
+  
+  /**
+   * Set to 1 if recursion is desired (client -> server)
+   */
+  unsigned int recursion_desired    : 1 GNUNET_PACKED;  
 
-struct dns_pkt
+  /**
+   * Set to 1 if recursion is available (server -> client)
+   */
+  unsigned int recursion_available  : 1 GNUNET_PACKED;
+  
+  /**
+   * Always zero.
+   */
+  unsigned int zero                 : 1 GNUNET_PACKED;
+  
+  /**
+   * Response has been cryptographically verified, RFC 4035.
+   */
+  unsigned int authenticated_data   : 1 GNUNET_PACKED;
+  
+  /**
+   * See RFC 4035.
+   */
+  unsigned int checking_disabled    : 1 GNUNET_PACKED; 
+  
+  /**
+   * See GNUNET_DNSPARSER_RETURN_CODE_ defines.
+   */  
+  unsigned int return_code          : 4 GNUNET_PACKED; 
+#else
+  #error byteorder undefined
+#endif
+  
+} GNUNET_GCC_STRUCT_LAYOUT;
+
+
+/**
+ * A DNS query.
+ */
+struct GNUNET_DNSPARSER_Query
 {
-  struct dns_static s;
-  unsigned char data[1];
+
+  /**
+   * Name of the record that the query is for (0-terminated).
+   */
+  char *name;
+
+  /**
+   * See GNUNET_DNSPARSER_TYPE_*.
+   */
+  uint16_t type;
+
+  /**
+   * See GNUNET_DNSPARSER_CLASS_*.
+   */
+  uint16_t class;
+
 };
 
-struct dns_pkt_parsed
+
+/**
+ * Information from MX records (RFC 1035).
+ */
+struct GNUNET_DNSPARSER_MxRecord
 {
-  struct dns_static s;
-  struct dns_query **queries;
-  struct dns_record **answers;
-  struct dns_record **nameservers;
-  struct dns_record **additional;
+  
+  /**
+   * Preference for this entry (lower value is higher preference).
+   */
+  uint16_t preference;
+
+  /**
+   * Name of the mail server.
+   */
+  char *mxhost;
+
 };
 
-struct dns_query_line
+
+/**
+ * Information from SRV records (RFC 2782).  The 'service', 'proto'
+ * and 'domain_name' fields together give the DNS-name which for SRV
+ * records is of the form "_$SERVICE._$PROTO.$DOMAIN_NAME".  The DNS
+ * parser provides the full name in 'struct DNSPARSER_Record' and the
+ * individual components in the respective fields of this struct.
+ * When serializing, you CAN set the 'name' field of 'struct
+ * GNUNET_DNSPARSER_Record' to NULL, in which case the DNSPARSER code
+ * will populate 'name' from the 'service', 'proto' and 'domain_name'
+ * fields in this struct.
+ */
+struct GNUNET_DNSPARSER_SrvRecord
 {
-  unsigned short type;
-  unsigned short class;
+  
+  /**
+   * Service name without the underscore (!).  Note that RFC 6335 clarifies the
+   * set of legal characters for service names.
+   */
+  char *service;
+
+  /**
+   * Transport protocol (typcially "tcp" or "udp", but others might be allowed).
+   * Without the underscore (!).
+   */
+  char *proto;
+
+  /**
+   * Domain name for which the record is valid
+   */
+  char *domain_name;
+
+  /**
+   * Hostname offering the service.
+   */
+  char *target;
+
+  /**
+   * Preference for this entry (lower value is higher preference).  Clients
+   * will contact hosts from the lowest-priority group first and fall back
+   * to higher priorities if the low-priority entries are unavailable.
+   */
+  uint16_t priority;
+
+  /**
+   * Relative weight for records with the same priority.  Clients will use
+   * the hosts of the same (lowest) priority with a probability proportional
+   * to the weight given.
+   */
+  uint16_t weight;
+
+  /**
+   * TCP or UDP port of the service.
+   */
+  uint16_t port;
+
 };
 
-struct dns_query
+  
+/**
+ * Information from SOA records (RFC 1035).
+ */
+struct GNUNET_DNSPARSER_SoaRecord
 {
-  char *name;
-  unsigned char namelen;
-  unsigned short qtype;
-  unsigned short qclass;
+  
+  /**
+   *The domainname of the name server that was the
+   * original or primary source of data for this zone.
+   */
+  char *mname;
+
+  /**
+   * A domainname which specifies the mailbox of the
+   * person responsible for this zone.
+   */
+  char *rname;
+
+  /**
+   * The version number of the original copy of the zone.  
+   */
+  uint32_t serial;
+
+  /**
+   * Time interval before the zone should be refreshed.
+   */
+  uint32_t refresh;
+
+  /**
+   * Time interval that should elapse before a failed refresh should
+   * be retried.
+   */
+  uint32_t retry;
+
+  /**
+   * Time value that specifies the upper limit on the time interval
+   * that can elapse before the zone is no longer authoritative.
+   */
+  uint32_t expire;
+
+  /**
+   * The bit minimum TTL field that should be exported with any RR
+   * from this zone.
+   */
+  uint32_t minimum_ttl;
+  
 };
 
-struct dns_record_line
+
+/**
+ * Binary record information (unparsed).
+ */
+struct GNUNET_DNSPARSER_RawRecord
 {
-  unsigned short type;
-  unsigned short class;
-  unsigned int ttl;
-  unsigned short data_len;
-  unsigned char data;
+
+  /**
+   * Binary record data.
+   */
+  void *data;
+
+  /**
+   * Number of bytes in data.
+   */
+  size_t data_len;
 };
 
-struct dns_record
+
+/**
+ * A DNS response record.
+ */
+struct GNUNET_DNSPARSER_Record
 {
+
+  /**
+   * Name of the record that the query is for (0-terminated).
+   */
   char *name;
-  unsigned char namelen;
-  unsigned short type;
-  unsigned short class;
-  unsigned int ttl;
-  unsigned short data_len;
-  unsigned char *data;
+
+  /**
+   * Payload of the record (which one of these is valid depends on the 'type').
+   */
+  union 
+  {
+
+    /**
+     * For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
+     */
+    char *hostname;
+    
+    /**
+     * SOA data for SOA records.
+     */
+    struct GNUNET_DNSPARSER_SoaRecord *soa;
+    
+    /**
+     * MX data for MX records.
+     */
+    struct GNUNET_DNSPARSER_MxRecord *mx;
+
+    /**
+     * SRV data for SRV records.
+     */
+    struct GNUNET_DNSPARSER_SrvRecord *srv;
+
+    /**
+     * Raw data for all other types.
+     */
+    struct GNUNET_DNSPARSER_RawRecord raw;
+
+  } data;
+
+
+  /**
+   * When does the record expire?
+   */
+  struct GNUNET_TIME_Absolute expiration_time;
+
+  /**
+   * See GNUNET_DNSPARSER_TYPE_*.
+   */
+  uint16_t type;
+
+  /**
+   * See GNUNET_DNSPARSER_CLASS_*.
+   */
+  uint16_t class;
+
 };
 
 
-struct dns_pkt_parsed *
-parse_dns_packet (struct dns_pkt *pkt);
+/**
+ * Easy-to-process, parsed version of a DNS packet.
+ */
+struct GNUNET_DNSPARSER_Packet
+{
+  /**
+   * Array of all queries in the packet, must contain "num_queries" entries.
+   */
+  struct GNUNET_DNSPARSER_Query *queries;
 
-struct dns_pkt *
-unparse_dns_packet (struct dns_pkt_parsed *pkt);
+  /**
+   * Array of all answers in the packet, must contain "num_answers" entries.
+   */
+  struct GNUNET_DNSPARSER_Record *answers;
 
+  /**
+   * Array of all authority records in the packet, must contain "num_authority_records" entries.
+   */
+  struct GNUNET_DNSPARSER_Record *authority_records;
+
+  /**
+   * Array of all additional answers in the packet, must contain "num_additional_records" entries.
+   */
+  struct GNUNET_DNSPARSER_Record *additional_records;
+
+  /**
+   * Number of queries in the packet.
+   */
+  unsigned int num_queries;
+
+  /**
+   * Number of answers in the packet, should be 0 for queries.
+   */
+  unsigned int num_answers;
+
+  /**
+   * Number of authoritative answers in the packet, should be 0 for queries.
+   */
+  unsigned int num_authority_records;
+
+  /**
+   * Number of additional records in the packet, should be 0 for queries.
+   */
+  unsigned int num_additional_records;
+
+  /**
+   * Bitfield of DNS flags.
+   */ 
+  struct GNUNET_DNSPARSER_Flags flags;
+
+  /**
+   * DNS ID (to match replies to requests).
+   */
+  uint16_t id;
+
+};
+
+
+/**
+ * Parse a UDP payload of a DNS packet in to a nice struct for further
+ * processing and manipulation.
+ *
+ * @param udp_payload wire-format of the DNS packet
+ * @param udp_payload_length number of bytes in udp_payload 
+ * @return NULL on error, otherwise the parsed packet
+ */
+struct GNUNET_DNSPARSER_Packet *
+GNUNET_DNSPARSER_parse (const char *udp_payload,
+                       size_t udp_payload_length);
+
+
+/**
+ * Free memory taken by a packet.
+ *
+ * @param p packet to free
+ */
 void
-free_parsed_dns_packet (struct dns_pkt_parsed *ppkt);
+GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p);
+
+
+/**
+ * Given a DNS packet, generate the corresponding UDP payload.
+ *
+ * @param p packet to pack
+ * @param max maximum allowed size for the resulting UDP payload
+ * @param buf set to a buffer with the packed message
+ * @param buf_length set to the length of buf
+ * @return GNUNET_SYSERR if 'p' is invalid
+ *         GNUNET_NO if 'p' was truncated (but there is still a result in 'buf')
+ *         GNUNET_OK if 'p' was packed completely into '*buf'
+ */
+int
+GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p,
+                      uint16_t max,
+                      char **buf,
+                      size_t *buf_length);
+
 
 #endif