gnunet-android

GNUnet for Android
Log | Files | Refs | README

gnunet_dnsparser_lib.h (28369B)


      1 /*
      2       This file is part of GNUnet
      3       Copyright (C) 2010-2014 GNUnet e.V.
      4 
      5       GNUnet is free software: you can redistribute it and/or modify it
      6       under the terms of the GNU Affero General Public License as published
      7       by the Free Software Foundation, either version 3 of the License,
      8       or (at your 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       Affero General Public License for more details.
     14 
     15       You should have received a copy of the GNU Affero General Public License
     16       along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18      SPDX-License-Identifier: AGPL3.0-or-later
     19  */
     20 
     21 #if !defined (__GNUNET_UTIL_LIB_H_INSIDE__)
     22 #error "Only <gnunet_util_lib.h> can be included directly."
     23 #endif
     24 
     25 
     26 /**
     27  * @addtogroup libgnunetutil
     28  * @{
     29  *
     30  * @author Philipp Toelke
     31  * @author Christian Grothoff
     32  *
     33  * @file
     34  * API for helper library to parse DNS packets.
     35  *
     36  * @defgroup dns-parser  DNS parser library
     37  * Helper library to parse DNS packets.
     38  * @{
     39  */
     40 #ifndef GNUNET_DNSPARSER_LIB_H
     41 #define GNUNET_DNSPARSER_LIB_H
     42 
     43 /**
     44  * Maximum length of a label in DNS.
     45  */
     46 #define GNUNET_DNSPARSER_MAX_LABEL_LENGTH 63
     47 
     48 /**
     49  * Maximum length of a name in DNS.
     50  */
     51 #define GNUNET_DNSPARSER_MAX_NAME_LENGTH 253
     52 
     53 
     54 /**
     55  * A few common DNS types.
     56  */
     57 #define GNUNET_DNSPARSER_TYPE_ANY 0
     58 #define GNUNET_DNSPARSER_TYPE_A 1
     59 #define GNUNET_DNSPARSER_TYPE_NS 2
     60 #define GNUNET_DNSPARSER_TYPE_CNAME 5
     61 #define GNUNET_DNSPARSER_TYPE_SOA 6
     62 #define GNUNET_DNSPARSER_TYPE_PTR 12
     63 #define GNUNET_DNSPARSER_TYPE_MX 15
     64 #define GNUNET_DNSPARSER_TYPE_TXT 16
     65 #define GNUNET_DNSPARSER_TYPE_RP 17
     66 #define GNUNET_DNSPARSER_TYPE_AFSDB 18
     67 #define GNUNET_DNSPARSER_TYPE_SIG 24
     68 #define GNUNET_DNSPARSER_TYPE_KEY 25
     69 #define GNUNET_DNSPARSER_TYPE_AAAA 28
     70 #define GNUNET_DNSPARSER_TYPE_LOC 29
     71 #define GNUNET_DNSPARSER_TYPE_SRV 33
     72 #define GNUNET_DNSPARSER_TYPE_NAPTR 35
     73 #define GNUNET_DNSPARSER_TYPE_KX 36
     74 #define GNUNET_DNSPARSER_TYPE_CERT 37
     75 #define GNUNET_DNSPARSER_TYPE_DNAME 39
     76 #define GNUNET_DNSPARSER_TYPE_APL 42
     77 #define GNUNET_DNSPARSER_TYPE_DS 43
     78 #define GNUNET_DNSPARSER_TYPE_SSHFP 44
     79 #define GNUNET_DNSPARSER_TYPE_IPSECKEY 45
     80 #define GNUNET_DNSPARSER_TYPE_RRSIG 46
     81 #define GNUNET_DNSPARSER_TYPE_NSEC 47
     82 #define GNUNET_DNSPARSER_TYPE_DNSKEY 48
     83 #define GNUNET_DNSPARSER_TYPE_DHCID 49
     84 #define GNUNET_DNSPARSER_TYPE_NSEC3 50
     85 #define GNUNET_DNSPARSER_TYPE_NSEC3PARAM 51
     86 #define GNUNET_DNSPARSER_TYPE_TLSA 52
     87 #define GNUNET_DNSPARSER_TYPE_SMIMEA 53
     88 #define GNUNET_DNSPARSER_TYPE_HIP 55
     89 #define GNUNET_DNSPARSER_TYPE_CDS 59
     90 #define GNUNET_DNSPARSER_TYPE_CDNSKEY 60
     91 #define GNUNET_DNSPARSER_TYPE_OPENPGPKEY 61
     92 #define GNUNET_DNSPARSER_TYPE_TKEY 249
     93 #define GNUNET_DNSPARSER_TYPE_TSIG 250
     94 #define GNUNET_DNSPARSER_TYPE_ALL 255
     95 #define GNUNET_DNSPARSER_TYPE_URI 256
     96 #define GNUNET_DNSPARSER_TYPE_CAA 257
     97 #define GNUNET_DNSPARSER_TYPE_TA 32768
     98 
     99 /**
    100  * A DNS query.
    101  */
    102 struct GNUNET_DNSPARSER_Query
    103 {
    104   /**
    105    * Name of the record that the query is for (0-terminated).
    106    * In UTF-8 format.  The library will convert from and to DNS-IDNA
    107    * as necessary.  Use #GNUNET_DNSPARSER_check_label() to test if an
    108    * individual label is well-formed.  If a given name is not well-formed,
    109    * creating the DNS packet will fail.
    110    */
    111   char *name;
    112 
    113   /**
    114    * See GNUNET_DNSPARSER_TYPE_*.
    115    */
    116   uint16_t type;
    117 
    118   /**
    119    * See GNUNET_TUN_DNS_CLASS_*.
    120    */
    121   uint16_t dns_traffic_class;
    122 };
    123 
    124 
    125 /**
    126  * Information from MX records (RFC 1035).
    127  */
    128 struct GNUNET_DNSPARSER_MxRecord
    129 {
    130   /**
    131    * Preference for this entry (lower value is higher preference).
    132    */
    133   uint16_t preference;
    134 
    135   /**
    136    * Name of the mail server.
    137    * In UTF-8 format.  The library will convert from and to DNS-IDNA
    138    * as necessary.  Use #GNUNET_DNSPARSER_check_label() to test if an
    139    * individual label is well-formed.  If a given name is not well-formed,
    140    * creating the DNS packet will fail.
    141    */
    142   char *mxhost;
    143 };
    144 
    145 
    146 /**
    147  * Information from SRV records (RFC 2782).
    148  */
    149 struct GNUNET_DNSPARSER_SrvRecord
    150 {
    151   /**
    152    * Hostname offering the service.
    153    * In UTF-8 format.  The library will convert from and to DNS-IDNA
    154    * as necessary.  Use #GNUNET_DNSPARSER_check_label() to test if an
    155    * individual label is well-formed.  If a given name is not well-formed,
    156    * creating the DNS packet will fail.
    157    */
    158   char *target;
    159 
    160   /**
    161    * Preference for this entry (lower value is higher preference).  Clients
    162    * will contact hosts from the lowest-priority group first and fall back
    163    * to higher priorities if the low-priority entries are unavailable.
    164    */
    165   uint16_t priority;
    166 
    167   /**
    168    * Relative weight for records with the same priority.  Clients will use
    169    * the hosts of the same (lowest) priority with a probability proportional
    170    * to the weight given.
    171    */
    172   uint16_t weight;
    173 
    174   /**
    175    * TCP or UDP port of the service.
    176    */
    177   uint16_t port;
    178 };
    179 
    180 
    181 /**
    182  * Information from URI records (RFC 7553).
    183  */
    184 struct GNUNET_DNSPARSER_UriRecord
    185 {
    186   /**
    187    * URI of the target,
    188    * where the URI is as specified in RFC 3986.
    189    */
    190   char *target;
    191 
    192   /**
    193    * Preference for this entry (lower value is higher preference).  Clients
    194    * will contact hosts from the lowest-priority group first and fall back
    195    * to higher priorities if the low-priority entries are unavailable.
    196    */
    197   uint16_t priority;
    198 
    199   /**
    200    * Relative weight for records with the same priority.  Clients will use
    201    * the hosts of the same (lowest) priority with a probability proportional
    202    * to the weight given.
    203    */
    204   uint16_t weight;
    205 };
    206 
    207 
    208 /**
    209  * DNS CERT types as defined in RFC 4398.
    210  */
    211 enum GNUNET_DNSPARSER_CertType
    212 {
    213   /**
    214    *  Reserved value
    215    */
    216   GNUNET_DNSPARSER_CERTTYPE_RESERVED = 0,
    217 
    218   /**
    219    * An x509 PKIX certificate
    220    */
    221   GNUNET_DNSPARSER_CERTTYPE_PKIX = 1,
    222 
    223   /**
    224    * A SKPI certificate
    225    */
    226   GNUNET_DNSPARSER_CERTTYPE_SKPI = 2,
    227 
    228   /**
    229    * A PGP certificate
    230    */
    231   GNUNET_DNSPARSER_CERTTYPE_PGP = 3,
    232 
    233   /**
    234    * An x509 PKIX cert URL
    235    */
    236   GNUNET_DNSPARSER_CERTTYPE_IPKIX = 4,
    237 
    238   /**
    239    * A SKPI cert URL
    240    */
    241   GNUNET_DNSPARSER_CERTTYPE_ISKPI = 5,
    242 
    243   /**
    244    * A PGP cert fingerprint and URL
    245    */
    246   GNUNET_DNSPARSER_CERTTYPE_IPGP = 6,
    247 
    248   /**
    249    * An attribute Certificate
    250    */
    251   GNUNET_DNSPARSER_CERTTYPE_ACPKIX = 7,
    252 
    253   /**
    254    * An attribute cert URL
    255    */
    256   GNUNET_DNSPARSER_CERTTYPE_IACKPIX = 8
    257 };
    258 
    259 
    260 /**
    261  * DNSCERT algorithms as defined in http://www.iana.org/assignments/
    262  *  dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml, under dns-sec-alg-numbers-1
    263  */
    264 enum GNUNET_DNSPARSER_CertAlgorithm
    265 {
    266   /**
    267    * No defined
    268    */
    269   GNUNET_DNSPARSER_CERTALGO_UNDEFINED = 0,
    270 
    271   /**
    272    * RSA/MD5
    273    */
    274   GNUNET_DNSPARSER_CERTALGO_RSAMD5 = 1,
    275 
    276   /**
    277    * Diffie-Hellman
    278    */
    279   GNUNET_DNSPARSER_CERTALGO_DH = 2,
    280 
    281   /**
    282    * DSA/SHA1
    283    */
    284   GNUNET_DNSPARSER_CERTALGO_DSASHA = 3,
    285 
    286   /**
    287    * Reserved
    288    */
    289   GNUNET_DNSPARSER_CERTALGO_RSRVD4 = 4,
    290 
    291   /**
    292    * RSA/SHA1
    293    */
    294   GNUNET_DNSPARSER_CERTALGO_RSASHA = 5,
    295 
    296   /**
    297    * DSA/NSEC3/SHA
    298    */
    299   GNUNET_DNSPARSER_CERTALGO_DSANSEC3 = 6,
    300 
    301   /**
    302    * RSA/NSEC3/SHA
    303    */
    304   GNUNET_DNSPARSER_CERTALGO_RSANSEC3 = 7,
    305 
    306   /**
    307    * RSA/SHA256
    308    */
    309   GNUNET_DNSPARSER_CERTALGO_RSASHA256 = 8,
    310 
    311   /**
    312    * Reserved
    313    */
    314   GNUNET_DNSPARSER_CERTALGO_RSRVD9 = 9,
    315 
    316   /**
    317    * RSA/SHA512
    318    */
    319   GNUNET_DNSPARSER_CERTALGO_RSASHA512 = 10,
    320 
    321   /**
    322    * GHOST R 34.10-2001
    323    */
    324   GNUNET_DNSPARSER_CERTALGO_GOST_R34 = 12,
    325 
    326   /**
    327    * ECDSA Curve P-256/SHA256
    328    */
    329   GNUNET_DNSPARSER_CERTALGO_ECDSA_P256SHA256 = 13,
    330 
    331   /**
    332    * ECDSA Curve P-384/SHA384
    333    */
    334   GNUNET_DNSPARSER_CERTALGO_ECDSA_P384SHA384 = 14
    335 };
    336 
    337 
    338 /**
    339  * Information from CERT records (RFC 4034).
    340  */
    341 struct GNUNET_DNSPARSER_CertRecord
    342 {
    343   /**
    344    * Certificate type
    345    */
    346   enum GNUNET_DNSPARSER_CertType cert_type;
    347 
    348   /**
    349    * Certificate KeyTag
    350    */
    351   uint16_t cert_tag;
    352 
    353   /**
    354    * Algorithm
    355    */
    356   enum GNUNET_DNSPARSER_CertAlgorithm algorithm;
    357 
    358   /**
    359    * Number of bytes in @e certificate_data
    360    */
    361   size_t certificate_size;
    362 
    363   /**
    364    * Data of the certificate.
    365    */
    366   char *certificate_data;
    367 };
    368 
    369 
    370 /**
    371  * Information from SOA records (RFC 1035).
    372  */
    373 struct GNUNET_DNSPARSER_SoaRecord
    374 {
    375   /**
    376    * The domainname of the name server that was the
    377    * original or primary source of data for this zone.
    378    * In UTF-8 format.  The library will convert from and to DNS-IDNA
    379    * as necessary.  Use #GNUNET_DNSPARSER_check_label() to test if an
    380    * individual label is well-formed.  If a given name is not well-formed,
    381    * creating the DNS packet will fail.
    382    */
    383   char *mname;
    384 
    385   /**
    386    * A domainname which specifies the mailbox of the
    387    * person responsible for this zone.
    388    * In UTF-8 format.  The library will convert from and to DNS-IDNA
    389    * as necessary.  Use #GNUNET_DNSPARSER_check_label() to test if an
    390    * individual label is well-formed.  If a given name is not well-formed,
    391    * creating the DNS packet will fail.
    392    */
    393   char *rname;
    394 
    395   /**
    396    * The version number of the original copy of the zone.
    397    */
    398   uint32_t serial;
    399 
    400   /**
    401    * Time interval before the zone should be refreshed.
    402    */
    403   uint32_t refresh;
    404 
    405   /**
    406    * Time interval that should elapse before a failed refresh should
    407    * be retried.
    408    */
    409   uint32_t retry;
    410 
    411   /**
    412    * Time value that specifies the upper limit on the time interval
    413    * that can elapse before the zone is no longer authoritative.
    414    */
    415   uint32_t expire;
    416 
    417   /**
    418    * The bit minimum TTL field that should be exported with any RR
    419    * from this zone.
    420    */
    421   uint32_t minimum_ttl;
    422 };
    423 
    424 
    425 /**
    426  * Information from CAA records (RFC 6844).
    427  * The tag is followed by the tag_len.
    428  * The value is followed by the tag for (d - tag_len - 2) bytes
    429  */
    430 struct GNUNET_DNSPARSER_CaaRecord
    431 {
    432   /**
    433    * The flags of the CAA record.
    434    */
    435   uint8_t flags;
    436 
    437   /**
    438    * The length of the tag.
    439    */
    440   uint8_t tag_len;
    441 };
    442 
    443 
    444 /**
    445  * Binary record information (unparsed).
    446  */
    447 struct GNUNET_DNSPARSER_RawRecord
    448 {
    449   /**
    450    * Binary record data.
    451    */
    452   void *data;
    453 
    454   /**
    455    * Number of bytes in data.
    456    */
    457   size_t data_len;
    458 };
    459 
    460 
    461 /**
    462  * A DNS response record.
    463  */
    464 struct GNUNET_DNSPARSER_Record
    465 {
    466   /**
    467    * Name of the record that the query is for (0-terminated).
    468    * In UTF-8 format.  The library will convert from and to DNS-IDNA
    469    * as necessary.  Use #GNUNET_DNSPARSER_check_label() to test if an
    470    * individual label is well-formed.  If a given name is not well-formed,
    471    * creating the DNS packet will fail.
    472    */
    473   char *name;
    474 
    475   /**
    476    * Payload of the record (which one of these is valid depends on the 'type').
    477    */
    478   union
    479   {
    480     /**
    481      * For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
    482      * In UTF-8 format.  The library will convert from and to DNS-IDNA
    483      * as necessary.  Use #GNUNET_DNSPARSER_check_label() to test if an
    484      * individual label is well-formed.  If a given name is not well-formed,
    485      * creating the DNS packet will fail.
    486      */
    487     char *hostname;
    488 
    489     /**
    490      * SOA data for SOA records.
    491      */
    492     struct GNUNET_DNSPARSER_SoaRecord *soa;
    493 
    494     /**
    495      * CERT data for CERT records.
    496      */
    497     struct GNUNET_DNSPARSER_CertRecord *cert;
    498 
    499     /**
    500      * MX data for MX records.
    501      */
    502     struct GNUNET_DNSPARSER_MxRecord *mx;
    503 
    504     /**
    505      * SRV data for SRV records.
    506      */
    507     struct GNUNET_DNSPARSER_SrvRecord *srv;
    508 
    509     /**
    510      * URI data for URI records.
    511      */
    512     struct GNUNET_DNSPARSER_UriRecord *uri;
    513 
    514     /**
    515      * Raw data for all other types.
    516      */
    517     struct GNUNET_DNSPARSER_RawRecord raw;
    518   } data;
    519 
    520 
    521   /**
    522    * When does the record expire?
    523    */
    524   struct GNUNET_TIME_Absolute expiration_time;
    525 
    526   /**
    527    * See GNUNET_DNSPARSER_TYPE_*.
    528    */
    529   uint16_t type;
    530 
    531   /**
    532    * See GNUNET_TUN_DNS_CLASS_*.
    533    */
    534   uint16_t dns_traffic_class;
    535 };
    536 
    537 
    538 /**
    539  * Easy-to-process, parsed version of a DNS packet.
    540  */
    541 struct GNUNET_DNSPARSER_Packet
    542 {
    543   /**
    544    * Array of all queries in the packet, must contain "num_queries" entries.
    545    */
    546   struct GNUNET_DNSPARSER_Query *queries;
    547 
    548   /**
    549    * Array of all answers in the packet, must contain "num_answers" entries.
    550    */
    551   struct GNUNET_DNSPARSER_Record *answers;
    552 
    553   /**
    554    * Array of all authority records in the packet, must contain "num_authority_records" entries.
    555    */
    556   struct GNUNET_DNSPARSER_Record *authority_records;
    557 
    558   /**
    559    * Array of all additional answers in the packet, must contain "num_additional_records" entries.
    560    */
    561   struct GNUNET_DNSPARSER_Record *additional_records;
    562 
    563   /**
    564    * Number of queries in the packet.
    565    */
    566   unsigned int num_queries;
    567 
    568   /**
    569    * Number of answers in the packet, should be 0 for queries.
    570    */
    571   unsigned int num_answers;
    572 
    573   /**
    574    * Number of authoritative answers in the packet, should be 0 for queries.
    575    */
    576   unsigned int num_authority_records;
    577 
    578   /**
    579    * Number of additional records in the packet, should be 0 for queries.
    580    */
    581   unsigned int num_additional_records;
    582 
    583   /**
    584    * Bitfield of DNS flags.
    585    */
    586   struct GNUNET_TUN_DnsFlags flags;
    587 
    588   /**
    589    * DNS ID (to match replies to requests).
    590    */
    591   uint16_t id;
    592 };
    593 
    594 
    595 /**
    596  * Check if a label in UTF-8 format can be coded into valid IDNA.
    597  * This can fail if the ASCII-conversion becomes longer than 63 characters.
    598  *
    599  * @param label label to check (UTF-8 string)
    600  * @return #GNUNET_OK if the label can be converted to IDNA,
    601  *         #GNUNET_SYSERR if the label is not valid for DNS names
    602  */
    603 int
    604 GNUNET_DNSPARSER_check_label (const char *label);
    605 
    606 
    607 /**
    608  * Check if a hostname in UTF-8 format can be coded into valid IDNA.
    609  * This can fail if a label becomes longer than 63 characters or if
    610  * the entire name exceeds 253 characters.
    611  *
    612  * @param name name to check (UTF-8 string)
    613  * @return #GNUNET_OK if the label can be converted to IDNA,
    614  *         #GNUNET_SYSERR if the label is not valid for DNS names
    615  */
    616 int
    617 GNUNET_DNSPARSER_check_name (const char *name);
    618 
    619 
    620 /**
    621  * Parse a UDP payload of a DNS packet in to a nice struct for further
    622  * processing and manipulation.
    623  *
    624  * @param udp_payload wire-format of the DNS packet
    625  * @param udp_payload_length number of bytes in @a udp_payload
    626  * @return NULL on error, otherwise the parsed packet
    627  */
    628 struct GNUNET_DNSPARSER_Packet *
    629 GNUNET_DNSPARSER_parse (const char *udp_payload,
    630                         size_t udp_payload_length);
    631 
    632 
    633 /**
    634  * Free memory taken by a packet.
    635  *
    636  * @param p packet to free
    637  */
    638 void
    639 GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p);
    640 
    641 
    642 /**
    643  * Given a DNS packet @a p, generate the corresponding UDP payload.
    644  * Note that we do not attempt to pack the strings with pointers
    645  * as this would complicate the code and this is about being
    646  * simple and secure, not fast, fancy and broken like bind.
    647  *
    648  * @param p packet to pack
    649  * @param max maximum allowed size for the resulting UDP payload
    650  * @param buf set to a buffer with the packed message
    651  * @param buf_length set to the length of @a buf
    652  * @return #GNUNET_SYSERR if @a p is invalid
    653  *         #GNUNET_NO if @a p was truncated (but there is still a result in @a buf)
    654  *         #GNUNET_OK if @a p was packed completely into @a buf
    655  */
    656 int
    657 GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p,
    658                        uint16_t max,
    659                        char **buf,
    660                        size_t *buf_length);
    661 
    662 /* ***************** low-level packing API ******************** */
    663 
    664 /**
    665  * Add a DNS name to the UDP packet at the given location, converting
    666  * the name to IDNA notation as necessary.
    667  *
    668  * @param dst where to write the name (UDP packet)
    669  * @param dst_len number of bytes in @a dst
    670  * @param off pointer to offset where to write the name (increment by bytes used)
    671  *            must not be changed if there is an error
    672  * @param name name to write
    673  * @return #GNUNET_SYSERR if @a name is invalid
    674  *         #GNUNET_NO if @a name did not fit
    675  *         #GNUNET_OK if @a name was added to @a dst
    676  */
    677 int
    678 GNUNET_DNSPARSER_builder_add_name (char *dst,
    679                                    size_t dst_len,
    680                                    size_t *off,
    681                                    const char *name);
    682 
    683 
    684 /**
    685  * Add a DNS query to the UDP packet at the given location.
    686  *
    687  * @param dst where to write the query
    688  * @param dst_len number of bytes in @a dst
    689  * @param off pointer to offset where to write the query (increment by bytes used)
    690  *            must not be changed if there is an error
    691  * @param query query to write
    692  * @return #GNUNET_SYSERR if @a query is invalid
    693  *         #GNUNET_NO if @a query did not fit
    694  *         #GNUNET_OK if @a query was added to @a dst
    695  */
    696 int
    697 GNUNET_DNSPARSER_builder_add_query (char *dst,
    698                                     size_t dst_len,
    699                                     size_t *off,
    700                                     const struct GNUNET_DNSPARSER_Query *query);
    701 
    702 
    703 /**
    704  * Add an MX record to the UDP packet at the given location.
    705  *
    706  * @param dst where to write the mx record
    707  * @param dst_len number of bytes in @a dst
    708  * @param off pointer to offset where to write the mx information (increment by bytes used);
    709  *            can also change if there was an error
    710  * @param mx mx information to write
    711  * @return #GNUNET_SYSERR if @a mx is invalid
    712  *         #GNUNET_NO if @a mx did not fit
    713  *         #GNUNET_OK if @a mx was added to @a dst
    714  */
    715 int
    716 GNUNET_DNSPARSER_builder_add_mx (char *dst,
    717                                  size_t dst_len,
    718                                  size_t *off,
    719                                  const struct GNUNET_DNSPARSER_MxRecord *mx);
    720 
    721 
    722 /**
    723  * Add an SOA record to the UDP packet at the given location.
    724  *
    725  * @param dst where to write the SOA record
    726  * @param dst_len number of bytes in @a dst
    727  * @param off pointer to offset where to write the SOA information (increment by bytes used)
    728  *            can also change if there was an error
    729  * @param soa SOA information to write
    730  * @return #GNUNET_SYSERR if @a soa is invalid
    731  *         #GNUNET_NO if @a soa did not fit
    732  *         #GNUNET_OK if @a soa was added to @a dst
    733  */
    734 int
    735 GNUNET_DNSPARSER_builder_add_soa (char *dst,
    736                                   size_t dst_len,
    737                                   size_t *off,
    738                                   const struct GNUNET_DNSPARSER_SoaRecord *soa);
    739 
    740 
    741 /**
    742  * Add CERT record to the UDP packet at the given location.
    743  *
    744  * @param dst where to write the CERT record
    745  * @param dst_len number of bytes in @a dst
    746  * @param off pointer to offset where to write the CERT information (increment by bytes used)
    747  *            can also change if there was an error
    748  * @param cert CERT information to write
    749  * @return #GNUNET_SYSERR if @a soa is invalid
    750  *         #GNUNET_NO if @a soa did not fit
    751  *         #GNUNET_OK if @a soa was added to @a dst
    752  */
    753 int
    754 GNUNET_DNSPARSER_builder_add_cert (char *dst,
    755                                    size_t dst_len,
    756                                    size_t *off,
    757                                    const struct
    758                                    GNUNET_DNSPARSER_CertRecord *cert);
    759 
    760 
    761 /**
    762  * Add an SRV record to the UDP packet at the given location.
    763  *
    764  * @param dst where to write the SRV record
    765  * @param dst_len number of bytes in @a dst
    766  * @param off pointer to offset where to write the SRV information (increment by bytes used)
    767  *            can also change if there was an error
    768  * @param srv SRV information to write
    769  * @return #GNUNET_SYSERR if @a srv is invalid
    770  *         #GNUNET_NO if @a srv did not fit
    771  *         #GNUNET_OK if @a srv was added to @a dst
    772  */
    773 int
    774 GNUNET_DNSPARSER_builder_add_srv (char *dst,
    775                                   size_t dst_len,
    776                                   size_t *off,
    777                                   const struct GNUNET_DNSPARSER_SrvRecord *srv);
    778 
    779 
    780 /**
    781  * Add an URI record to the UDP packet at the given location.
    782  *
    783  * @param dst where to write the URI record
    784  * @param dst_len number of bytes in @a dst
    785  * @param off pointer to offset where to write the URI information (increment by bytes used)
    786  *            can also change if there was an error
    787  * @param uri URI information to write
    788  * @return #GNUNET_SYSERR if @a uri is invalid
    789  *         #GNUNET_NO if @a uri did not fit
    790  *         #GNUNET_OK if @a uri was added to @a dst
    791  */
    792 int
    793 GNUNET_DNSPARSER_builder_add_uri (char *dst,
    794                                   size_t dst_len,
    795                                   size_t *off,
    796                                   const struct GNUNET_DNSPARSER_UriRecord *uri);
    797 
    798 /* ***************** low-level parsing API ******************** */
    799 
    800 /**
    801  * Parse a DNS record entry.
    802  *
    803  * @param udp_payload entire UDP payload
    804  * @param udp_payload_length length of @a udp_payload
    805  * @param off pointer to the offset of the record to parse in the udp_payload (to be
    806  *                    incremented by the size of the record)
    807  * @param r where to write the record information
    808  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the record is malformed
    809  */
    810 int
    811 GNUNET_DNSPARSER_parse_record (const char *udp_payload,
    812                                size_t udp_payload_length,
    813                                size_t *off,
    814                                struct GNUNET_DNSPARSER_Record *r);
    815 
    816 
    817 /**
    818  * Parse name inside of a DNS query or record.
    819  *
    820  * @param udp_payload entire UDP payload
    821  * @param udp_payload_length length of @a udp_payload
    822  * @param off pointer to the offset of the name to parse in the udp_payload (to be
    823  *                    incremented by the size of the name)
    824  * @return name as 0-terminated C string on success, NULL if the payload is malformed
    825  */
    826 char *
    827 GNUNET_DNSPARSER_parse_name (const char *udp_payload,
    828                              size_t udp_payload_length,
    829                              size_t *off);
    830 
    831 
    832 /**
    833  * Parse a DNS query entry.
    834  *
    835  * @param udp_payload entire UDP payload
    836  * @param udp_payload_length length of @a udp_payload
    837  * @param off pointer to the offset of the query to parse in the udp_payload (to be
    838  *                    incremented by the size of the query)
    839  * @param q where to write the query information
    840  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the query is malformed
    841  */
    842 int
    843 GNUNET_DNSPARSER_parse_query (const char *udp_payload,
    844                               size_t udp_payload_length,
    845                               size_t *off,
    846                               struct GNUNET_DNSPARSER_Query *q);
    847 
    848 
    849 /**
    850  * Parse a DNS SOA record.
    851  *
    852  * @param udp_payload reference to UDP packet
    853  * @param udp_payload_length length of @a udp_payload
    854  * @param off pointer to the offset of the query to parse in the SOA record (to be
    855  *                    incremented by the size of the record), unchanged on error
    856  * @return the parsed SOA record, NULL on error
    857  */
    858 struct GNUNET_DNSPARSER_SoaRecord *
    859 GNUNET_DNSPARSER_parse_soa (const char *udp_payload,
    860                             size_t udp_payload_length,
    861                             size_t *off);
    862 
    863 
    864 /**
    865  * Parse a DNS CERT record.
    866  *
    867  * @param udp_payload reference to UDP packet
    868  * @param udp_payload_length length of @a udp_payload
    869  * @param off pointer to the offset of the query to parse in the CERT record (to be
    870  *                    incremented by the size of the record), unchanged on error
    871  * @return the parsed CERT record, NULL on error
    872  */
    873 struct GNUNET_DNSPARSER_CertRecord *
    874 GNUNET_DNSPARSER_parse_cert (const char *udp_payload,
    875                              size_t udp_payload_length,
    876                              size_t *off);
    877 
    878 
    879 /**
    880  * Parse a DNS MX record.
    881  *
    882  * @param udp_payload reference to UDP packet
    883  * @param udp_payload_length length of @a udp_payload
    884  * @param off pointer to the offset of the query to parse in the MX record (to be
    885  *                    incremented by the size of the record), unchanged on error
    886  * @return the parsed MX record, NULL on error
    887  */
    888 struct GNUNET_DNSPARSER_MxRecord *
    889 GNUNET_DNSPARSER_parse_mx (const char *udp_payload,
    890                            size_t udp_payload_length,
    891                            size_t *off);
    892 
    893 
    894 /**
    895  * Parse a DNS SRV record.
    896  *
    897  * @param udp_payload reference to UDP packet
    898  * @param udp_payload_length length of @a udp_payload
    899  * @param off pointer to the offset of the query to parse in the SRV record (to be
    900  *                    incremented by the size of the record), unchanged on error
    901  * @return the parsed SRV record, NULL on error
    902  */
    903 struct GNUNET_DNSPARSER_SrvRecord *
    904 GNUNET_DNSPARSER_parse_srv (const char *udp_payload,
    905                             size_t udp_payload_length,
    906                             size_t *off);
    907 
    908 
    909 /**
    910  * Parse a DNS URI record.
    911  *
    912  * @param udp_payload reference to UDP packet
    913  * @param udp_payload_length length of @a udp_payload
    914  * @param off pointer to the offset of the query to parse in the URI record (to be
    915  *                    incremented by the size of the record), unchanged on error
    916  * @return the parsed URI record, NULL on error
    917  */
    918 struct GNUNET_DNSPARSER_UriRecord *
    919 GNUNET_DNSPARSER_parse_uri (const char *udp_payload,
    920                             size_t udp_payload_length,
    921                             size_t *off);
    922 
    923 /* ***************** low-level duplication API ******************** */
    924 
    925 /**
    926  * Duplicate (deep-copy) the given DNS record
    927  *
    928  * @param r the record
    929  * @return the newly allocated record
    930  */
    931 struct GNUNET_DNSPARSER_Record *
    932 GNUNET_DNSPARSER_duplicate_record (const struct GNUNET_DNSPARSER_Record *r);
    933 
    934 
    935 /**
    936  * Duplicate (deep-copy) the given DNS record
    937  *
    938  * @param r the record
    939  * @return the newly allocated record
    940  */
    941 struct GNUNET_DNSPARSER_SoaRecord *
    942 GNUNET_DNSPARSER_duplicate_soa_record (const struct
    943                                        GNUNET_DNSPARSER_SoaRecord *r);
    944 
    945 
    946 /**
    947  * Duplicate (deep-copy) the given DNS record
    948  *
    949  * @param r the record
    950  * @return the newly allocated record
    951  */
    952 struct GNUNET_DNSPARSER_CertRecord *
    953 GNUNET_DNSPARSER_duplicate_cert_record (const struct
    954                                         GNUNET_DNSPARSER_CertRecord *r);
    955 
    956 
    957 /**
    958  * Duplicate (deep-copy) the given DNS record
    959  *
    960  * @param r the record
    961  * @return the newly allocated record
    962  */
    963 struct GNUNET_DNSPARSER_MxRecord *
    964 GNUNET_DNSPARSER_duplicate_mx_record (const struct
    965                                       GNUNET_DNSPARSER_MxRecord *r);
    966 
    967 
    968 /**
    969  * Duplicate (deep-copy) the given DNS record
    970  *
    971  * @param r the record
    972  * @return the newly allocated record
    973  */
    974 struct GNUNET_DNSPARSER_SrvRecord *
    975 GNUNET_DNSPARSER_duplicate_srv_record (const struct
    976                                        GNUNET_DNSPARSER_SrvRecord *r);
    977 
    978 
    979 /**
    980  * Duplicate (deep-copy) the given DNS record
    981  *
    982  * @param r the record
    983  * @return the newly allocated record
    984  */
    985 struct GNUNET_DNSPARSER_UriRecord *
    986 GNUNET_DNSPARSER_duplicate_uri_record (const struct
    987                                        GNUNET_DNSPARSER_UriRecord *r);
    988 
    989 /* ***************** low-level deallocation API ******************** */
    990 
    991 /**
    992  * Free the given DNS record.
    993  *
    994  * @param r record to free
    995  */
    996 void
    997 GNUNET_DNSPARSER_free_record (struct GNUNET_DNSPARSER_Record *r);
    998 
    999 
   1000 /**
   1001  * Free MX information record.
   1002  *
   1003  * @param mx record to free
   1004  */
   1005 void
   1006 GNUNET_DNSPARSER_free_mx (struct GNUNET_DNSPARSER_MxRecord *mx);
   1007 
   1008 
   1009 /**
   1010  * Free SRV information record.
   1011  *
   1012  * @param srv record to free
   1013  */
   1014 void
   1015 GNUNET_DNSPARSER_free_srv (struct GNUNET_DNSPARSER_SrvRecord *srv);
   1016 
   1017 
   1018 /**
   1019  * Free URI information record.
   1020  *
   1021  * @param uri record to free
   1022  */
   1023 void
   1024 GNUNET_DNSPARSER_free_uri (struct GNUNET_DNSPARSER_UriRecord *uri);
   1025 
   1026 
   1027 /**
   1028  * Free SOA information record.
   1029  *
   1030  * @param soa record to free
   1031  */
   1032 void
   1033 GNUNET_DNSPARSER_free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa);
   1034 
   1035 
   1036 /**
   1037  * Free CERT information record.
   1038  *
   1039  * @param cert record to free
   1040  */
   1041 void
   1042 GNUNET_DNSPARSER_free_cert (struct GNUNET_DNSPARSER_CertRecord *cert);
   1043 
   1044 
   1045 /**
   1046  * Convert a block of binary data to HEX.
   1047  *
   1048  * @param data binary data to convert
   1049  * @param data_size number of bytes in @a data
   1050  * @return HEX string (lower case)
   1051  */
   1052 char *
   1053 GNUNET_DNSPARSER_bin_to_hex (const void *data,
   1054                              size_t data_size);
   1055 
   1056 
   1057 /**
   1058  * Convert a HEX string to block of binary data.
   1059  *
   1060  * @param hex HEX string to convert (may contain mixed case)
   1061  * @param data where to write result, must be
   1062  *             at least `strlen(hex)/2` bytes long
   1063  * @return number of bytes written to data
   1064  */
   1065 size_t
   1066 GNUNET_DNSPARSER_hex_to_bin (const char *hex,
   1067                              void *data);
   1068 
   1069 
   1070 #endif
   1071 
   1072 /** @} */  /* end of group */
   1073 
   1074 /** @} */ /* end of group addition */