+/**
+ * Parse a DNS SOA record.
+ *
+ * @param udp_payload reference to UDP packet
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the query to parse in the SOA record (to be
+ * incremented by the size of the record), unchanged on error
+ * @return the parsed SOA record, NULL on error
+ */
+struct GNUNET_DNSPARSER_SoaRecord *
+GNUNET_DNSPARSER_parse_soa (const char *udp_payload,
+ size_t udp_payload_length,
+ size_t *off)
+{
+ struct GNUNET_DNSPARSER_SoaRecord *soa;
+ struct GNUNET_TUN_DnsSoaRecord soa_bin;
+ size_t old_off;
+
+ old_off = *off;
+ soa = GNUNET_new (struct GNUNET_DNSPARSER_SoaRecord);
+ soa->mname = GNUNET_DNSPARSER_parse_name (udp_payload,
+ udp_payload_length,
+ off);
+ soa->rname = GNUNET_DNSPARSER_parse_name (udp_payload,
+ udp_payload_length,
+ off);
+ if ( (NULL == soa->mname) ||
+ (NULL == soa->rname) ||
+ (*off + sizeof (struct GNUNET_TUN_DnsSoaRecord) > udp_payload_length) )
+ {
+ GNUNET_break_op (0);
+ GNUNET_DNSPARSER_free_soa (soa);
+ *off = old_off;
+ return NULL;
+ }
+ GNUNET_memcpy (&soa_bin,
+ &udp_payload[*off],
+ sizeof (struct GNUNET_TUN_DnsSoaRecord));
+ soa->serial = ntohl (soa_bin.serial);
+ soa->refresh = ntohl (soa_bin.refresh);
+ soa->retry = ntohl (soa_bin.retry);
+ soa->expire = ntohl (soa_bin.expire);
+ soa->minimum_ttl = ntohl (soa_bin.minimum);
+ (*off) += sizeof (struct GNUNET_TUN_DnsSoaRecord);
+ return soa;
+}
+
+
+/**
+ * Parse a DNS MX record.
+ *
+ * @param udp_payload reference to UDP packet
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the query to parse in the MX record (to be
+ * incremented by the size of the record), unchanged on error
+ * @return the parsed MX record, NULL on error
+ */
+struct GNUNET_DNSPARSER_MxRecord *
+GNUNET_DNSPARSER_parse_mx (const char *udp_payload,
+ size_t udp_payload_length,
+ size_t *off)
+{
+ struct GNUNET_DNSPARSER_MxRecord *mx;
+ uint16_t mxpref;
+ size_t old_off;
+
+ old_off = *off;
+ if (*off + sizeof (uint16_t) > udp_payload_length)
+ {
+ GNUNET_break_op (0);
+ return NULL;
+ }
+ GNUNET_memcpy (&mxpref, &udp_payload[*off], sizeof (uint16_t));
+ (*off) += sizeof (uint16_t);
+ mx = GNUNET_new (struct GNUNET_DNSPARSER_MxRecord);
+ mx->preference = ntohs (mxpref);
+ mx->mxhost = GNUNET_DNSPARSER_parse_name (udp_payload,
+ udp_payload_length,
+ off);
+ if (NULL == mx->mxhost)
+ {
+ GNUNET_break_op (0);
+ GNUNET_DNSPARSER_free_mx (mx);
+ *off = old_off;
+ return NULL;
+ }
+ return mx;
+}
+
+
+/**
+ * Parse a DNS SRV record.
+ *
+ * @param udp_payload reference to UDP packet
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the query to parse in the SRV record (to be
+ * incremented by the size of the record), unchanged on error
+ * @return the parsed SRV record, NULL on error
+ */
+struct GNUNET_DNSPARSER_SrvRecord *
+GNUNET_DNSPARSER_parse_srv (const char *udp_payload,
+ size_t udp_payload_length,
+ size_t *off)
+{
+ struct GNUNET_DNSPARSER_SrvRecord *srv;
+ struct GNUNET_TUN_DnsSrvRecord srv_bin;
+ size_t old_off;
+
+ old_off = *off;
+ if (*off + sizeof (struct GNUNET_TUN_DnsSrvRecord) > udp_payload_length)
+ return NULL;
+ GNUNET_memcpy (&srv_bin,
+ &udp_payload[*off],
+ sizeof (struct GNUNET_TUN_DnsSrvRecord));
+ (*off) += sizeof (struct GNUNET_TUN_DnsSrvRecord);
+ srv = GNUNET_new (struct GNUNET_DNSPARSER_SrvRecord);
+ srv->priority = ntohs (srv_bin.prio);
+ srv->weight = ntohs (srv_bin.weight);
+ srv->port = ntohs (srv_bin.port);
+ srv->target = GNUNET_DNSPARSER_parse_name (udp_payload,
+ udp_payload_length,
+ off);
+ if (NULL == srv->target)
+ {
+ GNUNET_DNSPARSER_free_srv (srv);
+ *off = old_off;
+ return NULL;
+ }
+ return srv;
+}
+
+
+/**
+ * Parse a DNS CERT record.
+ *
+ * @param udp_payload reference to UDP packet
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the query to parse in the CERT record (to be
+ * incremented by the size of the record), unchanged on error
+ * @return the parsed CERT record, NULL on error
+ */
+struct GNUNET_DNSPARSER_CertRecord *
+GNUNET_DNSPARSER_parse_cert (const char *udp_payload,
+ size_t udp_payload_length,
+ size_t *off)
+{
+ struct GNUNET_DNSPARSER_CertRecord *cert;
+ struct GNUNET_TUN_DnsCertRecord dcert;
+
+ if (*off + sizeof (struct GNUNET_TUN_DnsCertRecord) >= udp_payload_length)
+ {
+ GNUNET_break_op (0);
+ return NULL;
+ }
+ GNUNET_memcpy (&dcert, &udp_payload[*off], sizeof (struct GNUNET_TUN_DnsCertRecord));
+ (*off) += sizeof (struct GNUNET_TUN_DnsCertRecord);
+ cert = GNUNET_new (struct GNUNET_DNSPARSER_CertRecord);
+ cert->cert_type = ntohs (dcert.cert_type);
+ cert->cert_tag = ntohs (dcert.cert_tag);
+ cert->algorithm = dcert.algorithm;
+ cert->certificate_size = udp_payload_length - (*off);
+ cert->certificate_data = GNUNET_malloc (cert->certificate_size);
+ GNUNET_memcpy (cert->certificate_data,
+ &udp_payload[*off],
+ cert->certificate_size);
+ (*off) += cert->certificate_size;
+ return cert;
+}
+
+