aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/util/data
diff options
context:
space:
mode:
authoranonimal <anonimal@i2pmail.org>2017-06-28 21:07:24 +0000
committeranonimal <anonimal@i2pmail.org>2018-03-18 15:52:19 +0000
commit84c5a9ba481d7a33cc0fd0ca43867b61d127d907 (patch)
treef05d3d3f107da02005b4a61f0e5074c113a7165c /external/unbound/util/data
parentMerge pull request #3416 (diff)
downloadmonero-84c5a9ba481d7a33cc0fd0ca43867b61d127d907.tar.xz
Unbound: remove unbound from in-tree source
We'll instead use a git submodule to pull from our unbound repo.
Diffstat (limited to 'external/unbound/util/data')
-rw-r--r--external/unbound/util/data/dname.c788
-rw-r--r--external/unbound/util/data/dname.h305
-rw-r--r--external/unbound/util/data/msgencode.c916
-rw-r--r--external/unbound/util/data/msgencode.h131
-rw-r--r--external/unbound/util/data/msgparse.c1093
-rw-r--r--external/unbound/util/data/msgparse.h334
-rw-r--r--external/unbound/util/data/msgreply.c1206
-rw-r--r--external/unbound/util/data/msgreply.h674
-rw-r--r--external/unbound/util/data/packed_rrset.c387
-rw-r--r--external/unbound/util/data/packed_rrset.h445
10 files changed, 0 insertions, 6279 deletions
diff --git a/external/unbound/util/data/dname.c b/external/unbound/util/data/dname.c
deleted file mode 100644
index 517af2843..000000000
--- a/external/unbound/util/data/dname.c
+++ /dev/null
@@ -1,788 +0,0 @@
-/*
- * util/data/dname.h - domain name handling
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains domain name handling functions.
- */
-
-#include "config.h"
-#include <ctype.h>
-#include "util/data/dname.h"
-#include "util/data/msgparse.h"
-#include "util/log.h"
-#include "util/storage/lookup3.h"
-#include "sldns/sbuffer.h"
-
-/* determine length of a dname in buffer, no compression pointers allowed */
-size_t
-query_dname_len(sldns_buffer* query)
-{
- size_t len = 0;
- size_t labellen;
- while(1) {
- if(sldns_buffer_remaining(query) < 1)
- return 0; /* parse error, need label len */
- labellen = sldns_buffer_read_u8(query);
- if(labellen&0xc0)
- return 0; /* no compression allowed in queries */
- len += labellen + 1;
- if(len > LDNS_MAX_DOMAINLEN)
- return 0; /* too long */
- if(labellen == 0)
- return len;
- if(sldns_buffer_remaining(query) < labellen)
- return 0; /* parse error, need content */
- sldns_buffer_skip(query, (ssize_t)labellen);
- }
-}
-
-size_t
-dname_valid(uint8_t* dname, size_t maxlen)
-{
- size_t len = 0;
- size_t labellen;
- labellen = *dname++;
- while(labellen) {
- if(labellen&0xc0)
- return 0; /* no compression ptrs allowed */
- len += labellen + 1;
- if(len >= LDNS_MAX_DOMAINLEN)
- return 0; /* too long */
- if(len > maxlen)
- return 0; /* does not fit in memory allocation */
- dname += labellen;
- labellen = *dname++;
- }
- len += 1;
- if(len > maxlen)
- return 0; /* does not fit in memory allocation */
- return len;
-}
-
-/** compare uncompressed, noncanonical, registers are hints for speed */
-int
-query_dname_compare(register uint8_t* d1, register uint8_t* d2)
-{
- register uint8_t lab1, lab2;
- log_assert(d1 && d2);
- lab1 = *d1++;
- lab2 = *d2++;
- while( lab1 != 0 || lab2 != 0 ) {
- /* compare label length */
- /* if one dname ends, it has labellength 0 */
- if(lab1 != lab2) {
- if(lab1 < lab2)
- return -1;
- return 1;
- }
- log_assert(lab1 == lab2 && lab1 != 0);
- /* compare lowercased labels. */
- while(lab1--) {
- /* compare bytes first for speed */
- if(*d1 != *d2 &&
- tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) {
- if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2))
- return -1;
- return 1;
- }
- d1++;
- d2++;
- }
- /* next pair of labels. */
- lab1 = *d1++;
- lab2 = *d2++;
- }
- return 0;
-}
-
-void
-query_dname_tolower(uint8_t* dname)
-{
- /* the dname is stored uncompressed */
- uint8_t labellen;
- labellen = *dname;
- while(labellen) {
- dname++;
- while(labellen--) {
- *dname = (uint8_t)tolower((unsigned char)*dname);
- dname++;
- }
- labellen = *dname;
- }
-}
-
-void
-pkt_dname_tolower(sldns_buffer* pkt, uint8_t* dname)
-{
- uint8_t lablen;
- int count = 0;
- if(dname >= sldns_buffer_end(pkt))
- return;
- lablen = *dname++;
- while(lablen) {
- if(LABEL_IS_PTR(lablen)) {
- if((size_t)PTR_OFFSET(lablen, *dname)
- >= sldns_buffer_limit(pkt))
- return;
- dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
- lablen = *dname++;
- if(count++ > MAX_COMPRESS_PTRS)
- return;
- continue;
- }
- if(dname+lablen >= sldns_buffer_end(pkt))
- return;
- while(lablen--) {
- *dname = (uint8_t)tolower((unsigned char)*dname);
- dname++;
- }
- if(dname >= sldns_buffer_end(pkt))
- return;
- lablen = *dname++;
- }
-}
-
-
-size_t
-pkt_dname_len(sldns_buffer* pkt)
-{
- size_t len = 0;
- int ptrcount = 0;
- uint8_t labellen;
- size_t endpos = 0;
-
- /* read dname and determine length */
- /* check compression pointers, loops, out of bounds */
- while(1) {
- /* read next label */
- if(sldns_buffer_remaining(pkt) < 1)
- return 0;
- labellen = sldns_buffer_read_u8(pkt);
- if(LABEL_IS_PTR(labellen)) {
- /* compression ptr */
- uint16_t ptr;
- if(sldns_buffer_remaining(pkt) < 1)
- return 0;
- ptr = PTR_OFFSET(labellen, sldns_buffer_read_u8(pkt));
- if(ptrcount++ > MAX_COMPRESS_PTRS)
- return 0; /* loop! */
- if(sldns_buffer_limit(pkt) <= ptr)
- return 0; /* out of bounds! */
- if(!endpos)
- endpos = sldns_buffer_position(pkt);
- sldns_buffer_set_position(pkt, ptr);
- } else {
- /* label contents */
- if(labellen > 0x3f)
- return 0; /* label too long */
- len += 1 + labellen;
- if(len > LDNS_MAX_DOMAINLEN)
- return 0;
- if(labellen == 0) {
- /* end of dname */
- break;
- }
- if(sldns_buffer_remaining(pkt) < labellen)
- return 0;
- sldns_buffer_skip(pkt, (ssize_t)labellen);
- }
- }
- if(endpos)
- sldns_buffer_set_position(pkt, endpos);
-
- return len;
-}
-
-int
-dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2)
-{
- uint8_t len1, len2;
- log_assert(pkt && d1 && d2);
- len1 = *d1++;
- len2 = *d2++;
- while( len1 != 0 || len2 != 0 ) {
- /* resolve ptrs */
- if(LABEL_IS_PTR(len1)) {
- d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1));
- len1 = *d1++;
- continue;
- }
- if(LABEL_IS_PTR(len2)) {
- d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2));
- len2 = *d2++;
- continue;
- }
- /* check label length */
- log_assert(len1 <= LDNS_MAX_LABELLEN);
- log_assert(len2 <= LDNS_MAX_LABELLEN);
- if(len1 != len2) {
- if(len1 < len2) return -1;
- return 1;
- }
- log_assert(len1 == len2 && len1 != 0);
- /* compare labels */
- while(len1--) {
- if(tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) {
- if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2))
- return -1;
- return 1;
- }
- d1++;
- d2++;
- }
- len1 = *d1++;
- len2 = *d2++;
- }
- return 0;
-}
-
-hashvalue_type
-dname_query_hash(uint8_t* dname, hashvalue_type h)
-{
- uint8_t labuf[LDNS_MAX_LABELLEN+1];
- uint8_t lablen;
- int i;
-
- /* preserve case of query, make hash label by label */
- lablen = *dname++;
- while(lablen) {
- log_assert(lablen <= LDNS_MAX_LABELLEN);
- labuf[0] = lablen;
- i=0;
- while(lablen--) {
- labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
- dname++;
- }
- h = hashlittle(labuf, labuf[0] + 1, h);
- lablen = *dname++;
- }
-
- return h;
-}
-
-hashvalue_type
-dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h)
-{
- uint8_t labuf[LDNS_MAX_LABELLEN+1];
- uint8_t lablen;
- int i;
-
- /* preserve case of query, make hash label by label */
- lablen = *dname++;
- while(lablen) {
- if(LABEL_IS_PTR(lablen)) {
- /* follow pointer */
- dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
- lablen = *dname++;
- continue;
- }
- log_assert(lablen <= LDNS_MAX_LABELLEN);
- labuf[0] = lablen;
- i=0;
- while(lablen--) {
- labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
- dname++;
- }
- h = hashlittle(labuf, labuf[0] + 1, h);
- lablen = *dname++;
- }
-
- return h;
-}
-
-void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)
-{
- /* copy over the dname and decompress it at the same time */
- size_t len = 0;
- uint8_t lablen;
- lablen = *dname++;
- while(lablen) {
- if(LABEL_IS_PTR(lablen)) {
- /* follow pointer */
- dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
- lablen = *dname++;
- continue;
- }
- log_assert(lablen <= LDNS_MAX_LABELLEN);
- len += (size_t)lablen+1;
- if(len >= LDNS_MAX_DOMAINLEN) {
- *to = 0; /* end the result prematurely */
- log_err("bad dname in dname_pkt_copy");
- return;
- }
- *to++ = lablen;
- memmove(to, dname, lablen);
- dname += lablen;
- to += lablen;
- lablen = *dname++;
- }
- /* copy last \0 */
- *to = 0;
-}
-
-void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname)
-{
- uint8_t lablen;
- if(!out) out = stdout;
- if(!dname) return;
-
- lablen = *dname++;
- if(!lablen)
- fputc('.', out);
- while(lablen) {
- if(LABEL_IS_PTR(lablen)) {
- /* follow pointer */
- if(!pkt) {
- fputs("??compressionptr??", out);
- return;
- }
- dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
- lablen = *dname++;
- continue;
- }
- if(lablen > LDNS_MAX_LABELLEN) {
- fputs("??extendedlabel??", out);
- return;
- }
- while(lablen--)
- fputc((int)*dname++, out);
- fputc('.', out);
- lablen = *dname++;
- }
-}
-
-int
-dname_count_labels(uint8_t* dname)
-{
- uint8_t lablen;
- int labs = 1;
-
- lablen = *dname++;
- while(lablen) {
- labs++;
- dname += lablen;
- lablen = *dname++;
- }
- return labs;
-}
-
-int
-dname_count_size_labels(uint8_t* dname, size_t* size)
-{
- uint8_t lablen;
- int labs = 1;
- size_t sz = 1;
-
- lablen = *dname++;
- while(lablen) {
- labs++;
- sz += lablen+1;
- dname += lablen;
- lablen = *dname++;
- }
- *size = sz;
- return labs;
-}
-
-/**
- * Compare labels in memory, lowercase while comparing.
- * @param p1: label 1
- * @param p2: label 2
- * @param len: number of bytes to compare.
- * @return: 0, -1, +1 comparison result.
- */
-static int
-memlowercmp(uint8_t* p1, uint8_t* p2, uint8_t len)
-{
- while(len--) {
- if(*p1 != *p2 && tolower((unsigned char)*p1) != tolower((unsigned char)*p2)) {
- if(tolower((unsigned char)*p1) < tolower((unsigned char)*p2))
- return -1;
- return 1;
- }
- p1++;
- p2++;
- }
- return 0;
-}
-
-int
-dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs)
-{
- uint8_t len1, len2;
- int atlabel = labs1;
- int lastmlabs;
- int lastdiff = 0;
- /* first skip so that we compare same label. */
- if(labs1 > labs2) {
- while(atlabel > labs2) {
- len1 = *d1++;
- d1 += len1;
- atlabel--;
- }
- log_assert(atlabel == labs2);
- } else if(labs1 < labs2) {
- atlabel = labs2;
- while(atlabel > labs1) {
- len2 = *d2++;
- d2 += len2;
- atlabel--;
- }
- log_assert(atlabel == labs1);
- }
- lastmlabs = atlabel+1;
- /* now at same label in d1 and d2, atlabel */
- /* www.example.com. */
- /* 4 3 2 1 atlabel number */
- /* repeat until at root label (which is always the same) */
- while(atlabel > 1) {
- len1 = *d1++;
- len2 = *d2++;
- if(len1 != len2) {
- log_assert(len1 != 0 && len2 != 0);
- if(len1<len2)
- lastdiff = -1;
- else lastdiff = 1;
- lastmlabs = atlabel;
- d1 += len1;
- d2 += len2;
- } else {
- /* memlowercmp is inlined here; or just like
- * if((c=memlowercmp(d1, d2, len1)) != 0) {
- * lastdiff = c;
- * lastmlabs = atlabel; } apart from d1++,d2++ */
- while(len1) {
- if(*d1 != *d2 && tolower((unsigned char)*d1)
- != tolower((unsigned char)*d2)) {
- if(tolower((unsigned char)*d1) <
- tolower((unsigned char)*d2)) {
- lastdiff = -1;
- lastmlabs = atlabel;
- d1 += len1;
- d2 += len1;
- break;
- }
- lastdiff = 1;
- lastmlabs = atlabel;
- d1 += len1;
- d2 += len1;
- break; /* out of memlowercmp */
- }
- d1++;
- d2++;
- len1--;
- }
- }
- atlabel--;
- }
- /* last difference atlabel number, so number of labels matching,
- * at the right side, is one less. */
- *mlabs = lastmlabs-1;
- if(lastdiff == 0) {
- /* all labels compared were equal, check if one has more
- * labels, so that example.com. > com. */
- if(labs1 > labs2)
- return 1;
- else if(labs1 < labs2)
- return -1;
- }
- return lastdiff;
-}
-
-int
-dname_buffer_write(sldns_buffer* pkt, uint8_t* dname)
-{
- uint8_t lablen;
-
- if(sldns_buffer_remaining(pkt) < 1)
- return 0;
- lablen = *dname++;
- sldns_buffer_write_u8(pkt, lablen);
- while(lablen) {
- if(sldns_buffer_remaining(pkt) < (size_t)lablen+1)
- return 0;
- sldns_buffer_write(pkt, dname, lablen);
- dname += lablen;
- lablen = *dname++;
- sldns_buffer_write_u8(pkt, lablen);
- }
- return 1;
-}
-
-void dname_str(uint8_t* dname, char* str)
-{
- size_t len = 0;
- uint8_t lablen = 0;
- char* s = str;
- if(!dname || !*dname) {
- *s++ = '.';
- *s = 0;
- return;
- }
- lablen = *dname++;
- while(lablen) {
- if(lablen > LDNS_MAX_LABELLEN) {
- *s++ = '#';
- *s = 0;
- return;
- }
- len += lablen+1;
- if(len >= LDNS_MAX_DOMAINLEN-1) {
- *s++ = '&';
- *s = 0;
- return;
- }
- while(lablen--) {
- if(isalnum((unsigned char)*dname)
- || *dname == '-' || *dname == '_'
- || *dname == '*')
- *s++ = *(char*)dname++;
- else {
- *s++ = '?';
- dname++;
- }
- }
- *s++ = '.';
- lablen = *dname++;
- }
- *s = 0;
-}
-
-int
-dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2)
-{
- int m;
- /* check subdomain: d1: www.example.com. and d2: example.com. */
- if(labs2 >= labs1)
- return 0;
- if(dname_lab_cmp(d1, labs1, d2, labs2, &m) > 0) {
- /* subdomain if all labels match */
- return (m == labs2);
- }
- return 0;
-}
-
-int
-dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2)
-{
- return dname_strict_subdomain(d1, dname_count_labels(d1), d2,
- dname_count_labels(d2));
-}
-
-int
-dname_subdomain_c(uint8_t* d1, uint8_t* d2)
-{
- int m;
- /* check subdomain: d1: www.example.com. and d2: example.com. */
- /* or d1: example.com. and d2: example.com. */
- int labs1 = dname_count_labels(d1);
- int labs2 = dname_count_labels(d2);
- if(labs2 > labs1)
- return 0;
- if(dname_lab_cmp(d1, labs1, d2, labs2, &m) < 0) {
- /* must have been example.com , www.example.com - wrong */
- /* or otherwise different dnames */
- return 0;
- }
- return (m == labs2);
-}
-
-int
-dname_is_root(uint8_t* dname)
-{
- uint8_t len;
- log_assert(dname);
- len = dname[0];
- log_assert(!LABEL_IS_PTR(len));
- return (len == 0);
-}
-
-void
-dname_remove_label(uint8_t** dname, size_t* len)
-{
- size_t lablen;
- log_assert(dname && *dname && len);
- lablen = (*dname)[0];
- log_assert(!LABEL_IS_PTR(lablen));
- log_assert(*len > lablen);
- if(lablen == 0)
- return; /* do not modify root label */
- *len -= lablen+1;
- *dname += lablen+1;
-}
-
-void
-dname_remove_labels(uint8_t** dname, size_t* len, int n)
-{
- int i;
- for(i=0; i<n; i++)
- dname_remove_label(dname, len);
-}
-
-int
-dname_signame_label_count(uint8_t* dname)
-{
- uint8_t lablen;
- int count = 0;
- if(!*dname)
- return 0;
- if(dname[0] == 1 && dname[1] == '*')
- dname += 2;
- lablen = dname[0];
- while(lablen) {
- count++;
- dname += lablen;
- dname += 1;
- lablen = dname[0];
- }
- return count;
-}
-
-int
-dname_is_wild(uint8_t* dname)
-{
- return (dname[0] == 1 && dname[1] == '*');
-}
-
-/**
- * Compare labels in memory, lowercase while comparing.
- * Returns canonical order for labels. If all is equal, the
- * shortest is first.
- *
- * @param p1: label 1
- * @param len1: length of label 1.
- * @param p2: label 2
- * @param len2: length of label 2.
- * @return: 0, -1, +1 comparison result.
- */
-static int
-memcanoncmp(uint8_t* p1, uint8_t len1, uint8_t* p2, uint8_t len2)
-{
- uint8_t min = (len1<len2)?len1:len2;
- int c = memlowercmp(p1, p2, min);
- if(c != 0)
- return c;
- /* equal, see who is shortest */
- if(len1 < len2)
- return -1;
- if(len1 > len2)
- return 1;
- return 0;
-}
-
-
-int
-dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs)
-{
- /* like dname_lab_cmp, but with different label comparison,
- * empty character sorts before \000.
- * So ylyly is before z. */
- uint8_t len1, len2;
- int atlabel = labs1;
- int lastmlabs;
- int lastdiff = 0;
- int c;
- /* first skip so that we compare same label. */
- if(labs1 > labs2) {
- while(atlabel > labs2) {
- len1 = *d1++;
- d1 += len1;
- atlabel--;
- }
- log_assert(atlabel == labs2);
- } else if(labs1 < labs2) {
- atlabel = labs2;
- while(atlabel > labs1) {
- len2 = *d2++;
- d2 += len2;
- atlabel--;
- }
- log_assert(atlabel == labs1);
- }
- lastmlabs = atlabel+1;
- /* now at same label in d1 and d2, atlabel */
- /* www.example.com. */
- /* 4 3 2 1 atlabel number */
- /* repeat until at root label (which is always the same) */
- while(atlabel > 1) {
- len1 = *d1++;
- len2 = *d2++;
-
- if((c=memcanoncmp(d1, len1, d2, len2)) != 0) {
- if(c<0)
- lastdiff = -1;
- else lastdiff = 1;
- lastmlabs = atlabel;
- }
-
- d1 += len1;
- d2 += len2;
- atlabel--;
- }
- /* last difference atlabel number, so number of labels matching,
- * at the right side, is one less. */
- *mlabs = lastmlabs-1;
- if(lastdiff == 0) {
- /* all labels compared were equal, check if one has more
- * labels, so that example.com. > com. */
- if(labs1 > labs2)
- return 1;
- else if(labs1 < labs2)
- return -1;
- }
- return lastdiff;
-}
-
-int
-dname_canonical_compare(uint8_t* d1, uint8_t* d2)
-{
- int labs1, labs2, m;
- labs1 = dname_count_labels(d1);
- labs2 = dname_count_labels(d2);
- return dname_canon_lab_cmp(d1, labs1, d2, labs2, &m);
-}
-
-uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2)
-{
- int labs1, labs2, m;
- size_t len = LDNS_MAX_DOMAINLEN;
- labs1 = dname_count_labels(d1);
- labs2 = dname_count_labels(d2);
- (void)dname_lab_cmp(d1, labs1, d2, labs2, &m);
- dname_remove_labels(&d1, &len, labs1-m);
- return d1;
-}
diff --git a/external/unbound/util/data/dname.h b/external/unbound/util/data/dname.h
deleted file mode 100644
index 53b341bf7..000000000
--- a/external/unbound/util/data/dname.h
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * util/data/dname.h - domain name routines
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains functions to deal with domain names (dnames).
- *
- * Some of the functions deal with domain names as a wireformat buffer,
- * with a length.
- */
-
-#ifndef UTIL_DATA_DNAME_H
-#define UTIL_DATA_DNAME_H
-#include "util/storage/lruhash.h"
-struct sldns_buffer;
-
-/** max number of compression ptrs to follow */
-#define MAX_COMPRESS_PTRS 256
-
-/**
- * Determine length of dname in buffer, no compression ptrs allowed,
- * @param query: the ldns buffer, current position at start of dname.
- * at end, position is at end of the dname.
- * @return: 0 on parse failure, or length including ending 0 of dname.
- */
-size_t query_dname_len(struct sldns_buffer* query);
-
-/**
- * Determine if dname in memory is correct. no compression ptrs allowed.
- * @param dname: where dname starts in memory.
- * @param len: dname is not allowed to exceed this length (i.e. of allocation).
- * @return length of dname if dname is ok, 0 on a parse error.
- */
-size_t dname_valid(uint8_t* dname, size_t len);
-
-/** lowercase query dname */
-void query_dname_tolower(uint8_t* dname);
-
-/**
- * lowercase pkt dname (follows compression pointers)
- * @param pkt: the packet, used to follow compression pointers. Position
- * is unchanged.
- * @param dname: start of dname in packet.
- */
-void pkt_dname_tolower(struct sldns_buffer* pkt, uint8_t* dname);
-
-/**
- * Compare query dnames (uncompressed storage). The Dnames passed do not
- * have to be lowercased, comparison routine does this.
- *
- * This routine is special, in that the comparison that it does corresponds
- * with the canonical comparison needed when comparing dnames inside rdata
- * for RR types that need canonicalization. That means that the first byte
- * that is smaller (possibly after lowercasing) makes an RR smaller, or the
- * shortest name makes an RR smaller.
- *
- * This routine does not compute the canonical order needed for NSEC
- * processing.
- *
- * Dnames have to be valid format.
- * @param d1: dname to compare
- * @param d2: dname to compare
- * @return: -1, 0, or +1 depending on comparison results.
- * Sort order is first difference found. not the canonical ordering.
- */
-int query_dname_compare(uint8_t* d1, uint8_t* d2);
-
-/**
- * Determine correct, compressed, dname present in packet.
- * Checks for parse errors.
- * @param pkt: packet to read from (from current start position).
- * @return: 0 on parse error.
- * At exit the position is right after the (compressed) dname.
- * Compression pointers are followed and checked for loops.
- * The uncompressed wireformat length is returned.
- */
-size_t pkt_dname_len(struct sldns_buffer* pkt);
-
-/**
- * Compare dnames in packet (compressed). Dnames must be valid.
- * routine performs lowercasing, so the packet casing is preserved.
- * @param pkt: packet, used to resolve compression pointers.
- * @param d1: dname to compare
- * @param d2: dname to compare
- * @return: -1, 0, or +1 depending on comparison results.
- * Sort order is first difference found. not the canonical ordering.
- */
-int dname_pkt_compare(struct sldns_buffer* pkt, uint8_t* d1, uint8_t* d2);
-
-/**
- * Hash dname, label by label, lowercasing, into hashvalue.
- * Dname in query format (not compressed).
- * @param dname: dname to hash.
- * @param h: initial hash value.
- * @return: result hash value.
- */
-hashvalue_type dname_query_hash(uint8_t* dname, hashvalue_type h);
-
-/**
- * Hash dname, label by label, lowercasing, into hashvalue.
- * Dname in pkt format (compressed).
- * @param pkt: packet, for resolving compression pointers.
- * @param dname: dname to hash, pointer to the pkt buffer.
- * Must be valid format. No loops, etc.
- * @param h: initial hash value.
- * @return: result hash value.
- * Result is the same as dname_query_hash, even if compression is used.
- */
-hashvalue_type dname_pkt_hash(struct sldns_buffer* pkt, uint8_t* dname,
- hashvalue_type h);
-
-/**
- * Copy over a valid dname and decompress it.
- * @param pkt: packet to resolve compression pointers.
- * @param to: buffer of size from pkt_len function to hold result.
- * @param dname: pointer into packet where dname starts.
- */
-void dname_pkt_copy(struct sldns_buffer* pkt, uint8_t* to, uint8_t* dname);
-
-/**
- * Copy over a valid dname to a packet.
- * @param pkt: packet to copy to.
- * @param dname: dname to copy.
- * @return: 0 if not enough space in buffer.
- */
-int dname_buffer_write(struct sldns_buffer* pkt, uint8_t* dname);
-
-/**
- * Count the number of labels in an uncompressed dname in memory.
- * @param dname: pointer to uncompressed dname.
- * @return: count of labels, including root label, "com." has 2 labels.
- */
-int dname_count_labels(uint8_t* dname);
-
-/**
- * Count labels and dname length both, for uncompressed dname in memory.
- * @param dname: pointer to uncompressed dname.
- * @param size: length of dname, including root label.
- * @return: count of labels, including root label, "com." has 2 labels.
- */
-int dname_count_size_labels(uint8_t* dname, size_t* size);
-
-/**
- * Compare dnames, sorted not canonical, but by label.
- * Such that zone contents follows zone apex.
- * @param d1: first dname. pointer to uncompressed wireformat.
- * @param labs1: number of labels in first dname.
- * @param d2: second dname. pointer to uncompressed wireformat.
- * @param labs2: number of labels in second dname.
- * @param mlabs: number of labels that matched exactly (the shared topdomain).
- * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
- */
-int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs);
-
-/**
- * See if domain name d1 is a strict subdomain of d2.
- * That is a subdomain, but not equal.
- * @param d1: domain name, uncompressed wireformat
- * @param labs1: number of labels in d1, including root label.
- * @param d2: domain name, uncompressed wireformat
- * @param labs2: number of labels in d2, including root label.
- * @return true if d1 is a subdomain of d2, but not equal to d2.
- */
-int dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2);
-
-/**
- * Like dname_strict_subdomain but counts labels
- * @param d1: domain name, uncompressed wireformat
- * @param d2: domain name, uncompressed wireformat
- * @return true if d1 is a subdomain of d2, but not equal to d2.
- */
-int dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2);
-
-/**
- * Counts labels. Tests is d1 is a subdomain of d2.
- * @param d1: domain name, uncompressed wireformat
- * @param d2: domain name, uncompressed wireformat
- * @return true if d1 is a subdomain of d2.
- */
-int dname_subdomain_c(uint8_t* d1, uint8_t* d2);
-
-/**
- * Debug helper. Print wireformat dname to output.
- * @param out: like stdout or a file.
- * @param pkt: if not NULL, the packet for resolving compression ptrs.
- * @param dname: pointer to (start of) dname.
- */
-void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname);
-
-/**
- * Debug helper. Print dname to given string buffer (string buffer must
- * be at least 255 chars + 1 for the 0, in printable form.
- * This may lose information (? for nonprintable characters, or & if
- * the name is too long, # for a bad label length).
- * @param dname: uncompressed wireformat.
- * @param str: buffer of 255+1 length.
- */
-void dname_str(uint8_t* dname, char* str);
-
-/**
- * Returns true if the uncompressed wireformat dname is the root "."
- * @param dname: the dname to check
- * @return true if ".", false if not.
- */
-int dname_is_root(uint8_t* dname);
-
-/**
- * Snip off first label from a dname, returning the parent zone.
- * @param dname: from what to strip off. uncompressed wireformat.
- * @param len: length, adjusted to become less.
- * @return stripped off, or "." if input was ".".
- */
-void dname_remove_label(uint8_t** dname, size_t* len);
-
-/**
- * Snip off first N labels from a dname, returning the parent zone.
- * @param dname: from what to strip off. uncompressed wireformat.
- * @param len: length, adjusted to become less.
- * @param n: number of labels to strip off (from the left).
- * if 0, nothing happens.
- * @return stripped off, or "." if input was ".".
- */
-void dname_remove_labels(uint8_t** dname, size_t* len, int n);
-
-/**
- * Count labels for the RRSIG signature label field.
- * Like a normal labelcount, but "*" wildcard and "." root are not counted.
- * @param dname: valid uncompressed wireformat.
- * @return number of labels like in RRSIG; '*' and '.' are not counted.
- */
-int dname_signame_label_count(uint8_t* dname);
-
-/**
- * Return true if the label is a wildcard, *.example.com.
- * @param dname: valid uncompressed wireformat.
- * @return true if wildcard, or false.
- */
-int dname_is_wild(uint8_t* dname);
-
-/**
- * Compare dnames, Canonical in rfc4034 sense, but by label.
- * Such that zone contents follows zone apex.
- *
- * @param d1: first dname. pointer to uncompressed wireformat.
- * @param labs1: number of labels in first dname.
- * @param d2: second dname. pointer to uncompressed wireformat.
- * @param labs2: number of labels in second dname.
- * @param mlabs: number of labels that matched exactly (the shared topdomain).
- * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
- */
-int dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2,
- int* mlabs);
-
-/**
- * Canonical dname compare. Takes care of counting labels.
- * Per rfc 4034 canonical order.
- *
- * @param d1: first dname. pointer to uncompressed wireformat.
- * @param d2: second dname. pointer to uncompressed wireformat.
- * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
- */
-int dname_canonical_compare(uint8_t* d1, uint8_t* d2);
-
-/**
- * Get the shared topdomain between two names. Root "." or longer.
- * @param d1: first dname. pointer to uncompressed wireformat.
- * @param d2: second dname. pointer to uncompressed wireformat.
- * @return pointer to shared topdomain. Ptr to a part of d1.
- */
-uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2);
-
-#endif /* UTIL_DATA_DNAME_H */
diff --git a/external/unbound/util/data/msgencode.c b/external/unbound/util/data/msgencode.c
deleted file mode 100644
index 1f72a03b8..000000000
--- a/external/unbound/util/data/msgencode.c
+++ /dev/null
@@ -1,916 +0,0 @@
-/*
- * util/data/msgencode.c - Encode DNS messages, queries and replies.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains a routines to encode DNS messages.
- */
-
-#include "config.h"
-#include "util/data/msgencode.h"
-#include "util/data/msgreply.h"
-#include "util/data/msgparse.h"
-#include "util/data/dname.h"
-#include "util/log.h"
-#include "util/regional.h"
-#include "util/net_help.h"
-#include "sldns/sbuffer.h"
-#include "services/localzone.h"
-
-/** return code that means the function ran out of memory. negative so it does
- * not conflict with DNS rcodes. */
-#define RETVAL_OUTMEM -2
-/** return code that means the data did not fit (completely) in the packet */
-#define RETVAL_TRUNC -4
-/** return code that means all is peachy keen. Equal to DNS rcode NOERROR */
-#define RETVAL_OK 0
-
-/**
- * Data structure to help domain name compression in outgoing messages.
- * A tree of dnames and their offsets in the packet is kept.
- * It is kept sorted, not canonical, but by label at least, so that after
- * a lookup of a name you know its closest match, and the parent from that
- * closest match. These are possible compression targets.
- *
- * It is a binary tree, not a rbtree or balanced tree, as the effort
- * of keeping it balanced probably outweighs usefulness (given typical
- * DNS packet size).
- */
-struct compress_tree_node {
- /** left node in tree, all smaller to this */
- struct compress_tree_node* left;
- /** right node in tree, all larger than this */
- struct compress_tree_node* right;
-
- /** the parent node - not for tree, but zone parent. One less label */
- struct compress_tree_node* parent;
- /** the domain name for this node. Pointer to uncompressed memory. */
- uint8_t* dname;
- /** number of labels in domain name, kept to help compare func. */
- int labs;
- /** offset in packet that points to this dname */
- size_t offset;
-};
-
-/**
- * Find domain name in tree, returns exact and closest match.
- * @param tree: root of tree.
- * @param dname: pointer to uncompressed dname.
- * @param labs: number of labels in domain name.
- * @param match: closest or exact match.
- * guaranteed to be smaller or equal to the sought dname.
- * can be null if the tree is empty.
- * @param matchlabels: number of labels that match with closest match.
- * can be zero is there is no match.
- * @param insertpt: insert location for dname, if not found.
- * @return: 0 if no exact match.
- */
-static int
-compress_tree_search(struct compress_tree_node** tree, uint8_t* dname,
- int labs, struct compress_tree_node** match, int* matchlabels,
- struct compress_tree_node*** insertpt)
-{
- int c, n, closen=0;
- struct compress_tree_node* p = *tree;
- struct compress_tree_node* close = 0;
- struct compress_tree_node** prev = tree;
- while(p) {
- if((c = dname_lab_cmp(dname, labs, p->dname, p->labs, &n))
- == 0) {
- *matchlabels = n;
- *match = p;
- return 1;
- }
- if(c<0) {
- prev = &p->left;
- p = p->left;
- } else {
- closen = n;
- close = p; /* p->dname is smaller than dname */
- prev = &p->right;
- p = p->right;
- }
- }
- *insertpt = prev;
- *matchlabels = closen;
- *match = close;
- return 0;
-}
-
-/**
- * Lookup a domain name in compression tree.
- * @param tree: root of tree (not the node with '.').
- * @param dname: pointer to uncompressed dname.
- * @param labs: number of labels in domain name.
- * @param insertpt: insert location for dname, if not found.
- * @return: 0 if not found or compress treenode with best compression.
- */
-static struct compress_tree_node*
-compress_tree_lookup(struct compress_tree_node** tree, uint8_t* dname,
- int labs, struct compress_tree_node*** insertpt)
-{
- struct compress_tree_node* p;
- int m;
- if(labs <= 1)
- return 0; /* do not compress root node */
- if(compress_tree_search(tree, dname, labs, &p, &m, insertpt)) {
- /* exact match */
- return p;
- }
- /* return some ancestor of p that compresses well. */
- if(m>1) {
- /* www.example.com. (labs=4) matched foo.example.com.(labs=4)
- * then matchcount = 3. need to go up. */
- while(p && p->labs > m)
- p = p->parent;
- return p;
- }
- return 0;
-}
-
-/**
- * Create node for domain name compression tree.
- * @param dname: pointer to uncompressed dname (stored in tree).
- * @param labs: number of labels in dname.
- * @param offset: offset into packet for dname.
- * @param region: how to allocate memory for new node.
- * @return new node or 0 on malloc failure.
- */
-static struct compress_tree_node*
-compress_tree_newnode(uint8_t* dname, int labs, size_t offset,
- struct regional* region)
-{
- struct compress_tree_node* n = (struct compress_tree_node*)
- regional_alloc(region, sizeof(struct compress_tree_node));
- if(!n) return 0;
- n->left = 0;
- n->right = 0;
- n->parent = 0;
- n->dname = dname;
- n->labs = labs;
- n->offset = offset;
- return n;
-}
-
-/**
- * Store domain name and ancestors into compression tree.
- * @param dname: pointer to uncompressed dname (stored in tree).
- * @param labs: number of labels in dname.
- * @param offset: offset into packet for dname.
- * @param region: how to allocate memory for new node.
- * @param closest: match from previous lookup, used to compress dname.
- * may be NULL if no previous match.
- * if the tree has an ancestor of dname already, this must be it.
- * @param insertpt: where to insert the dname in tree.
- * @return: 0 on memory error.
- */
-static int
-compress_tree_store(uint8_t* dname, int labs, size_t offset,
- struct regional* region, struct compress_tree_node* closest,
- struct compress_tree_node** insertpt)
-{
- uint8_t lablen;
- struct compress_tree_node* newnode;
- struct compress_tree_node* prevnode = NULL;
- int uplabs = labs-1; /* does not store root in tree */
- if(closest) uplabs = labs - closest->labs;
- log_assert(uplabs >= 0);
- /* algorithms builds up a vine of dname-labels to hang into tree */
- while(uplabs--) {
- if(offset > PTR_MAX_OFFSET) {
- /* insertion failed, drop vine */
- return 1; /* compression pointer no longer useful */
- }
- if(!(newnode = compress_tree_newnode(dname, labs, offset,
- region))) {
- /* insertion failed, drop vine */
- return 0;
- }
-
- if(prevnode) {
- /* chain nodes together, last one has one label more,
- * so is larger than newnode, thus goes right. */
- newnode->right = prevnode;
- prevnode->parent = newnode;
- }
-
- /* next label */
- lablen = *dname++;
- dname += lablen;
- offset += lablen+1;
- prevnode = newnode;
- labs--;
- }
- /* if we have a vine, hang the vine into the tree */
- if(prevnode) {
- *insertpt = prevnode;
- prevnode->parent = closest;
- }
- return 1;
-}
-
-/** compress a domain name */
-static int
-write_compressed_dname(sldns_buffer* pkt, uint8_t* dname, int labs,
- struct compress_tree_node* p)
-{
- /* compress it */
- int labcopy = labs - p->labs;
- uint8_t lablen;
- uint16_t ptr;
-
- if(labs == 1) {
- /* write root label */
- if(sldns_buffer_remaining(pkt) < 1)
- return 0;
- sldns_buffer_write_u8(pkt, 0);
- return 1;
- }
-
- /* copy the first couple of labels */
- while(labcopy--) {
- lablen = *dname++;
- if(sldns_buffer_remaining(pkt) < (size_t)lablen+1)
- return 0;
- sldns_buffer_write_u8(pkt, lablen);
- sldns_buffer_write(pkt, dname, lablen);
- dname += lablen;
- }
- /* insert compression ptr */
- if(sldns_buffer_remaining(pkt) < 2)
- return 0;
- ptr = PTR_CREATE(p->offset);
- sldns_buffer_write_u16(pkt, ptr);
- return 1;
-}
-
-/** compress owner name of RR, return RETVAL_OUTMEM RETVAL_TRUNC */
-static int
-compress_owner(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
- struct regional* region, struct compress_tree_node** tree,
- size_t owner_pos, uint16_t* owner_ptr, int owner_labs)
-{
- struct compress_tree_node* p;
- struct compress_tree_node** insertpt = NULL;
- if(!*owner_ptr) {
- /* compress first time dname */
- if((p = compress_tree_lookup(tree, key->rk.dname,
- owner_labs, &insertpt))) {
- if(p->labs == owner_labs)
- /* avoid ptr chains, since some software is
- * not capable of decoding ptr after a ptr. */
- *owner_ptr = htons(PTR_CREATE(p->offset));
- if(!write_compressed_dname(pkt, key->rk.dname,
- owner_labs, p))
- return RETVAL_TRUNC;
- /* check if typeclass+4 ttl + rdatalen is available */
- if(sldns_buffer_remaining(pkt) < 4+4+2)
- return RETVAL_TRUNC;
- } else {
- /* no compress */
- if(sldns_buffer_remaining(pkt) < key->rk.dname_len+4+4+2)
- return RETVAL_TRUNC;
- sldns_buffer_write(pkt, key->rk.dname,
- key->rk.dname_len);
- if(owner_pos <= PTR_MAX_OFFSET)
- *owner_ptr = htons(PTR_CREATE(owner_pos));
- }
- if(!compress_tree_store(key->rk.dname, owner_labs,
- owner_pos, region, p, insertpt))
- return RETVAL_OUTMEM;
- } else {
- /* always compress 2nd-further RRs in RRset */
- if(owner_labs == 1) {
- if(sldns_buffer_remaining(pkt) < 1+4+4+2)
- return RETVAL_TRUNC;
- sldns_buffer_write_u8(pkt, 0);
- } else {
- if(sldns_buffer_remaining(pkt) < 2+4+4+2)
- return RETVAL_TRUNC;
- sldns_buffer_write(pkt, owner_ptr, 2);
- }
- }
- return RETVAL_OK;
-}
-
-/** compress any domain name to the packet, return RETVAL_* */
-static int
-compress_any_dname(uint8_t* dname, sldns_buffer* pkt, int labs,
- struct regional* region, struct compress_tree_node** tree)
-{
- struct compress_tree_node* p;
- struct compress_tree_node** insertpt = NULL;
- size_t pos = sldns_buffer_position(pkt);
- if((p = compress_tree_lookup(tree, dname, labs, &insertpt))) {
- if(!write_compressed_dname(pkt, dname, labs, p))
- return RETVAL_TRUNC;
- } else {
- if(!dname_buffer_write(pkt, dname))
- return RETVAL_TRUNC;
- }
- if(!compress_tree_store(dname, labs, pos, region, p, insertpt))
- return RETVAL_OUTMEM;
- return RETVAL_OK;
-}
-
-/** return true if type needs domain name compression in rdata */
-static const sldns_rr_descriptor*
-type_rdata_compressable(struct ub_packed_rrset_key* key)
-{
- uint16_t t = ntohs(key->rk.type);
- if(sldns_rr_descript(t) &&
- sldns_rr_descript(t)->_compress == LDNS_RR_COMPRESS)
- return sldns_rr_descript(t);
- return 0;
-}
-
-/** compress domain names in rdata, return RETVAL_* */
-static int
-compress_rdata(sldns_buffer* pkt, uint8_t* rdata, size_t todolen,
- struct regional* region, struct compress_tree_node** tree,
- const sldns_rr_descriptor* desc)
-{
- int labs, r, rdf = 0;
- size_t dname_len, len, pos = sldns_buffer_position(pkt);
- uint8_t count = desc->_dname_count;
-
- sldns_buffer_skip(pkt, 2); /* rdata len fill in later */
- /* space for rdatalen checked for already */
- rdata += 2;
- todolen -= 2;
- while(todolen > 0 && count) {
- switch(desc->_wireformat[rdf]) {
- case LDNS_RDF_TYPE_DNAME:
- labs = dname_count_size_labels(rdata, &dname_len);
- if((r=compress_any_dname(rdata, pkt, labs, region,
- tree)) != RETVAL_OK)
- return r;
- rdata += dname_len;
- todolen -= dname_len;
- count--;
- len = 0;
- break;
- case LDNS_RDF_TYPE_STR:
- len = *rdata + 1;
- break;
- default:
- len = get_rdf_size(desc->_wireformat[rdf]);
- }
- if(len) {
- /* copy over */
- if(sldns_buffer_remaining(pkt) < len)
- return RETVAL_TRUNC;
- sldns_buffer_write(pkt, rdata, len);
- todolen -= len;
- rdata += len;
- }
- rdf++;
- }
- /* copy remainder */
- if(todolen > 0) {
- if(sldns_buffer_remaining(pkt) < todolen)
- return RETVAL_TRUNC;
- sldns_buffer_write(pkt, rdata, todolen);
- }
-
- /* set rdata len */
- sldns_buffer_write_u16_at(pkt, pos, sldns_buffer_position(pkt)-pos-2);
- return RETVAL_OK;
-}
-
-/** Returns true if RR type should be included */
-static int
-rrset_belongs_in_reply(sldns_pkt_section s, uint16_t rrtype, uint16_t qtype,
- int dnssec)
-{
- if(dnssec)
- return 1;
- /* skip non DNSSEC types, except if directly queried for */
- if(s == LDNS_SECTION_ANSWER) {
- if(qtype == LDNS_RR_TYPE_ANY || qtype == rrtype)
- return 1;
- }
- /* check DNSSEC-ness */
- switch(rrtype) {
- case LDNS_RR_TYPE_SIG:
- case LDNS_RR_TYPE_KEY:
- case LDNS_RR_TYPE_NXT:
- case LDNS_RR_TYPE_DS:
- case LDNS_RR_TYPE_RRSIG:
- case LDNS_RR_TYPE_NSEC:
- case LDNS_RR_TYPE_DNSKEY:
- case LDNS_RR_TYPE_NSEC3:
- case LDNS_RR_TYPE_NSEC3PARAMS:
- return 0;
- }
- return 1;
-}
-
-/** store rrset in buffer in wireformat, return RETVAL_* */
-static int
-packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
- uint16_t* num_rrs, time_t timenow, struct regional* region,
- int do_data, int do_sig, struct compress_tree_node** tree,
- sldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
-{
- size_t i, j, owner_pos;
- int r, owner_labs;
- uint16_t owner_ptr = 0;
- struct packed_rrset_data* data = (struct packed_rrset_data*)
- key->entry.data;
-
- /* does this RR type belong in the answer? */
- if(!rrset_belongs_in_reply(s, ntohs(key->rk.type), qtype, dnssec))
- return RETVAL_OK;
-
- owner_labs = dname_count_labels(key->rk.dname);
- owner_pos = sldns_buffer_position(pkt);
-
- /* For an rrset with a fixed TTL, use the rrset's TTL as given */
- if((key->rk.flags & PACKED_RRSET_FIXEDTTL) != 0)
- timenow = 0;
-
- if(do_data) {
- const sldns_rr_descriptor* c = type_rdata_compressable(key);
- for(i=0; i<data->count; i++) {
- /* rrset roundrobin */
- j = (i + rr_offset) % data->count;
- if((r=compress_owner(key, pkt, region, tree,
- owner_pos, &owner_ptr, owner_labs))
- != RETVAL_OK)
- return r;
- sldns_buffer_write(pkt, &key->rk.type, 2);
- sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
- if(data->rr_ttl[j] < timenow)
- sldns_buffer_write_u32(pkt, 0);
- else sldns_buffer_write_u32(pkt,
- data->rr_ttl[j]-timenow);
- if(c) {
- if((r=compress_rdata(pkt, data->rr_data[j],
- data->rr_len[j], region, tree, c))
- != RETVAL_OK)
- return r;
- } else {
- if(sldns_buffer_remaining(pkt) < data->rr_len[j])
- return RETVAL_TRUNC;
- sldns_buffer_write(pkt, data->rr_data[j],
- data->rr_len[j]);
- }
- }
- }
- /* insert rrsigs */
- if(do_sig && dnssec) {
- size_t total = data->count+data->rrsig_count;
- for(i=data->count; i<total; i++) {
- if(owner_ptr && owner_labs != 1) {
- if(sldns_buffer_remaining(pkt) <
- 2+4+4+data->rr_len[i])
- return RETVAL_TRUNC;
- sldns_buffer_write(pkt, &owner_ptr, 2);
- } else {
- if((r=compress_any_dname(key->rk.dname,
- pkt, owner_labs, region, tree))
- != RETVAL_OK)
- return r;
- if(sldns_buffer_remaining(pkt) <
- 4+4+data->rr_len[i])
- return RETVAL_TRUNC;
- }
- sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_RRSIG);
- sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
- if(data->rr_ttl[i] < timenow)
- sldns_buffer_write_u32(pkt, 0);
- else sldns_buffer_write_u32(pkt,
- data->rr_ttl[i]-timenow);
- /* rrsig rdata cannot be compressed, perform 100+ byte
- * memcopy. */
- sldns_buffer_write(pkt, data->rr_data[i],
- data->rr_len[i]);
- }
- }
- /* change rrnum only after we are sure it fits */
- if(do_data)
- *num_rrs += data->count;
- if(do_sig && dnssec)
- *num_rrs += data->rrsig_count;
-
- return RETVAL_OK;
-}
-
-/** store msg section in wireformat buffer, return RETVAL_* */
-static int
-insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
- sldns_buffer* pkt, size_t rrsets_before, time_t timenow,
- struct regional* region, struct compress_tree_node** tree,
- sldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
-{
- int r;
- size_t i, setstart;
- /* we now allow this function to be called multiple times for the
- * same section, incrementally updating num_rrs. The caller is
- * responsible for initializing it (which is the case in the current
- * implementation). */
-
- if(s != LDNS_SECTION_ADDITIONAL) {
- if(s == LDNS_SECTION_ANSWER && qtype == LDNS_RR_TYPE_ANY)
- dnssec = 1; /* include all types in ANY answer */
- for(i=0; i<num_rrsets; i++) {
- setstart = sldns_buffer_position(pkt);
- if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
- pkt, num_rrs, timenow, region, 1, 1, tree,
- s, qtype, dnssec, rr_offset))
- != RETVAL_OK) {
- /* Bad, but if due to size must set TC bit */
- /* trim off the rrset neatly. */
- sldns_buffer_set_position(pkt, setstart);
- return r;
- }
- }
- } else {
- for(i=0; i<num_rrsets; i++) {
- setstart = sldns_buffer_position(pkt);
- if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
- pkt, num_rrs, timenow, region, 1, 0, tree,
- s, qtype, dnssec, rr_offset))
- != RETVAL_OK) {
- sldns_buffer_set_position(pkt, setstart);
- return r;
- }
- }
- if(dnssec)
- for(i=0; i<num_rrsets; i++) {
- setstart = sldns_buffer_position(pkt);
- if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
- pkt, num_rrs, timenow, region, 0, 1, tree,
- s, qtype, dnssec, rr_offset))
- != RETVAL_OK) {
- sldns_buffer_set_position(pkt, setstart);
- return r;
- }
- }
- }
- return RETVAL_OK;
-}
-
-/** store query section in wireformat buffer, return RETVAL */
-static int
-insert_query(struct query_info* qinfo, struct compress_tree_node** tree,
- sldns_buffer* buffer, struct regional* region)
-{
- uint8_t* qname = qinfo->local_alias ?
- qinfo->local_alias->rrset->rk.dname : qinfo->qname;
- size_t qname_len = qinfo->local_alias ?
- qinfo->local_alias->rrset->rk.dname_len : qinfo->qname_len;
- if(sldns_buffer_remaining(buffer) <
- qinfo->qname_len+sizeof(uint16_t)*2)
- return RETVAL_TRUNC; /* buffer too small */
- /* the query is the first name inserted into the tree */
- if(!compress_tree_store(qname, dname_count_labels(qname),
- sldns_buffer_position(buffer), region, NULL, tree))
- return RETVAL_OUTMEM;
- if(sldns_buffer_current(buffer) == qname)
- sldns_buffer_skip(buffer, (ssize_t)qname_len);
- else sldns_buffer_write(buffer, qname, qname_len);
- sldns_buffer_write_u16(buffer, qinfo->qtype);
- sldns_buffer_write_u16(buffer, qinfo->qclass);
- return RETVAL_OK;
-}
-
-static int
-positive_answer(struct reply_info* rep, uint16_t qtype) {
- size_t i;
- if (FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR)
- return 0;
-
- for(i=0;i<rep->an_numrrsets; i++) {
- if(ntohs(rep->rrsets[i]->rk.type) == qtype) {
- /* in case it is a wildcard with DNSSEC, there will
- * be NSEC/NSEC3 records in the authority section
- * that we cannot remove */
- for(i=rep->an_numrrsets; i<rep->an_numrrsets+
- rep->ns_numrrsets; i++) {
- if(ntohs(rep->rrsets[i]->rk.type) ==
- LDNS_RR_TYPE_NSEC ||
- ntohs(rep->rrsets[i]->rk.type) ==
- LDNS_RR_TYPE_NSEC3)
- return 0;
- }
- return 1;
- }
- }
- return 0;
-}
-
-int
-reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
- uint16_t id, uint16_t flags, sldns_buffer* buffer, time_t timenow,
- struct regional* region, uint16_t udpsize, int dnssec)
-{
- uint16_t ancount=0, nscount=0, arcount=0;
- struct compress_tree_node* tree = 0;
- int r;
- size_t rr_offset;
-
- sldns_buffer_clear(buffer);
- if(udpsize < sldns_buffer_limit(buffer))
- sldns_buffer_set_limit(buffer, udpsize);
- if(sldns_buffer_remaining(buffer) < LDNS_HEADER_SIZE)
- return 0;
-
- sldns_buffer_write(buffer, &id, sizeof(uint16_t));
- sldns_buffer_write_u16(buffer, flags);
- sldns_buffer_write_u16(buffer, rep->qdcount);
- /* set an, ns, ar counts to zero in case of small packets */
- sldns_buffer_write(buffer, "\000\000\000\000\000\000", 6);
-
- /* insert query section */
- if(rep->qdcount) {
- if((r=insert_query(qinfo, &tree, buffer, region)) !=
- RETVAL_OK) {
- if(r == RETVAL_TRUNC) {
- /* create truncated message */
- sldns_buffer_write_u16_at(buffer, 4, 0);
- LDNS_TC_SET(sldns_buffer_begin(buffer));
- sldns_buffer_flip(buffer);
- return 1;
- }
- return 0;
- }
- }
- /* roundrobin offset. using query id for random number. With ntohs
- * for different roundrobins for sequential id client senders. */
- rr_offset = RRSET_ROUNDROBIN?ntohs(id):0;
-
- /* "prepend" any local alias records in the answer section if this
- * response is supposed to be authoritative. Currently it should
- * be a single CNAME record (sanity-checked in worker_handle_request())
- * but it can be extended if and when we support more variations of
- * aliases. */
- if(qinfo->local_alias && (flags & BIT_AA)) {
- struct reply_info arep;
- time_t timezero = 0; /* to use the 'authoritative' TTL */
- memset(&arep, 0, sizeof(arep));
- arep.flags = rep->flags;
- arep.an_numrrsets = 1;
- arep.rrset_count = 1;
- arep.rrsets = &qinfo->local_alias->rrset;
- if((r=insert_section(&arep, 1, &ancount, buffer, 0,
- timezero, region, &tree, LDNS_SECTION_ANSWER,
- qinfo->qtype, dnssec, rr_offset)) != RETVAL_OK) {
- if(r == RETVAL_TRUNC) {
- /* create truncated message */
- sldns_buffer_write_u16_at(buffer, 6, ancount);
- LDNS_TC_SET(sldns_buffer_begin(buffer));
- sldns_buffer_flip(buffer);
- return 1;
- }
- return 0;
- }
- }
-
- /* insert answer section */
- if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer,
- 0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype,
- dnssec, rr_offset)) != RETVAL_OK) {
- if(r == RETVAL_TRUNC) {
- /* create truncated message */
- sldns_buffer_write_u16_at(buffer, 6, ancount);
- LDNS_TC_SET(sldns_buffer_begin(buffer));
- sldns_buffer_flip(buffer);
- return 1;
- }
- return 0;
- }
- sldns_buffer_write_u16_at(buffer, 6, ancount);
-
- /* if response is positive answer, auth/add sections are not required */
- if( ! (MINIMAL_RESPONSES && positive_answer(rep, qinfo->qtype)) ) {
- /* insert auth section */
- if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer,
- rep->an_numrrsets, timenow, region, &tree,
- LDNS_SECTION_AUTHORITY, qinfo->qtype,
- dnssec, rr_offset)) != RETVAL_OK) {
- if(r == RETVAL_TRUNC) {
- /* create truncated message */
- sldns_buffer_write_u16_at(buffer, 8, nscount);
- LDNS_TC_SET(sldns_buffer_begin(buffer));
- sldns_buffer_flip(buffer);
- return 1;
- }
- return 0;
- }
- sldns_buffer_write_u16_at(buffer, 8, nscount);
-
- /* insert add section */
- if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer,
- rep->an_numrrsets + rep->ns_numrrsets, timenow, region,
- &tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype,
- dnssec, rr_offset)) != RETVAL_OK) {
- if(r == RETVAL_TRUNC) {
- /* no need to set TC bit, this is the additional */
- sldns_buffer_write_u16_at(buffer, 10, arcount);
- sldns_buffer_flip(buffer);
- return 1;
- }
- return 0;
- }
- sldns_buffer_write_u16_at(buffer, 10, arcount);
- }
- sldns_buffer_flip(buffer);
- return 1;
-}
-
-uint16_t
-calc_edns_field_size(struct edns_data* edns)
-{
- size_t rdatalen = 0;
- struct edns_option* opt;
- if(!edns || !edns->edns_present)
- return 0;
- for(opt = edns->opt_list; opt; opt = opt->next) {
- rdatalen += 4 + opt->opt_len;
- }
- /* domain root '.' + type + class + ttl + rdatalen */
- return 1 + 2 + 2 + 4 + 2 + rdatalen;
-}
-
-void
-attach_edns_record(sldns_buffer* pkt, struct edns_data* edns)
-{
- size_t len;
- size_t rdatapos;
- struct edns_option* opt;
- if(!edns || !edns->edns_present)
- return;
- /* inc additional count */
- sldns_buffer_write_u16_at(pkt, 10,
- sldns_buffer_read_u16_at(pkt, 10) + 1);
- len = sldns_buffer_limit(pkt);
- sldns_buffer_clear(pkt);
- sldns_buffer_set_position(pkt, len);
- /* write EDNS record */
- sldns_buffer_write_u8(pkt, 0); /* '.' label */
- sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_OPT); /* type */
- sldns_buffer_write_u16(pkt, edns->udp_size); /* class */
- sldns_buffer_write_u8(pkt, edns->ext_rcode); /* ttl */
- sldns_buffer_write_u8(pkt, edns->edns_version);
- sldns_buffer_write_u16(pkt, edns->bits);
- rdatapos = sldns_buffer_position(pkt);
- sldns_buffer_write_u16(pkt, 0); /* rdatalen */
- /* write rdata */
- for(opt=edns->opt_list; opt; opt=opt->next) {
- sldns_buffer_write_u16(pkt, opt->opt_code);
- sldns_buffer_write_u16(pkt, opt->opt_len);
- if(opt->opt_len != 0)
- sldns_buffer_write(pkt, opt->opt_data, opt->opt_len);
- }
- if(edns->opt_list)
- sldns_buffer_write_u16_at(pkt, rdatapos,
- sldns_buffer_position(pkt)-rdatapos-2);
- sldns_buffer_flip(pkt);
-}
-
-int
-reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
- uint16_t id, uint16_t qflags, sldns_buffer* pkt, time_t timenow,
- int cached, struct regional* region, uint16_t udpsize,
- struct edns_data* edns, int dnssec, int secure)
-{
- uint16_t flags;
- int attach_edns = 1;
-
- if(!cached || rep->authoritative) {
- /* original flags, copy RD and CD bits from query. */
- flags = rep->flags | (qflags & (BIT_RD|BIT_CD));
- } else {
- /* remove AA bit, copy RD and CD bits from query. */
- flags = (rep->flags & ~BIT_AA) | (qflags & (BIT_RD|BIT_CD));
- }
- if(secure && (dnssec || (qflags&BIT_AD)))
- flags |= BIT_AD;
- /* restore AA bit if we have a local alias and the response can be
- * authoritative. Also clear AD bit if set as the local data is the
- * primary answer. */
- if(qinf->local_alias &&
- (FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR ||
- FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN)) {
- flags |= BIT_AA;
- flags &= ~BIT_AD;
- }
- log_assert(flags & BIT_QR); /* QR bit must be on in our replies */
- if(udpsize < LDNS_HEADER_SIZE)
- return 0;
- if(udpsize < LDNS_HEADER_SIZE + calc_edns_field_size(edns)) {
- /* packet too small to contain edns, omit it. */
- attach_edns = 0;
- } else {
- /* reserve space for edns record */
- udpsize -= calc_edns_field_size(edns);
- }
-
- if(!reply_info_encode(qinf, rep, id, flags, pkt, timenow, region,
- udpsize, dnssec)) {
- log_err("reply encode: out of memory");
- return 0;
- }
- if(attach_edns)
- attach_edns_record(pkt, edns);
- return 1;
-}
-
-void
-qinfo_query_encode(sldns_buffer* pkt, struct query_info* qinfo)
-{
- uint16_t flags = 0; /* QUERY, NOERROR */
- const uint8_t* qname = qinfo->local_alias ?
- qinfo->local_alias->rrset->rk.dname : qinfo->qname;
- size_t qname_len = qinfo->local_alias ?
- qinfo->local_alias->rrset->rk.dname_len : qinfo->qname_len;
- sldns_buffer_clear(pkt);
- log_assert(sldns_buffer_remaining(pkt) >= 12+255+4/*max query*/);
- sldns_buffer_skip(pkt, 2); /* id done later */
- sldns_buffer_write_u16(pkt, flags);
- sldns_buffer_write_u16(pkt, 1); /* query count */
- sldns_buffer_write(pkt, "\000\000\000\000\000\000", 6); /* counts */
- sldns_buffer_write(pkt, qname, qname_len);
- sldns_buffer_write_u16(pkt, qinfo->qtype);
- sldns_buffer_write_u16(pkt, qinfo->qclass);
- sldns_buffer_flip(pkt);
-}
-
-void
-error_encode(sldns_buffer* buf, int r, struct query_info* qinfo,
- uint16_t qid, uint16_t qflags, struct edns_data* edns)
-{
- uint16_t flags;
-
- sldns_buffer_clear(buf);
- sldns_buffer_write(buf, &qid, sizeof(uint16_t));
- flags = (uint16_t)(BIT_QR | BIT_RA | r); /* QR and retcode*/
- flags |= (qflags & (BIT_RD|BIT_CD)); /* copy RD and CD bit */
- sldns_buffer_write_u16(buf, flags);
- if(qinfo) flags = 1;
- else flags = 0;
- sldns_buffer_write_u16(buf, flags);
- flags = 0;
- sldns_buffer_write(buf, &flags, sizeof(uint16_t));
- sldns_buffer_write(buf, &flags, sizeof(uint16_t));
- sldns_buffer_write(buf, &flags, sizeof(uint16_t));
- if(qinfo) {
- const uint8_t* qname = qinfo->local_alias ?
- qinfo->local_alias->rrset->rk.dname : qinfo->qname;
- size_t qname_len = qinfo->local_alias ?
- qinfo->local_alias->rrset->rk.dname_len :
- qinfo->qname_len;
- if(sldns_buffer_current(buf) == qname)
- sldns_buffer_skip(buf, (ssize_t)qname_len);
- else sldns_buffer_write(buf, qname, qname_len);
- sldns_buffer_write_u16(buf, qinfo->qtype);
- sldns_buffer_write_u16(buf, qinfo->qclass);
- }
- sldns_buffer_flip(buf);
- if(edns) {
- struct edns_data es = *edns;
- es.edns_version = EDNS_ADVERTISED_VERSION;
- es.udp_size = EDNS_ADVERTISED_SIZE;
- es.ext_rcode = 0;
- es.bits &= EDNS_DO;
- if(sldns_buffer_limit(buf) + calc_edns_field_size(&es) >
- edns->udp_size)
- return;
- attach_edns_record(buf, &es);
- }
-}
diff --git a/external/unbound/util/data/msgencode.h b/external/unbound/util/data/msgencode.h
deleted file mode 100644
index eea129d98..000000000
--- a/external/unbound/util/data/msgencode.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * util/data/msgencode.h - encode compressed DNS messages.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains temporary data structures and routines to create
- * compressed DNS messages.
- */
-
-#ifndef UTIL_DATA_MSGENCODE_H
-#define UTIL_DATA_MSGENCODE_H
-struct sldns_buffer;
-struct query_info;
-struct reply_info;
-struct regional;
-struct edns_data;
-
-/**
- * Generate answer from reply_info.
- * @param qinf: query information that provides query section in packet.
- * @param rep: reply to fill in.
- * @param id: id word from the query.
- * @param qflags: flags word from the query.
- * @param dest: buffer to put message into; will truncate if it does not fit.
- * @param timenow: time to subtract.
- * @param cached: set true if a cached reply (so no AA bit).
- * set false for the first reply.
- * @param region: where to allocate temp variables (for compression).
- * @param udpsize: size of the answer, 512, from EDNS, or 64k for TCP.
- * @param edns: EDNS data included in the answer, NULL for none.
- * or if edns_present = 0, it is not included.
- * @param dnssec: if 0 DNSSEC records are omitted from the answer.
- * @param secure: if 1, the AD bit is set in the reply.
- * @return: 0 on error (server failure).
- */
-int reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
- uint16_t id, uint16_t qflags, struct sldns_buffer* dest, time_t timenow,
- int cached, struct regional* region, uint16_t udpsize,
- struct edns_data* edns, int dnssec, int secure);
-
-/**
- * Regenerate the wireformat from the stored msg reply.
- * If the buffer is too small then the message is truncated at a whole
- * rrset and the TC bit set, or whole rrsets are left out of the additional
- * and the TC bit is not set.
- * @param qinfo: query info to store.
- * @param rep: reply to store.
- * @param id: id value to store, network order.
- * @param flags: flags value to store, host order.
- * @param buffer: buffer to store the packet into.
- * @param timenow: time now, to adjust ttl values.
- * @param region: to store temporary data in.
- * @param udpsize: size of the answer, 512, from EDNS, or 64k for TCP.
- * @param dnssec: if 0 DNSSEC records are omitted from the answer.
- * @return: nonzero is success, or
- * 0 on error: malloc failure (no log_err has been done).
- */
-int reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
- uint16_t id, uint16_t flags, struct sldns_buffer* buffer, time_t timenow,
- struct regional* region, uint16_t udpsize, int dnssec);
-
-/**
- * Encode query packet. Assumes the buffer is large enough.
- * @param pkt: where to store the packet.
- * @param qinfo: query info.
- */
-void qinfo_query_encode(struct sldns_buffer* pkt, struct query_info* qinfo);
-
-/**
- * Estimate size of EDNS record in packet. EDNS record will be no larger.
- * @param edns: edns data or NULL.
- * @return octets to reserve for EDNS.
- */
-uint16_t calc_edns_field_size(struct edns_data* edns);
-
-/**
- * Attach EDNS record to buffer. Buffer has complete packet. There must
- * be enough room left for the EDNS record.
- * @param pkt: packet added to.
- * @param edns: if NULL or present=0, nothing is added to the packet.
- */
-void attach_edns_record(struct sldns_buffer* pkt, struct edns_data* edns);
-
-/**
- * Encode an error. With QR and RA set.
- *
- * @param pkt: where to store the packet.
- * @param r: RCODE value to encode.
- * @param qinfo: if not NULL, the query is included.
- * @param qid: query ID to set in packet. network order.
- * @param qflags: original query flags (to copy RD and CD bits). host order.
- * @param edns: if not NULL, this is the query edns info,
- * and an edns reply is attached. Only attached if EDNS record fits reply.
- */
-void error_encode(struct sldns_buffer* pkt, int r, struct query_info* qinfo,
- uint16_t qid, uint16_t qflags, struct edns_data* edns);
-
-#endif /* UTIL_DATA_MSGENCODE_H */
diff --git a/external/unbound/util/data/msgparse.c b/external/unbound/util/data/msgparse.c
deleted file mode 100644
index 5381500e1..000000000
--- a/external/unbound/util/data/msgparse.c
+++ /dev/null
@@ -1,1093 +0,0 @@
-/*
- * util/data/msgparse.c - parse wireformat DNS messages.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/**
- * \file
- * Routines for message parsing a packet buffer to a descriptive structure.
- */
-#include "config.h"
-#include "util/data/msgparse.h"
-#include "util/data/msgreply.h"
-#include "util/data/dname.h"
-#include "util/data/packed_rrset.h"
-#include "util/storage/lookup3.h"
-#include "util/regional.h"
-#include "sldns/rrdef.h"
-#include "sldns/sbuffer.h"
-#include "sldns/parseutil.h"
-#include "sldns/wire2str.h"
-
-/** smart comparison of (compressed, valid) dnames from packet */
-static int
-smart_compare(sldns_buffer* pkt, uint8_t* dnow,
- uint8_t* dprfirst, uint8_t* dprlast)
-{
- if(LABEL_IS_PTR(*dnow)) {
- /* ptr points to a previous dname */
- uint8_t* p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1]));
- if( p == dprfirst || p == dprlast )
- return 0;
- /* prev dname is also a ptr, both ptrs are the same. */
- if(LABEL_IS_PTR(*dprlast) &&
- dprlast[0] == dnow[0] && dprlast[1] == dnow[1])
- return 0;
- }
- return dname_pkt_compare(pkt, dnow, dprlast);
-}
-
-/**
- * Allocate new rrset in region, fill with data.
- */
-static struct rrset_parse*
-new_rrset(struct msg_parse* msg, uint8_t* dname, size_t dnamelen,
- uint16_t type, uint16_t dclass, hashvalue_type hash,
- uint32_t rrset_flags, sldns_pkt_section section,
- struct regional* region)
-{
- struct rrset_parse* p = regional_alloc(region, sizeof(*p));
- if(!p) return NULL;
- p->rrset_bucket_next = msg->hashtable[hash & (PARSE_TABLE_SIZE-1)];
- msg->hashtable[hash & (PARSE_TABLE_SIZE-1)] = p;
- p->rrset_all_next = 0;
- if(msg->rrset_last)
- msg->rrset_last->rrset_all_next = p;
- else msg->rrset_first = p;
- msg->rrset_last = p;
- p->hash = hash;
- p->section = section;
- p->dname = dname;
- p->dname_len = dnamelen;
- p->type = type;
- p->rrset_class = dclass;
- p->flags = rrset_flags;
- p->rr_count = 0;
- p->size = 0;
- p->rr_first = 0;
- p->rr_last = 0;
- p->rrsig_count = 0;
- p->rrsig_first = 0;
- p->rrsig_last = 0;
- return p;
-}
-
-/** See if next rrset is nsec at zone apex */
-static int
-nsec_at_apex(sldns_buffer* pkt)
-{
- /* we are at ttl position in packet. */
- size_t pos = sldns_buffer_position(pkt);
- uint16_t rdatalen;
- if(sldns_buffer_remaining(pkt) < 7) /* ttl+len+root */
- return 0; /* eek! */
- sldns_buffer_skip(pkt, 4); /* ttl */;
- rdatalen = sldns_buffer_read_u16(pkt);
- if(sldns_buffer_remaining(pkt) < rdatalen) {
- sldns_buffer_set_position(pkt, pos);
- return 0; /* parse error happens later */
- }
- /* must validate the nsec next domain name format */
- if(pkt_dname_len(pkt) == 0) {
- sldns_buffer_set_position(pkt, pos);
- return 0; /* parse error */
- }
-
- /* see if SOA bit is set. */
- if(sldns_buffer_position(pkt) < pos+4+rdatalen) {
- /* nsec type bitmap contains items */
- uint8_t win, blen, bits;
- /* need: windownum, bitmap len, firstbyte */
- if(sldns_buffer_position(pkt)+3 > pos+4+rdatalen) {
- sldns_buffer_set_position(pkt, pos);
- return 0; /* malformed nsec */
- }
- win = sldns_buffer_read_u8(pkt);
- blen = sldns_buffer_read_u8(pkt);
- bits = sldns_buffer_read_u8(pkt);
- /* 0window always first window. bitlen >=1 or parse
- error really. bit 0x2 is SOA. */
- if(win == 0 && blen >= 1 && (bits & 0x02)) {
- sldns_buffer_set_position(pkt, pos);
- return 1;
- }
- }
-
- sldns_buffer_set_position(pkt, pos);
- return 0;
-}
-
-/** Calculate rrset flags */
-static uint32_t
-pkt_rrset_flags(sldns_buffer* pkt, uint16_t type, sldns_pkt_section sec)
-{
- uint32_t f = 0;
- if(type == LDNS_RR_TYPE_NSEC && nsec_at_apex(pkt)) {
- f |= PACKED_RRSET_NSEC_AT_APEX;
- } else if(type == LDNS_RR_TYPE_SOA && sec == LDNS_SECTION_AUTHORITY) {
- f |= PACKED_RRSET_SOA_NEG;
- }
- return f;
-}
-
-hashvalue_type
-pkt_hash_rrset(sldns_buffer* pkt, uint8_t* dname, uint16_t type,
- uint16_t dclass, uint32_t rrset_flags)
-{
- /* note this MUST be identical to rrset_key_hash in packed_rrset.c */
- /* this routine handles compressed names */
- hashvalue_type h = 0xab;
- h = dname_pkt_hash(pkt, dname, h);
- h = hashlittle(&type, sizeof(type), h); /* host order */
- h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */
- h = hashlittle(&rrset_flags, sizeof(uint32_t), h);
- return h;
-}
-
-/** create partial dname hash for rrset hash */
-static hashvalue_type
-pkt_hash_rrset_first(sldns_buffer* pkt, uint8_t* dname)
-{
- /* works together with pkt_hash_rrset_rest */
- /* note this MUST be identical to rrset_key_hash in packed_rrset.c */
- /* this routine handles compressed names */
- hashvalue_type h = 0xab;
- h = dname_pkt_hash(pkt, dname, h);
- return h;
-}
-
-/** create a rrset hash from a partial dname hash */
-static hashvalue_type
-pkt_hash_rrset_rest(hashvalue_type dname_h, uint16_t type, uint16_t dclass,
- uint32_t rrset_flags)
-{
- /* works together with pkt_hash_rrset_first */
- /* note this MUST be identical to rrset_key_hash in packed_rrset.c */
- hashvalue_type h;
- h = hashlittle(&type, sizeof(type), dname_h); /* host order */
- h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */
- h = hashlittle(&rrset_flags, sizeof(uint32_t), h);
- return h;
-}
-
-/** compare rrset_parse with data */
-static int
-rrset_parse_equals(struct rrset_parse* p, sldns_buffer* pkt, hashvalue_type h,
- uint32_t rrset_flags, uint8_t* dname, size_t dnamelen,
- uint16_t type, uint16_t dclass)
-{
- if(p->hash == h && p->dname_len == dnamelen && p->type == type &&
- p->rrset_class == dclass && p->flags == rrset_flags &&
- dname_pkt_compare(pkt, dname, p->dname) == 0)
- return 1;
- return 0;
-}
-
-
-struct rrset_parse*
-msgparse_hashtable_lookup(struct msg_parse* msg, sldns_buffer* pkt,
- hashvalue_type h, uint32_t rrset_flags, uint8_t* dname,
- size_t dnamelen, uint16_t type, uint16_t dclass)
-{
- struct rrset_parse* p = msg->hashtable[h & (PARSE_TABLE_SIZE-1)];
- while(p) {
- if(rrset_parse_equals(p, pkt, h, rrset_flags, dname, dnamelen,
- type, dclass))
- return p;
- p = p->rrset_bucket_next;
- }
- return NULL;
-}
-
-/** return type networkformat that rrsig in packet covers */
-static int
-pkt_rrsig_covered(sldns_buffer* pkt, uint8_t* here, uint16_t* type)
-{
- size_t pos = sldns_buffer_position(pkt);
- sldns_buffer_set_position(pkt, (size_t)(here-sldns_buffer_begin(pkt)));
- /* ttl + len + size of small rrsig(rootlabel, no signature) */
- if(sldns_buffer_remaining(pkt) < 4+2+19)
- return 0;
- sldns_buffer_skip(pkt, 4); /* ttl */
- if(sldns_buffer_read_u16(pkt) < 19) /* too short */ {
- sldns_buffer_set_position(pkt, pos);
- return 0;
- }
- *type = sldns_buffer_read_u16(pkt);
- sldns_buffer_set_position(pkt, pos);
- return 1;
-}
-
-/** true if covered type equals prevtype */
-static int
-pkt_rrsig_covered_equals(sldns_buffer* pkt, uint8_t* here, uint16_t type)
-{
- uint16_t t;
- if(pkt_rrsig_covered(pkt, here, &t) && t == type)
- return 1;
- return 0;
-}
-
-void
-msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset)
-{
- struct rrset_parse** p;
- p = &msg->hashtable[ rrset->hash & (PARSE_TABLE_SIZE-1) ];
- while(*p) {
- if(*p == rrset) {
- *p = rrset->rrset_bucket_next;
- return;
- }
- p = &( (*p)->rrset_bucket_next );
- }
-}
-
-/** change section of rrset from previous to current section */
-static void
-change_section(struct msg_parse* msg, struct rrset_parse* rrset,
- sldns_pkt_section section)
-{
- struct rrset_parse *p, *prev;
- /* remove from list */
- if(section == rrset->section)
- return;
- p = msg->rrset_first;
- prev = 0;
- while(p) {
- if(p == rrset) {
- if(prev) prev->rrset_all_next = p->rrset_all_next;
- else msg->rrset_first = p->rrset_all_next;
- if(msg->rrset_last == rrset)
- msg->rrset_last = prev;
- break;
- }
- prev = p;
- p = p->rrset_all_next;
- }
- /* remove from count */
- switch(rrset->section) {
- case LDNS_SECTION_ANSWER: msg->an_rrsets--; break;
- case LDNS_SECTION_AUTHORITY: msg->ns_rrsets--; break;
- case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets--; break;
- default: log_assert(0);
- }
- /* insert at end of list */
- rrset->rrset_all_next = 0;
- if(msg->rrset_last)
- msg->rrset_last->rrset_all_next = rrset;
- else msg->rrset_first = rrset;
- msg->rrset_last = rrset;
- /* up count of new section */
- switch(section) {
- case LDNS_SECTION_AUTHORITY: msg->ns_rrsets++; break;
- case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets++; break;
- default: log_assert(0);
- }
- rrset->section = section;
-}
-
-/** see if rrset of type RRSIG contains sig over given type */
-static int
-rrset_has_sigover(sldns_buffer* pkt, struct rrset_parse* rrset, uint16_t type,
- int* hasother)
-{
- int res = 0;
- struct rr_parse* rr = rrset->rr_first;
- log_assert( rrset->type == LDNS_RR_TYPE_RRSIG );
- while(rr) {
- if(pkt_rrsig_covered_equals(pkt, rr->ttl_data, type))
- res = 1;
- else *hasother = 1;
- rr = rr->next;
- }
- return res;
-}
-
-/** move rrsigs from sigset to dataset */
-static int
-moveover_rrsigs(sldns_buffer* pkt, struct regional* region,
- struct rrset_parse* sigset, struct rrset_parse* dataset, int duplicate)
-{
- struct rr_parse* sig = sigset->rr_first;
- struct rr_parse* prev = NULL;
- struct rr_parse* insert;
- struct rr_parse* nextsig;
- while(sig) {
- nextsig = sig->next;
- if(pkt_rrsig_covered_equals(pkt, sig->ttl_data,
- dataset->type)) {
- if(duplicate) {
- /* new */
- insert = (struct rr_parse*)regional_alloc(
- region, sizeof(struct rr_parse));
- if(!insert) return 0;
- insert->outside_packet = 0;
- insert->ttl_data = sig->ttl_data;
- insert->size = sig->size;
- /* prev not used */
- } else {
- /* remove from sigset */
- if(prev) prev->next = sig->next;
- else sigset->rr_first = sig->next;
- if(sigset->rr_last == sig)
- sigset->rr_last = prev;
- sigset->rr_count--;
- sigset->size -= sig->size;
- insert = sig;
- /* prev not changed */
- }
- /* add to dataset */
- dataset->rrsig_count++;
- insert->next = 0;
- if(dataset->rrsig_last)
- dataset->rrsig_last->next = insert;
- else dataset->rrsig_first = insert;
- dataset->rrsig_last = insert;
- dataset->size += insert->size;
- } else {
- prev = sig;
- }
- sig = nextsig;
- }
- return 1;
-}
-
-/** change an rrsig rrset for use as data rrset */
-static struct rrset_parse*
-change_rrsig_rrset(struct rrset_parse* sigset, struct msg_parse* msg,
- sldns_buffer* pkt, uint16_t datatype, uint32_t rrset_flags,
- int hasother, sldns_pkt_section section, struct regional* region)
-{
- struct rrset_parse* dataset = sigset;
- hashvalue_type hash = pkt_hash_rrset(pkt, sigset->dname, datatype,
- sigset->rrset_class, rrset_flags);
- log_assert( sigset->type == LDNS_RR_TYPE_RRSIG );
- log_assert( datatype != LDNS_RR_TYPE_RRSIG );
- if(hasother) {
- /* need to make new rrset to hold data type */
- dataset = new_rrset(msg, sigset->dname, sigset->dname_len,
- datatype, sigset->rrset_class, hash, rrset_flags,
- section, region);
- if(!dataset)
- return NULL;
- switch(section) {
- case LDNS_SECTION_ANSWER: msg->an_rrsets++; break;
- case LDNS_SECTION_AUTHORITY: msg->ns_rrsets++; break;
- case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets++; break;
- default: log_assert(0);
- }
- if(!moveover_rrsigs(pkt, region, sigset, dataset,
- msg->qtype == LDNS_RR_TYPE_RRSIG ||
- (msg->qtype == LDNS_RR_TYPE_ANY &&
- section != LDNS_SECTION_ANSWER) ))
- return NULL;
- return dataset;
- }
- /* changeover the type of the rrset to data set */
- msgparse_bucket_remove(msg, dataset);
- /* insert into new hash bucket */
- dataset->rrset_bucket_next = msg->hashtable[hash&(PARSE_TABLE_SIZE-1)];
- msg->hashtable[hash&(PARSE_TABLE_SIZE-1)] = dataset;
- dataset->hash = hash;
- /* use section of data item for result */
- change_section(msg, dataset, section);
- dataset->type = datatype;
- dataset->flags = rrset_flags;
- dataset->rrsig_count += dataset->rr_count;
- dataset->rr_count = 0;
- /* move sigs to end of siglist */
- if(dataset->rrsig_last)
- dataset->rrsig_last->next = dataset->rr_first;
- else dataset->rrsig_first = dataset->rr_first;
- dataset->rrsig_last = dataset->rr_last;
- dataset->rr_first = 0;
- dataset->rr_last = 0;
- return dataset;
-}
-
-/** Find rrset. If equal to previous it is fast. hash if not so.
- * @param msg: the message with hash table.
- * @param pkt: the packet in wireformat (needed for compression ptrs).
- * @param dname: pointer to start of dname (compressed) in packet.
- * @param dnamelen: uncompressed wirefmt length of dname.
- * @param type: type of current rr.
- * @param dclass: class of current rr.
- * @param hash: hash value is returned if the rrset could not be found.
- * @param rrset_flags: is returned if the rrset could not be found.
- * @param prev_dname_first: dname of last seen RR. First seen dname.
- * @param prev_dname_last: dname of last seen RR. Last seen dname.
- * @param prev_dnamelen: dname len of last seen RR.
- * @param prev_type: type of last seen RR.
- * @param prev_dclass: class of last seen RR.
- * @param rrset_prev: last seen RRset.
- * @param section: the current section in the packet.
- * @param region: used to allocate temporary parsing data.
- * @return 0 on out of memory.
- */
-static int
-find_rrset(struct msg_parse* msg, sldns_buffer* pkt, uint8_t* dname,
- size_t dnamelen, uint16_t type, uint16_t dclass, hashvalue_type* hash,
- uint32_t* rrset_flags,
- uint8_t** prev_dname_first, uint8_t** prev_dname_last,
- size_t* prev_dnamelen, uint16_t* prev_type,
- uint16_t* prev_dclass, struct rrset_parse** rrset_prev,
- sldns_pkt_section section, struct regional* region)
-{
- hashvalue_type dname_h = pkt_hash_rrset_first(pkt, dname);
- uint16_t covtype;
- if(*rrset_prev) {
- /* check if equal to previous item */
- if(type == *prev_type && dclass == *prev_dclass &&
- dnamelen == *prev_dnamelen &&
- smart_compare(pkt, dname, *prev_dname_first,
- *prev_dname_last) == 0 &&
- type != LDNS_RR_TYPE_RRSIG) {
- /* same as previous */
- *prev_dname_last = dname;
- return 1;
- }
- /* check if rrsig over previous item */
- if(type == LDNS_RR_TYPE_RRSIG && dclass == *prev_dclass &&
- pkt_rrsig_covered_equals(pkt, sldns_buffer_current(pkt),
- *prev_type) &&
- smart_compare(pkt, dname, *prev_dname_first,
- *prev_dname_last) == 0) {
- /* covers previous */
- *prev_dname_last = dname;
- return 1;
- }
- }
- /* find by hashing and lookup in hashtable */
- *rrset_flags = pkt_rrset_flags(pkt, type, section);
-
- /* if rrsig - try to lookup matching data set first */
- if(type == LDNS_RR_TYPE_RRSIG && pkt_rrsig_covered(pkt,
- sldns_buffer_current(pkt), &covtype)) {
- *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass,
- *rrset_flags);
- *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash,
- *rrset_flags, dname, dnamelen, covtype, dclass);
- if(!*rrset_prev && covtype == LDNS_RR_TYPE_NSEC) {
- /* if NSEC try with NSEC apex bit twiddled */
- *rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX;
- *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass,
- *rrset_flags);
- *rrset_prev = msgparse_hashtable_lookup(msg, pkt,
- *hash, *rrset_flags, dname, dnamelen, covtype,
- dclass);
- if(!*rrset_prev) /* untwiddle if not found */
- *rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX;
- }
- if(!*rrset_prev && covtype == LDNS_RR_TYPE_SOA) {
- /* if SOA try with SOA neg flag twiddled */
- *rrset_flags ^= PACKED_RRSET_SOA_NEG;
- *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass,
- *rrset_flags);
- *rrset_prev = msgparse_hashtable_lookup(msg, pkt,
- *hash, *rrset_flags, dname, dnamelen, covtype,
- dclass);
- if(!*rrset_prev) /* untwiddle if not found */
- *rrset_flags ^= PACKED_RRSET_SOA_NEG;
- }
- if(*rrset_prev) {
- *prev_dname_first = (*rrset_prev)->dname;
- *prev_dname_last = dname;
- *prev_dnamelen = dnamelen;
- *prev_type = covtype;
- *prev_dclass = dclass;
- return 1;
- }
- }
- if(type != LDNS_RR_TYPE_RRSIG) {
- int hasother = 0;
- /* find matching rrsig */
- *hash = pkt_hash_rrset_rest(dname_h, LDNS_RR_TYPE_RRSIG,
- dclass, 0);
- *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash,
- 0, dname, dnamelen, LDNS_RR_TYPE_RRSIG,
- dclass);
- if(*rrset_prev && rrset_has_sigover(pkt, *rrset_prev, type,
- &hasother)) {
- /* yes! */
- *prev_dname_first = (*rrset_prev)->dname;
- *prev_dname_last = dname;
- *prev_dnamelen = dnamelen;
- *prev_type = type;
- *prev_dclass = dclass;
- *rrset_prev = change_rrsig_rrset(*rrset_prev, msg,
- pkt, type, *rrset_flags, hasother, section,
- region);
- if(!*rrset_prev) return 0;
- return 1;
- }
- }
-
- *hash = pkt_hash_rrset_rest(dname_h, type, dclass, *rrset_flags);
- *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, *rrset_flags,
- dname, dnamelen, type, dclass);
- if(*rrset_prev)
- *prev_dname_first = (*rrset_prev)->dname;
- else *prev_dname_first = dname;
- *prev_dname_last = dname;
- *prev_dnamelen = dnamelen;
- *prev_type = type;
- *prev_dclass = dclass;
- return 1;
-}
-
-/**
- * Parse query section.
- * @param pkt: packet, position at call must be at start of query section.
- * at end position is after query section.
- * @param msg: store results here.
- * @return: 0 if OK, or rcode on error.
- */
-static int
-parse_query_section(sldns_buffer* pkt, struct msg_parse* msg)
-{
- if(msg->qdcount == 0)
- return 0;
- if(msg->qdcount > 1)
- return LDNS_RCODE_FORMERR;
- log_assert(msg->qdcount == 1);
- if(sldns_buffer_remaining(pkt) <= 0)
- return LDNS_RCODE_FORMERR;
- msg->qname = sldns_buffer_current(pkt);
- if((msg->qname_len = pkt_dname_len(pkt)) == 0)
- return LDNS_RCODE_FORMERR;
- if(sldns_buffer_remaining(pkt) < sizeof(uint16_t)*2)
- return LDNS_RCODE_FORMERR;
- msg->qtype = sldns_buffer_read_u16(pkt);
- msg->qclass = sldns_buffer_read_u16(pkt);
- return 0;
-}
-
-size_t
-get_rdf_size(sldns_rdf_type rdf)
-{
- switch(rdf) {
- case LDNS_RDF_TYPE_CLASS:
- case LDNS_RDF_TYPE_ALG:
- case LDNS_RDF_TYPE_INT8:
- return 1;
- break;
- case LDNS_RDF_TYPE_INT16:
- case LDNS_RDF_TYPE_TYPE:
- case LDNS_RDF_TYPE_CERT_ALG:
- return 2;
- break;
- case LDNS_RDF_TYPE_INT32:
- case LDNS_RDF_TYPE_TIME:
- case LDNS_RDF_TYPE_A:
- case LDNS_RDF_TYPE_PERIOD:
- return 4;
- break;
- case LDNS_RDF_TYPE_TSIGTIME:
- return 6;
- break;
- case LDNS_RDF_TYPE_AAAA:
- return 16;
- break;
- default:
- log_assert(0); /* add type above */
- /* only types that appear before a domain *
- * name are needed. rest is simply copied. */
- }
- return 0;
-}
-
-/** calculate the size of one rr */
-static int
-calc_size(sldns_buffer* pkt, uint16_t type, struct rr_parse* rr)
-{
- const sldns_rr_descriptor* desc;
- uint16_t pkt_len; /* length of rr inside the packet */
- rr->size = sizeof(uint16_t); /* the rdatalen */
- sldns_buffer_skip(pkt, 4); /* skip ttl */
- pkt_len = sldns_buffer_read_u16(pkt);
- if(sldns_buffer_remaining(pkt) < pkt_len)
- return 0;
- desc = sldns_rr_descript(type);
- if(pkt_len > 0 && desc && desc->_dname_count > 0) {
- int count = (int)desc->_dname_count;
- int rdf = 0;
- size_t len;
- size_t oldpos;
- /* skip first part. */
- while(pkt_len > 0 && count) {
- switch(desc->_wireformat[rdf]) {
- case LDNS_RDF_TYPE_DNAME:
- /* decompress every domain name */
- oldpos = sldns_buffer_position(pkt);
- if((len = pkt_dname_len(pkt)) == 0)
- return 0; /* malformed dname */
- if(sldns_buffer_position(pkt)-oldpos > pkt_len)
- return 0; /* dname exceeds rdata */
- pkt_len -= sldns_buffer_position(pkt)-oldpos;
- rr->size += len;
- count--;
- len = 0;
- break;
- case LDNS_RDF_TYPE_STR:
- if(pkt_len < 1) {
- /* NOTREACHED, due to 'while(>0)' */
- return 0; /* len byte exceeds rdata */
- }
- len = sldns_buffer_current(pkt)[0] + 1;
- break;
- default:
- len = get_rdf_size(desc->_wireformat[rdf]);
- }
- if(len) {
- if(pkt_len < len)
- return 0; /* exceeds rdata */
- pkt_len -= len;
- sldns_buffer_skip(pkt, (ssize_t)len);
- rr->size += len;
- }
- rdf++;
- }
- }
- /* remaining rdata */
- rr->size += pkt_len;
- sldns_buffer_skip(pkt, (ssize_t)pkt_len);
- return 1;
-}
-
-/** skip rr ttl and rdata */
-static int
-skip_ttl_rdata(sldns_buffer* pkt)
-{
- uint16_t rdatalen;
- if(sldns_buffer_remaining(pkt) < 6) /* ttl + rdatalen */
- return 0;
- sldns_buffer_skip(pkt, 4); /* ttl */
- rdatalen = sldns_buffer_read_u16(pkt);
- if(sldns_buffer_remaining(pkt) < rdatalen)
- return 0;
- sldns_buffer_skip(pkt, (ssize_t)rdatalen);
- return 1;
-}
-
-/** see if RRSIG is a duplicate of another */
-static int
-sig_is_double(sldns_buffer* pkt, struct rrset_parse* rrset, uint8_t* ttldata)
-{
- uint16_t rlen, siglen;
- size_t pos = sldns_buffer_position(pkt);
- struct rr_parse* sig;
- if(sldns_buffer_remaining(pkt) < 6)
- return 0;
- sldns_buffer_skip(pkt, 4); /* ttl */
- rlen = sldns_buffer_read_u16(pkt);
- if(sldns_buffer_remaining(pkt) < rlen) {
- sldns_buffer_set_position(pkt, pos);
- return 0;
- }
- sldns_buffer_set_position(pkt, pos);
-
- sig = rrset->rrsig_first;
- while(sig) {
- /* check if rdatalen is same */
- memmove(&siglen, sig->ttl_data+4, sizeof(siglen));
- siglen = ntohs(siglen);
- /* checks if data in packet is exactly the same, this means
- * also dname in rdata is the same, but rrsig is not allowed
- * to have compressed dnames anyway. If it is compressed anyway
- * it will lead to duplicate rrs for qtype=RRSIG. (or ANY).
- *
- * Cannot use sig->size because size of the other one is not
- * calculated yet.
- */
- if(siglen == rlen) {
- if(siglen>0 && memcmp(sig->ttl_data+6, ttldata+6,
- siglen) == 0) {
- /* same! */
- return 1;
- }
- }
- sig = sig->next;
- }
- return 0;
-}
-
-/** Add rr (from packet here) to rrset, skips rr */
-static int
-add_rr_to_rrset(struct rrset_parse* rrset, sldns_buffer* pkt,
- struct msg_parse* msg, struct regional* region,
- sldns_pkt_section section, uint16_t type)
-{
- struct rr_parse* rr;
- /* check section of rrset. */
- if(rrset->section != section && type != LDNS_RR_TYPE_RRSIG &&
- rrset->type != LDNS_RR_TYPE_RRSIG) {
- /* silently drop it - we drop the last part, since
- * trust in rr data depends on the section it is in.
- * the less trustworthy part is discarded.
- * also the last part is more likely to be incomplete.
- * RFC 2181: must put RRset only once in response. */
- /*
- verbose(VERB_QUERY, "Packet contains rrset data in "
- "multiple sections, dropped last part.");
- log_buf(VERB_QUERY, "packet was", pkt);
- */
- /* forwards */
- if(!skip_ttl_rdata(pkt))
- return LDNS_RCODE_FORMERR;
- return 0;
- }
-
- if( (msg->qtype == LDNS_RR_TYPE_RRSIG ||
- msg->qtype == LDNS_RR_TYPE_ANY)
- && sig_is_double(pkt, rrset, sldns_buffer_current(pkt))) {
- if(!skip_ttl_rdata(pkt))
- return LDNS_RCODE_FORMERR;
- return 0;
- }
-
- /* create rr */
- if(!(rr = (struct rr_parse*)regional_alloc(region, sizeof(*rr))))
- return LDNS_RCODE_SERVFAIL;
- rr->outside_packet = 0;
- rr->ttl_data = sldns_buffer_current(pkt);
- rr->next = 0;
- if(type == LDNS_RR_TYPE_RRSIG && rrset->type != LDNS_RR_TYPE_RRSIG) {
- if(rrset->rrsig_last)
- rrset->rrsig_last->next = rr;
- else rrset->rrsig_first = rr;
- rrset->rrsig_last = rr;
- rrset->rrsig_count++;
- } else {
- if(rrset->rr_last)
- rrset->rr_last->next = rr;
- else rrset->rr_first = rr;
- rrset->rr_last = rr;
- rrset->rr_count++;
- }
-
- /* calc decompressed size */
- if(!calc_size(pkt, type, rr))
- return LDNS_RCODE_FORMERR;
- rrset->size += rr->size;
-
- return 0;
-}
-
-/**
- * Parse packet RR section, for answer, authority and additional sections.
- * @param pkt: packet, position at call must be at start of section.
- * at end position is after section.
- * @param msg: store results here.
- * @param region: how to alloc results.
- * @param section: section enum.
- * @param num_rrs: how many rrs are in the section.
- * @param num_rrsets: returns number of rrsets in the section.
- * @return: 0 if OK, or rcode on error.
- */
-static int
-parse_section(sldns_buffer* pkt, struct msg_parse* msg,
- struct regional* region, sldns_pkt_section section,
- uint16_t num_rrs, size_t* num_rrsets)
-{
- uint16_t i;
- uint8_t* dname, *prev_dname_f = NULL, *prev_dname_l = NULL;
- size_t dnamelen, prev_dnamelen = 0;
- uint16_t type, prev_type = 0;
- uint16_t dclass, prev_dclass = 0;
- uint32_t rrset_flags = 0;
- hashvalue_type hash = 0;
- struct rrset_parse* rrset = NULL;
- int r;
-
- if(num_rrs == 0)
- return 0;
- if(sldns_buffer_remaining(pkt) <= 0)
- return LDNS_RCODE_FORMERR;
- for(i=0; i<num_rrs; i++) {
- /* parse this RR. */
- dname = sldns_buffer_current(pkt);
- if((dnamelen = pkt_dname_len(pkt)) == 0)
- return LDNS_RCODE_FORMERR;
- if(sldns_buffer_remaining(pkt) < 10) /* type, class, ttl, len */
- return LDNS_RCODE_FORMERR;
- type = sldns_buffer_read_u16(pkt);
- sldns_buffer_read(pkt, &dclass, sizeof(dclass));
-
- if(0) { /* debug show what is being parsed. */
- if(type == LDNS_RR_TYPE_RRSIG) {
- uint16_t t;
- if(pkt_rrsig_covered(pkt,
- sldns_buffer_current(pkt), &t))
- fprintf(stderr, "parse of %s(%d) [%s(%d)]",
- sldns_rr_descript(type)?
- sldns_rr_descript(type)->_name: "??",
- (int)type,
- sldns_rr_descript(t)?
- sldns_rr_descript(t)->_name: "??",
- (int)t);
- } else
- fprintf(stderr, "parse of %s(%d)",
- sldns_rr_descript(type)?
- sldns_rr_descript(type)->_name: "??",
- (int)type);
- fprintf(stderr, " %s(%d) ",
- sldns_lookup_by_id(sldns_rr_classes,
- (int)ntohs(dclass))?sldns_lookup_by_id(
- sldns_rr_classes, (int)ntohs(dclass))->name:
- "??", (int)ntohs(dclass));
- dname_print(stderr, pkt, dname);
- fprintf(stderr, "\n");
- }
-
- /* see if it is part of an existing RR set */
- if(!find_rrset(msg, pkt, dname, dnamelen, type, dclass, &hash,
- &rrset_flags, &prev_dname_f, &prev_dname_l,
- &prev_dnamelen, &prev_type, &prev_dclass, &rrset,
- section, region))
- return LDNS_RCODE_SERVFAIL;
- if(!rrset) {
- /* it is a new RR set. hash&flags already calculated.*/
- (*num_rrsets)++;
- rrset = new_rrset(msg, dname, dnamelen, type, dclass,
- hash, rrset_flags, section, region);
- if(!rrset)
- return LDNS_RCODE_SERVFAIL;
- }
- else if(0) {
- fprintf(stderr, "is part of existing: ");
- dname_print(stderr, pkt, rrset->dname);
- fprintf(stderr, " type %s(%d)\n",
- sldns_rr_descript(rrset->type)?
- sldns_rr_descript(rrset->type)->_name: "??",
- (int)rrset->type);
- }
- /* add to rrset. */
- if((r=add_rr_to_rrset(rrset, pkt, msg, region, section,
- type)) != 0)
- return r;
- }
- return 0;
-}
-
-int
-parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region)
-{
- int ret;
- if(sldns_buffer_remaining(pkt) < LDNS_HEADER_SIZE)
- return LDNS_RCODE_FORMERR;
- /* read the header */
- sldns_buffer_read(pkt, &msg->id, sizeof(uint16_t));
- msg->flags = sldns_buffer_read_u16(pkt);
- msg->qdcount = sldns_buffer_read_u16(pkt);
- msg->ancount = sldns_buffer_read_u16(pkt);
- msg->nscount = sldns_buffer_read_u16(pkt);
- msg->arcount = sldns_buffer_read_u16(pkt);
- if(msg->qdcount > 1)
- return LDNS_RCODE_FORMERR;
- if((ret = parse_query_section(pkt, msg)) != 0)
- return ret;
- if((ret = parse_section(pkt, msg, region, LDNS_SECTION_ANSWER,
- msg->ancount, &msg->an_rrsets)) != 0)
- return ret;
- if((ret = parse_section(pkt, msg, region, LDNS_SECTION_AUTHORITY,
- msg->nscount, &msg->ns_rrsets)) != 0)
- return ret;
- if(sldns_buffer_remaining(pkt) == 0 && msg->arcount == 1) {
- /* BIND accepts leniently that an EDNS record is missing.
- * so, we do too. */
- } else if((ret = parse_section(pkt, msg, region,
- LDNS_SECTION_ADDITIONAL, msg->arcount, &msg->ar_rrsets)) != 0)
- return ret;
- /* if(sldns_buffer_remaining(pkt) > 0) { */
- /* there is spurious data at end of packet. ignore */
- /* } */
- msg->rrset_count = msg->an_rrsets + msg->ns_rrsets + msg->ar_rrsets;
- return 0;
-}
-
-/** parse EDNS options from EDNS wireformat rdata */
-static int
-parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len,
- struct edns_data* edns, struct regional* region)
-{
- /* while still more options, and have code+len to read */
- /* ignores partial content (i.e. rdata len 3) */
- while(rdata_len >= 4) {
- uint16_t opt_code = sldns_read_uint16(rdata_ptr);
- uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
- rdata_ptr += 4;
- rdata_len -= 4;
- if(opt_len > rdata_len)
- break; /* option code partial */
- if(!edns_opt_append(edns, region, opt_code, opt_len,
- rdata_ptr)) {
- log_err("out of memory");
- return 0;
- }
- rdata_ptr += opt_len;
- rdata_len -= opt_len;
- }
- return 1;
-}
-
-int
-parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
- struct regional* region)
-{
- struct rrset_parse* rrset = msg->rrset_first;
- struct rrset_parse* prev = 0;
- struct rrset_parse* found = 0;
- struct rrset_parse* found_prev = 0;
- size_t rdata_len;
- uint8_t* rdata_ptr;
- /* since the class encodes the UDP size, we cannot use hash table to
- * find the EDNS OPT record. Scan the packet. */
- while(rrset) {
- if(rrset->type == LDNS_RR_TYPE_OPT) {
- /* only one OPT RR allowed. */
- if(found) return LDNS_RCODE_FORMERR;
- /* found it! */
- found_prev = prev;
- found = rrset;
- }
- prev = rrset;
- rrset = rrset->rrset_all_next;
- }
- if(!found) {
- memset(edns, 0, sizeof(*edns));
- edns->udp_size = 512;
- return 0;
- }
- /* check the found RRset */
- /* most lenient check possible. ignore dname, use last opt */
- if(found->section != LDNS_SECTION_ADDITIONAL)
- return LDNS_RCODE_FORMERR;
- if(found->rr_count == 0)
- return LDNS_RCODE_FORMERR;
- if(0) { /* strict checking of dname and RRcount */
- if(found->dname_len != 1 || !found->dname
- || found->dname[0] != 0) return LDNS_RCODE_FORMERR;
- if(found->rr_count != 1) return LDNS_RCODE_FORMERR;
- }
- log_assert(found->rr_first && found->rr_last);
-
- /* remove from packet */
- if(found_prev) found_prev->rrset_all_next = found->rrset_all_next;
- else msg->rrset_first = found->rrset_all_next;
- if(found == msg->rrset_last)
- msg->rrset_last = found_prev;
- msg->arcount --;
- msg->ar_rrsets --;
- msg->rrset_count --;
-
- /* take the data ! */
- edns->edns_present = 1;
- edns->ext_rcode = found->rr_last->ttl_data[0];
- edns->edns_version = found->rr_last->ttl_data[1];
- edns->bits = sldns_read_uint16(&found->rr_last->ttl_data[2]);
- edns->udp_size = ntohs(found->rrset_class);
- edns->opt_list = NULL;
-
- /* take the options */
- rdata_len = found->rr_first->size;
- rdata_ptr = found->rr_first->ttl_data+6;
- if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
- return 0;
-
- /* ignore rrsigs */
-
- return 0;
-}
-
-int
-parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
- struct regional* region)
-{
- size_t rdata_len;
- uint8_t* rdata_ptr;
- log_assert(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) == 1);
- log_assert(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0);
- log_assert(LDNS_NSCOUNT(sldns_buffer_begin(pkt)) == 0);
- /* check edns section is present */
- if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) > 1) {
- return LDNS_RCODE_FORMERR;
- }
- if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) == 0) {
- memset(edns, 0, sizeof(*edns));
- edns->udp_size = 512;
- return 0;
- }
- /* domain name must be the root of length 1. */
- if(pkt_dname_len(pkt) != 1)
- return LDNS_RCODE_FORMERR;
- if(sldns_buffer_remaining(pkt) < 10) /* type, class, ttl, rdatalen */
- return LDNS_RCODE_FORMERR;
- if(sldns_buffer_read_u16(pkt) != LDNS_RR_TYPE_OPT)
- return LDNS_RCODE_FORMERR;
- edns->edns_present = 1;
- edns->udp_size = sldns_buffer_read_u16(pkt); /* class is udp size */
- edns->ext_rcode = sldns_buffer_read_u8(pkt); /* ttl used for bits */
- edns->edns_version = sldns_buffer_read_u8(pkt);
- edns->bits = sldns_buffer_read_u16(pkt);
- edns->opt_list = NULL;
-
- /* take the options */
- rdata_len = sldns_buffer_read_u16(pkt);
- if(sldns_buffer_remaining(pkt) < rdata_len)
- return LDNS_RCODE_FORMERR;
- rdata_ptr = sldns_buffer_current(pkt);
- if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
- return LDNS_RCODE_SERVFAIL;
-
- /* ignore rrsigs */
-
- return 0;
-}
-
-void
-log_edns_opt_list(enum verbosity_value level, const char* info_str,
- struct edns_option* list)
-{
- if(verbosity >= level && list) {
- char str[128], *s;
- size_t slen;
- verbose(level, "%s", info_str);
- while(list) {
- s = str;
- slen = sizeof(str);
- (void)sldns_wire2str_edns_option_print(&s, &slen, list->opt_code,
- list->opt_data, list->opt_len);
- verbose(level, " %s", str);
- list = list->next;
- }
- }
-}
diff --git a/external/unbound/util/data/msgparse.h b/external/unbound/util/data/msgparse.h
deleted file mode 100644
index e21f8504e..000000000
--- a/external/unbound/util/data/msgparse.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * util/data/msgparse.h - parse wireformat DNS messages.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/**
- * \file
- * Contains message parsing data structures.
- * These point back into the packet buffer.
- *
- * During parsing RRSIGS are put together with the rrsets they (claim to) sign.
- * This process works as follows:
- * o if RRSIG follows the data rrset, it is added to the rrset rrsig list.
- * o if no matching data rrset is found, the RRSIG becomes a new rrset.
- * o If the data rrset later follows the RRSIG
- * o See if the RRSIG rrset contains multiple types, and needs to
- * have the rrsig(s) for that data type split off.
- * o Put the data rr as data type in the rrset and rrsig in list.
- * o RRSIGs are allowed to move to a different section. The section of
- * the data item is used for the final rrset.
- * o multiple signatures over an RRset are possible.
- *
- * For queries of qtype=RRSIG, some special handling is needed, to avoid
- * splitting the RRSIG in the answer section.
- * o duplicate, not split, RRSIGs from the answer section, if qtype=RRSIG.
- * o check for doubles in the rrsig list when adding an RRSIG to data,
- * so that a data rrset is signed by RRSIGs with different rdata.
- * when qtype=RRSIG.
- * This will move the RRSIG from the answer section to sign the data further
- * in the packet (if possible). If then after that, more RRSIGs are found
- * that sign the data as well, doubles are removed.
- */
-
-#ifndef UTIL_DATA_MSGPARSE_H
-#define UTIL_DATA_MSGPARSE_H
-#include "util/storage/lruhash.h"
-#include "sldns/pkthdr.h"
-#include "sldns/rrdef.h"
-struct sldns_buffer;
-struct rrset_parse;
-struct rr_parse;
-struct regional;
-struct edns_option;
-
-/** number of buckets in parse rrset hash table. Must be power of 2. */
-#define PARSE_TABLE_SIZE 32
-/** Maximum TTL that is allowed. */
-extern time_t MAX_TTL;
-/** Minimum TTL that is allowed. */
-extern time_t MIN_TTL;
-/** Maximum Negative TTL that is allowed */
-extern time_t MAX_NEG_TTL;
-/** Negative cache time (for entries without any RRs.) */
-#define NORR_TTL 5 /* seconds */
-
-/**
- * Data stored in scratch pad memory during parsing.
- * Stores the data that will enter into the msgreply and packet result.
- */
-struct msg_parse {
- /** id from message, network format. */
- uint16_t id;
- /** flags from message, host format. */
- uint16_t flags;
- /** count of RRs, host format */
- uint16_t qdcount;
- /** count of RRs, host format */
- uint16_t ancount;
- /** count of RRs, host format */
- uint16_t nscount;
- /** count of RRs, host format */
- uint16_t arcount;
- /** count of RRsets per section. */
- size_t an_rrsets;
- /** count of RRsets per section. */
- size_t ns_rrsets;
- /** count of RRsets per section. */
- size_t ar_rrsets;
- /** total number of rrsets found. */
- size_t rrset_count;
-
- /** query dname (pointer to start location in packet, NULL if none */
- uint8_t* qname;
- /** length of query dname in octets, 0 if none */
- size_t qname_len;
- /** query type, host order. 0 if qdcount=0 */
- uint16_t qtype;
- /** query class, host order. 0 if qdcount=0 */
- uint16_t qclass;
-
- /**
- * Hash table array used during parsing to lookup rrset types.
- * Based on name, type, class. Same hash value as in rrset cache.
- */
- struct rrset_parse* hashtable[PARSE_TABLE_SIZE];
-
- /** linked list of rrsets that have been found (in order). */
- struct rrset_parse* rrset_first;
- /** last element of rrset list. */
- struct rrset_parse* rrset_last;
-};
-
-/**
- * Data stored for an rrset during parsing.
- */
-struct rrset_parse {
- /** next in hash bucket */
- struct rrset_parse* rrset_bucket_next;
- /** next in list of all rrsets */
- struct rrset_parse* rrset_all_next;
- /** hash value of rrset */
- hashvalue_type hash;
- /** which section was it found in: one of
- * LDNS_SECTION_ANSWER, LDNS_SECTION_AUTHORITY, LDNS_SECTION_ADDITIONAL
- */
- sldns_pkt_section section;
- /** start of (possibly compressed) dname in packet */
- uint8_t* dname;
- /** length of the dname uncompressed wireformat */
- size_t dname_len;
- /** type, host order. */
- uint16_t type;
- /** class, network order. var name so that it is not a c++ keyword. */
- uint16_t rrset_class;
- /** the flags for the rrset, like for packedrrset */
- uint32_t flags;
- /** number of RRs in the rr list */
- size_t rr_count;
- /** sum of RR rdata sizes */
- size_t size;
- /** linked list of RRs in this rrset. */
- struct rr_parse* rr_first;
- /** last in list of RRs in this rrset. */
- struct rr_parse* rr_last;
- /** number of RRSIGs over this rrset. */
- size_t rrsig_count;
- /** linked list of RRsig RRs over this rrset. */
- struct rr_parse* rrsig_first;
- /** last in list of RRSIG RRs over this rrset. */
- struct rr_parse* rrsig_last;
-};
-
-/**
- * Data stored for an RR during parsing.
- */
-struct rr_parse {
- /**
- * Pointer to the RR. Points to start of TTL value in the packet.
- * Rdata length and rdata follow it.
- * its dname, type and class are the same and stored for the rrset.
- */
- uint8_t* ttl_data;
- /** true if ttl_data is not part of the packet, but elsewhere in mem.
- * Set for generated CNAMEs for DNAMEs. */
- int outside_packet;
- /** the length of the rdata if allocated (with no dname compression)*/
- size_t size;
- /** next in list of RRs. */
- struct rr_parse* next;
-};
-
-/** Check if label length is first octet of a compression pointer, pass u8. */
-#define LABEL_IS_PTR(x) ( ((x)&0xc0) == 0xc0 )
-/** Calculate destination offset of a compression pointer. pass first and
- * second octets of the compression pointer. */
-#define PTR_OFFSET(x, y) ( ((x)&0x3f)<<8 | (y) )
-/** create a compression pointer to the given offset. */
-#define PTR_CREATE(offset) ((uint16_t)(0xc000 | (offset)))
-
-/** error codes, extended with EDNS, so > 15. */
-#define EDNS_RCODE_BADVERS 16 /** bad EDNS version */
-/** largest valid compression offset */
-#define PTR_MAX_OFFSET 0x3fff
-
-/**
- * EDNS data storage
- * rdata is parsed in a list (has accessor functions). allocated in a
- * region.
- */
-struct edns_data {
- /** if EDNS OPT record was present */
- int edns_present;
- /** Extended RCODE */
- uint8_t ext_rcode;
- /** The EDNS version number */
- uint8_t edns_version;
- /** the EDNS bits field from ttl (host order): Z */
- uint16_t bits;
- /** UDP reassembly size. */
- uint16_t udp_size;
- /** rdata element list, or NULL if none */
- struct edns_option* opt_list;
-};
-
-/**
- * EDNS option
- */
-struct edns_option {
- /** next item in list */
- struct edns_option* next;
- /** type of this edns option */
- uint16_t opt_code;
- /** length of this edns option (cannot exceed uint16 in encoding) */
- size_t opt_len;
- /** data of this edns option; allocated in region, or NULL if len=0 */
- uint8_t* opt_data;
-};
-
-/**
- * Obtain size in the packet of an rr type, that is before dname type.
- * Do TYPE_DNAME, and type STR, yourself. Gives size for most regular types.
- * @param rdf: the rdf type from the descriptor.
- * @return: size in octets. 0 on failure.
- */
-size_t get_rdf_size(sldns_rdf_type rdf);
-
-/**
- * Parse the packet.
- * @param pkt: packet, position at call must be at start of packet.
- * at end position is after packet.
- * @param msg: where to store results.
- * @param region: how to alloc results.
- * @return: 0 if OK, or rcode on error.
- */
-int parse_packet(struct sldns_buffer* pkt, struct msg_parse* msg,
- struct regional* region);
-
-/**
- * After parsing the packet, extract EDNS data from packet.
- * If not present this is noted in the data structure.
- * If a parse error happens, an error code is returned.
- *
- * Quirks:
- * o ignores OPT rdata.
- * o ignores OPT owner name.
- * o ignores extra OPT records, except the last one in the packet.
- *
- * @param msg: parsed message structure. Modified on exit, if EDNS was present
- * it is removed from the additional section.
- * @param edns: the edns data is stored here. Does not have to be initialised.
- * @param region: region to alloc results in (edns option contents)
- * @return: 0 on success. or an RCODE on an error.
- * RCODE formerr if OPT in wrong section, and so on.
- */
-int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
- struct regional* region);
-
-/**
- * If EDNS data follows a query section, extract it and initialize edns struct.
- * @param pkt: the packet. position at start must be right after the query
- * section. At end, right after EDNS data or no movement if failed.
- * @param edns: the edns data allocated by the caller. Does not have to be
- * initialised.
- * @param region: region to alloc results in (edns option contents)
- * @return: 0 on success, or an RCODE on error.
- * RCODE formerr if OPT is badly formatted and so on.
- */
-int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns,
- struct regional* region);
-
-/**
- * Calculate hash value for rrset in packet.
- * @param pkt: the packet.
- * @param dname: pointer to uncompressed dname, or compressed dname in packet.
- * @param type: rrset type in host order.
- * @param dclass: rrset class in network order.
- * @param rrset_flags: rrset flags (same as packed_rrset flags).
- * @return hash value
- */
-hashvalue_type pkt_hash_rrset(struct sldns_buffer* pkt, uint8_t* dname,
- uint16_t type, uint16_t dclass, uint32_t rrset_flags);
-
-/**
- * Lookup in msg hashtable to find a rrset.
- * @param msg: with the hashtable.
- * @param pkt: packet for compressed names.
- * @param h: hash value
- * @param rrset_flags: flags of rrset sought for.
- * @param dname: name of rrset sought for.
- * @param dnamelen: len of dname.
- * @param type: rrset type, host order.
- * @param dclass: rrset class, network order.
- * @return NULL or the rrset_parse if found.
- */
-struct rrset_parse* msgparse_hashtable_lookup(struct msg_parse* msg,
- struct sldns_buffer* pkt, hashvalue_type h, uint32_t rrset_flags,
- uint8_t* dname, size_t dnamelen, uint16_t type, uint16_t dclass);
-
-/**
- * Remove rrset from hash table.
- * @param msg: with hashtable.
- * @param rrset: with hash value and id info.
- */
-void msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset);
-
-/**
- * Log the edns options in the edns option list.
- * @param level: the verbosity level.
- * @param info_str: the informational string to be printed before the options.
- * @param list: the edns option list.
- */
-void log_edns_opt_list(enum verbosity_value level, const char* info_str,
- struct edns_option* list);
-
-#endif /* UTIL_DATA_MSGPARSE_H */
diff --git a/external/unbound/util/data/msgreply.c b/external/unbound/util/data/msgreply.c
deleted file mode 100644
index 2ce898d7f..000000000
--- a/external/unbound/util/data/msgreply.c
+++ /dev/null
@@ -1,1206 +0,0 @@
-/*
- * util/data/msgreply.c - store message and reply data.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains a data structure to store a message and its reply.
- */
-
-#include "config.h"
-#include "util/data/msgreply.h"
-#include "util/storage/lookup3.h"
-#include "util/log.h"
-#include "util/alloc.h"
-#include "util/netevent.h"
-#include "util/net_help.h"
-#include "util/data/dname.h"
-#include "util/regional.h"
-#include "util/data/msgparse.h"
-#include "util/data/msgencode.h"
-#include "sldns/sbuffer.h"
-#include "sldns/wire2str.h"
-#include "util/module.h"
-#include "util/fptr_wlist.h"
-
-/** MAX TTL default for messages and rrsets */
-time_t MAX_TTL = 3600 * 24 * 10; /* ten days */
-/** MIN TTL default for messages and rrsets */
-time_t MIN_TTL = 0;
-/** MAX Negative TTL, for SOA records in authority section */
-time_t MAX_NEG_TTL = 3600; /* one hour */
-
-/** allocate qinfo, return 0 on error */
-static int
-parse_create_qinfo(sldns_buffer* pkt, struct msg_parse* msg,
- struct query_info* qinf, struct regional* region)
-{
- if(msg->qname) {
- if(region)
- qinf->qname = (uint8_t*)regional_alloc(region,
- msg->qname_len);
- else qinf->qname = (uint8_t*)malloc(msg->qname_len);
- if(!qinf->qname) return 0;
- dname_pkt_copy(pkt, qinf->qname, msg->qname);
- } else qinf->qname = 0;
- qinf->qname_len = msg->qname_len;
- qinf->qtype = msg->qtype;
- qinf->qclass = msg->qclass;
- qinf->local_alias = NULL;
- return 1;
-}
-
-/** constructor for replyinfo */
-struct reply_info*
-construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd,
- time_t ttl, time_t prettl, size_t an, size_t ns, size_t ar,
- size_t total, enum sec_status sec)
-{
- struct reply_info* rep;
- /* rrset_count-1 because the first ref is part of the struct. */
- size_t s = sizeof(struct reply_info) - sizeof(struct rrset_ref) +
- sizeof(struct ub_packed_rrset_key*) * total;
- if(total >= RR_COUNT_MAX) return NULL; /* sanity check on numRRS*/
- if(region)
- rep = (struct reply_info*)regional_alloc(region, s);
- else rep = (struct reply_info*)malloc(s +
- sizeof(struct rrset_ref) * (total));
- if(!rep)
- return NULL;
- rep->flags = flags;
- rep->qdcount = qd;
- rep->ttl = ttl;
- rep->prefetch_ttl = prettl;
- rep->an_numrrsets = an;
- rep->ns_numrrsets = ns;
- rep->ar_numrrsets = ar;
- rep->rrset_count = total;
- rep->security = sec;
- rep->authoritative = 0;
- /* array starts after the refs */
- if(region)
- rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[0]);
- else rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[total]);
- /* zero the arrays to assist cleanup in case of malloc failure */
- memset( rep->rrsets, 0, sizeof(struct ub_packed_rrset_key*) * total);
- if(!region)
- memset( &rep->ref[0], 0, sizeof(struct rrset_ref) * total);
- return rep;
-}
-
-/** allocate replyinfo, return 0 on error */
-static int
-parse_create_repinfo(struct msg_parse* msg, struct reply_info** rep,
- struct regional* region)
-{
- *rep = construct_reply_info_base(region, msg->flags, msg->qdcount, 0,
- 0, msg->an_rrsets, msg->ns_rrsets, msg->ar_rrsets,
- msg->rrset_count, sec_status_unchecked);
- if(!*rep)
- return 0;
- return 1;
-}
-
-int
-reply_info_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc,
- struct regional* region)
-{
- size_t i;
- for(i=0; i<rep->rrset_count; i++) {
- if(region) {
- rep->rrsets[i] = (struct ub_packed_rrset_key*)
- regional_alloc(region,
- sizeof(struct ub_packed_rrset_key));
- if(rep->rrsets[i]) {
- memset(rep->rrsets[i], 0,
- sizeof(struct ub_packed_rrset_key));
- rep->rrsets[i]->entry.key = rep->rrsets[i];
- }
- }
- else rep->rrsets[i] = alloc_special_obtain(alloc);
- if(!rep->rrsets[i])
- return 0;
- rep->rrsets[i]->entry.data = NULL;
- }
- return 1;
-}
-
-/** find the minimumttl in the rdata of SOA record */
-static time_t
-soa_find_minttl(struct rr_parse* rr)
-{
- uint16_t rlen = sldns_read_uint16(rr->ttl_data+4);
- if(rlen < 20)
- return 0; /* rdata too small for SOA (dname, dname, 5*32bit) */
- /* minimum TTL is the last 32bit value in the rdata of the record */
- /* at position ttl_data + 4(ttl) + 2(rdatalen) + rdatalen - 4(timeval)*/
- return (time_t)sldns_read_uint32(rr->ttl_data+6+rlen-4);
-}
-
-/** do the rdata copy */
-static int
-rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to,
- struct rr_parse* rr, time_t* rr_ttl, uint16_t type,
- sldns_pkt_section section)
-{
- uint16_t pkt_len;
- const sldns_rr_descriptor* desc;
-
- *rr_ttl = sldns_read_uint32(rr->ttl_data);
- /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */
- if(*rr_ttl & 0x80000000U)
- *rr_ttl = 0;
- if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) {
- /* negative response. see if TTL of SOA record larger than the
- * minimum-ttl in the rdata of the SOA record */
- if(*rr_ttl > soa_find_minttl(rr))
- *rr_ttl = soa_find_minttl(rr);
- if(*rr_ttl > MAX_NEG_TTL)
- *rr_ttl = MAX_NEG_TTL;
- }
- if(*rr_ttl < MIN_TTL)
- *rr_ttl = MIN_TTL;
- if(*rr_ttl < data->ttl)
- data->ttl = *rr_ttl;
-
- if(rr->outside_packet) {
- /* uncompressed already, only needs copy */
- memmove(to, rr->ttl_data+sizeof(uint32_t), rr->size);
- return 1;
- }
-
- sldns_buffer_set_position(pkt, (size_t)
- (rr->ttl_data - sldns_buffer_begin(pkt) + sizeof(uint32_t)));
- /* insert decompressed size into rdata len stored in memory */
- /* -2 because rdatalen bytes are not included. */
- pkt_len = htons(rr->size - 2);
- memmove(to, &pkt_len, sizeof(uint16_t));
- to += 2;
- /* read packet rdata len */
- pkt_len = sldns_buffer_read_u16(pkt);
- if(sldns_buffer_remaining(pkt) < pkt_len)
- return 0;
- desc = sldns_rr_descript(type);
- if(pkt_len > 0 && desc && desc->_dname_count > 0) {
- int count = (int)desc->_dname_count;
- int rdf = 0;
- size_t len;
- size_t oldpos;
- /* decompress dnames. */
- while(pkt_len > 0 && count) {
- switch(desc->_wireformat[rdf]) {
- case LDNS_RDF_TYPE_DNAME:
- oldpos = sldns_buffer_position(pkt);
- dname_pkt_copy(pkt, to,
- sldns_buffer_current(pkt));
- to += pkt_dname_len(pkt);
- pkt_len -= sldns_buffer_position(pkt)-oldpos;
- count--;
- len = 0;
- break;
- case LDNS_RDF_TYPE_STR:
- len = sldns_buffer_current(pkt)[0] + 1;
- break;
- default:
- len = get_rdf_size(desc->_wireformat[rdf]);
- break;
- }
- if(len) {
- memmove(to, sldns_buffer_current(pkt), len);
- to += len;
- sldns_buffer_skip(pkt, (ssize_t)len);
- log_assert(len <= pkt_len);
- pkt_len -= len;
- }
- rdf++;
- }
- }
- /* copy remaining rdata */
- if(pkt_len > 0)
- memmove(to, sldns_buffer_current(pkt), pkt_len);
-
- return 1;
-}
-
-/** copy over the data into packed rrset */
-static int
-parse_rr_copy(sldns_buffer* pkt, struct rrset_parse* pset,
- struct packed_rrset_data* data)
-{
- size_t i;
- struct rr_parse* rr = pset->rr_first;
- uint8_t* nextrdata;
- size_t total = pset->rr_count + pset->rrsig_count;
- data->ttl = MAX_TTL;
- data->count = pset->rr_count;
- data->rrsig_count = pset->rrsig_count;
- data->trust = rrset_trust_none;
- data->security = sec_status_unchecked;
- /* layout: struct - rr_len - rr_data - rr_ttl - rdata - rrsig */
- data->rr_len = (size_t*)((uint8_t*)data +
- sizeof(struct packed_rrset_data));
- data->rr_data = (uint8_t**)&(data->rr_len[total]);
- data->rr_ttl = (time_t*)&(data->rr_data[total]);
- nextrdata = (uint8_t*)&(data->rr_ttl[total]);
- for(i=0; i<data->count; i++) {
- data->rr_len[i] = rr->size;
- data->rr_data[i] = nextrdata;
- nextrdata += rr->size;
- if(!rdata_copy(pkt, data, data->rr_data[i], rr,
- &data->rr_ttl[i], pset->type, pset->section))
- return 0;
- rr = rr->next;
- }
- /* if rrsig, its rdata is at nextrdata */
- rr = pset->rrsig_first;
- for(i=data->count; i<total; i++) {
- data->rr_len[i] = rr->size;
- data->rr_data[i] = nextrdata;
- nextrdata += rr->size;
- if(!rdata_copy(pkt, data, data->rr_data[i], rr,
- &data->rr_ttl[i], LDNS_RR_TYPE_RRSIG, pset->section))
- return 0;
- rr = rr->next;
- }
- return 1;
-}
-
-/** create rrset return 0 on failure */
-static int
-parse_create_rrset(sldns_buffer* pkt, struct rrset_parse* pset,
- struct packed_rrset_data** data, struct regional* region)
-{
- /* allocate */
- size_t s;
- if(pset->rr_count > RR_COUNT_MAX || pset->rrsig_count > RR_COUNT_MAX ||
- pset->size > RR_COUNT_MAX)
- return 0; /* protect against integer overflow */
- s = sizeof(struct packed_rrset_data) +
- (pset->rr_count + pset->rrsig_count) *
- (sizeof(size_t)+sizeof(uint8_t*)+sizeof(time_t)) +
- pset->size;
- if(region)
- *data = regional_alloc(region, s);
- else *data = malloc(s);
- if(!*data)
- return 0;
- /* copy & decompress */
- if(!parse_rr_copy(pkt, pset, *data)) {
- if(!region) free(*data);
- return 0;
- }
- return 1;
-}
-
-/** get trust value for rrset */
-static enum rrset_trust
-get_rrset_trust(struct msg_parse* msg, struct rrset_parse* rrset)
-{
- uint16_t AA = msg->flags & BIT_AA;
- if(rrset->section == LDNS_SECTION_ANSWER) {
- if(AA) {
- /* RFC2181 says remainder of CNAME chain is nonauth*/
- if(msg->rrset_first &&
- msg->rrset_first->section==LDNS_SECTION_ANSWER
- && msg->rrset_first->type==LDNS_RR_TYPE_CNAME){
- if(rrset == msg->rrset_first)
- return rrset_trust_ans_AA;
- else return rrset_trust_ans_noAA;
- }
- if(msg->rrset_first &&
- msg->rrset_first->section==LDNS_SECTION_ANSWER
- && msg->rrset_first->type==LDNS_RR_TYPE_DNAME){
- if(rrset == msg->rrset_first ||
- rrset == msg->rrset_first->rrset_all_next)
- return rrset_trust_ans_AA;
- else return rrset_trust_ans_noAA;
- }
- return rrset_trust_ans_AA;
- }
- else return rrset_trust_ans_noAA;
- } else if(rrset->section == LDNS_SECTION_AUTHORITY) {
- if(AA) return rrset_trust_auth_AA;
- else return rrset_trust_auth_noAA;
- } else {
- /* addit section */
- if(AA) return rrset_trust_add_AA;
- else return rrset_trust_add_noAA;
- }
- /* NOTREACHED */
- return rrset_trust_none;
-}
-
-int
-parse_copy_decompress_rrset(sldns_buffer* pkt, struct msg_parse* msg,
- struct rrset_parse *pset, struct regional* region,
- struct ub_packed_rrset_key* pk)
-{
- struct packed_rrset_data* data;
- pk->rk.flags = pset->flags;
- pk->rk.dname_len = pset->dname_len;
- if(region)
- pk->rk.dname = (uint8_t*)regional_alloc(
- region, pset->dname_len);
- else pk->rk.dname =
- (uint8_t*)malloc(pset->dname_len);
- if(!pk->rk.dname)
- return 0;
- /** copy & decompress dname */
- dname_pkt_copy(pkt, pk->rk.dname, pset->dname);
- /** copy over type and class */
- pk->rk.type = htons(pset->type);
- pk->rk.rrset_class = pset->rrset_class;
- /** read data part. */
- if(!parse_create_rrset(pkt, pset, &data, region))
- return 0;
- pk->entry.data = (void*)data;
- pk->entry.key = (void*)pk;
- pk->entry.hash = pset->hash;
- data->trust = get_rrset_trust(msg, pset);
- return 1;
-}
-
-/**
- * Copy and decompress rrs
- * @param pkt: the packet for compression pointer resolution.
- * @param msg: the parsed message
- * @param rep: reply info to put rrs into.
- * @param region: if not NULL, used for allocation.
- * @return 0 on failure.
- */
-static int
-parse_copy_decompress(sldns_buffer* pkt, struct msg_parse* msg,
- struct reply_info* rep, struct regional* region)
-{
- size_t i;
- struct rrset_parse *pset = msg->rrset_first;
- struct packed_rrset_data* data;
- log_assert(rep);
- rep->ttl = MAX_TTL;
- rep->security = sec_status_unchecked;
- if(rep->rrset_count == 0)
- rep->ttl = NORR_TTL;
-
- for(i=0; i<rep->rrset_count; i++) {
- if(!parse_copy_decompress_rrset(pkt, msg, pset, region,
- rep->rrsets[i]))
- return 0;
- data = (struct packed_rrset_data*)rep->rrsets[i]->entry.data;
- if(data->ttl < rep->ttl)
- rep->ttl = data->ttl;
-
- pset = pset->rrset_all_next;
- }
- rep->prefetch_ttl = PREFETCH_TTL_CALC(rep->ttl);
- return 1;
-}
-
-int
-parse_create_msg(sldns_buffer* pkt, struct msg_parse* msg,
- struct alloc_cache* alloc, struct query_info* qinf,
- struct reply_info** rep, struct regional* region)
-{
- log_assert(pkt && msg);
- if(!parse_create_qinfo(pkt, msg, qinf, region))
- return 0;
- if(!parse_create_repinfo(msg, rep, region))
- return 0;
- if(!reply_info_alloc_rrset_keys(*rep, alloc, region))
- return 0;
- if(!parse_copy_decompress(pkt, msg, *rep, region))
- return 0;
- return 1;
-}
-
-int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc,
- struct query_info* qinf, struct reply_info** rep,
- struct regional* region, struct edns_data* edns)
-{
- /* use scratch pad region-allocator during parsing. */
- struct msg_parse* msg;
- int ret;
-
- qinf->qname = NULL;
- qinf->local_alias = NULL;
- *rep = NULL;
- if(!(msg = regional_alloc(region, sizeof(*msg)))) {
- return LDNS_RCODE_SERVFAIL;
- }
- memset(msg, 0, sizeof(*msg));
-
- sldns_buffer_set_position(pkt, 0);
- if((ret = parse_packet(pkt, msg, region)) != 0) {
- return ret;
- }
- if((ret = parse_extract_edns(msg, edns, region)) != 0)
- return ret;
-
- /* parse OK, allocate return structures */
- /* this also performs dname decompression */
- if(!parse_create_msg(pkt, msg, alloc, qinf, rep, NULL)) {
- query_info_clear(qinf);
- reply_info_parsedelete(*rep, alloc);
- *rep = NULL;
- return LDNS_RCODE_SERVFAIL;
- }
- return 0;
-}
-
-/** helper compare function to sort in lock order */
-static int
-reply_info_sortref_cmp(const void* a, const void* b)
-{
- struct rrset_ref* x = (struct rrset_ref*)a;
- struct rrset_ref* y = (struct rrset_ref*)b;
- if(x->key < y->key) return -1;
- if(x->key > y->key) return 1;
- return 0;
-}
-
-void
-reply_info_sortref(struct reply_info* rep)
-{
- qsort(&rep->ref[0], rep->rrset_count, sizeof(struct rrset_ref),
- reply_info_sortref_cmp);
-}
-
-void
-reply_info_set_ttls(struct reply_info* rep, time_t timenow)
-{
- size_t i, j;
- rep->ttl += timenow;
- rep->prefetch_ttl += timenow;
- for(i=0; i<rep->rrset_count; i++) {
- struct packed_rrset_data* data = (struct packed_rrset_data*)
- rep->ref[i].key->entry.data;
- if(i>0 && rep->ref[i].key == rep->ref[i-1].key)
- continue;
- data->ttl += timenow;
- for(j=0; j<data->count + data->rrsig_count; j++) {
- data->rr_ttl[j] += timenow;
- }
- }
-}
-
-void
-reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc)
-{
- size_t i;
- if(!rep)
- return;
- /* no need to lock, since not shared in hashtables. */
- for(i=0; i<rep->rrset_count; i++) {
- ub_packed_rrset_parsedelete(rep->rrsets[i], alloc);
- }
- free(rep);
-}
-
-int
-query_info_parse(struct query_info* m, sldns_buffer* query)
-{
- uint8_t* q = sldns_buffer_begin(query);
- /* minimum size: header + \0 + qtype + qclass */
- if(sldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5)
- return 0;
- if(LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY ||
- LDNS_QDCOUNT(q) != 1 || sldns_buffer_position(query) != 0)
- return 0;
- sldns_buffer_skip(query, LDNS_HEADER_SIZE);
- m->qname = sldns_buffer_current(query);
- if((m->qname_len = query_dname_len(query)) == 0)
- return 0; /* parse error */
- if(sldns_buffer_remaining(query) < 4)
- return 0; /* need qtype, qclass */
- m->qtype = sldns_buffer_read_u16(query);
- m->qclass = sldns_buffer_read_u16(query);
- m->local_alias = NULL;
- return 1;
-}
-
-/** tiny subroutine for msgreply_compare */
-#define COMPARE_IT(x, y) \
- if( (x) < (y) ) return -1; \
- else if( (x) > (y) ) return +1; \
- log_assert( (x) == (y) );
-
-int
-query_info_compare(void* m1, void* m2)
-{
- struct query_info* msg1 = (struct query_info*)m1;
- struct query_info* msg2 = (struct query_info*)m2;
- int mc;
- /* from most different to least different for speed */
- COMPARE_IT(msg1->qtype, msg2->qtype);
- if((mc = query_dname_compare(msg1->qname, msg2->qname)) != 0)
- return mc;
- log_assert(msg1->qname_len == msg2->qname_len);
- COMPARE_IT(msg1->qclass, msg2->qclass);
- return 0;
-#undef COMPARE_IT
-}
-
-void
-query_info_clear(struct query_info* m)
-{
- free(m->qname);
- m->qname = NULL;
-}
-
-size_t
-msgreply_sizefunc(void* k, void* d)
-{
- struct msgreply_entry* q = (struct msgreply_entry*)k;
- struct reply_info* r = (struct reply_info*)d;
- size_t s = sizeof(struct msgreply_entry) + sizeof(struct reply_info)
- + q->key.qname_len + lock_get_mem(&q->entry.lock)
- - sizeof(struct rrset_ref);
- s += r->rrset_count * sizeof(struct rrset_ref);
- s += r->rrset_count * sizeof(struct ub_packed_rrset_key*);
- return s;
-}
-
-void
-query_entry_delete(void *k, void* ATTR_UNUSED(arg))
-{
- struct msgreply_entry* q = (struct msgreply_entry*)k;
- lock_rw_destroy(&q->entry.lock);
- query_info_clear(&q->key);
- free(q);
-}
-
-void
-reply_info_delete(void* d, void* ATTR_UNUSED(arg))
-{
- struct reply_info* r = (struct reply_info*)d;
- free(r);
-}
-
-hashvalue_type
-query_info_hash(struct query_info *q, uint16_t flags)
-{
- hashvalue_type h = 0xab;
- h = hashlittle(&q->qtype, sizeof(q->qtype), h);
- if(q->qtype == LDNS_RR_TYPE_AAAA && (flags&BIT_CD))
- h++;
- h = hashlittle(&q->qclass, sizeof(q->qclass), h);
- h = dname_query_hash(q->qname, h);
- return h;
-}
-
-struct msgreply_entry*
-query_info_entrysetup(struct query_info* q, struct reply_info* r,
- hashvalue_type h)
-{
- struct msgreply_entry* e = (struct msgreply_entry*)malloc(
- sizeof(struct msgreply_entry));
- if(!e) return NULL;
- memcpy(&e->key, q, sizeof(*q));
- e->entry.hash = h;
- e->entry.key = e;
- e->entry.data = r;
- lock_rw_init(&e->entry.lock);
- lock_protect(&e->entry.lock, &e->key, sizeof(e->key));
- lock_protect(&e->entry.lock, &e->entry.hash, sizeof(e->entry.hash) +
- sizeof(e->entry.key) + sizeof(e->entry.data));
- lock_protect(&e->entry.lock, e->key.qname, e->key.qname_len);
- q->qname = NULL;
- return e;
-}
-
-/** copy rrsets from replyinfo to dest replyinfo */
-static int
-repinfo_copy_rrsets(struct reply_info* dest, struct reply_info* from,
- struct regional* region)
-{
- size_t i, s;
- struct packed_rrset_data* fd, *dd;
- struct ub_packed_rrset_key* fk, *dk;
- for(i=0; i<dest->rrset_count; i++) {
- fk = from->rrsets[i];
- dk = dest->rrsets[i];
- fd = (struct packed_rrset_data*)fk->entry.data;
- dk->entry.hash = fk->entry.hash;
- dk->rk = fk->rk;
- if(region) {
- dk->id = fk->id;
- dk->rk.dname = (uint8_t*)regional_alloc_init(region,
- fk->rk.dname, fk->rk.dname_len);
- } else
- dk->rk.dname = (uint8_t*)memdup(fk->rk.dname,
- fk->rk.dname_len);
- if(!dk->rk.dname)
- return 0;
- s = packed_rrset_sizeof(fd);
- if(region)
- dd = (struct packed_rrset_data*)regional_alloc_init(
- region, fd, s);
- else dd = (struct packed_rrset_data*)memdup(fd, s);
- if(!dd)
- return 0;
- packed_rrset_ptr_fixup(dd);
- dk->entry.data = (void*)dd;
- }
- return 1;
-}
-
-struct reply_info*
-reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc,
- struct regional* region)
-{
- struct reply_info* cp;
- cp = construct_reply_info_base(region, rep->flags, rep->qdcount,
- rep->ttl, rep->prefetch_ttl, rep->an_numrrsets,
- rep->ns_numrrsets, rep->ar_numrrsets, rep->rrset_count,
- rep->security);
- if(!cp)
- return NULL;
- /* allocate ub_key structures special or not */
- if(!reply_info_alloc_rrset_keys(cp, alloc, region)) {
- if(!region)
- reply_info_parsedelete(cp, alloc);
- return NULL;
- }
- if(!repinfo_copy_rrsets(cp, rep, region)) {
- if(!region)
- reply_info_parsedelete(cp, alloc);
- return NULL;
- }
- return cp;
-}
-
-uint8_t*
-reply_find_final_cname_target(struct query_info* qinfo, struct reply_info* rep)
-{
- uint8_t* sname = qinfo->qname;
- size_t snamelen = qinfo->qname_len;
- size_t i;
- for(i=0; i<rep->an_numrrsets; i++) {
- struct ub_packed_rrset_key* s = rep->rrsets[i];
- /* follow CNAME chain (if any) */
- if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
- ntohs(s->rk.rrset_class) == qinfo->qclass &&
- snamelen == s->rk.dname_len &&
- query_dname_compare(sname, s->rk.dname) == 0) {
- get_cname_target(s, &sname, &snamelen);
- }
- }
- if(sname != qinfo->qname)
- return sname;
- return NULL;
-}
-
-struct ub_packed_rrset_key*
-reply_find_answer_rrset(struct query_info* qinfo, struct reply_info* rep)
-{
- uint8_t* sname = qinfo->qname;
- size_t snamelen = qinfo->qname_len;
- size_t i;
- for(i=0; i<rep->an_numrrsets; i++) {
- struct ub_packed_rrset_key* s = rep->rrsets[i];
- /* first match type, for query of qtype cname */
- if(ntohs(s->rk.type) == qinfo->qtype &&
- ntohs(s->rk.rrset_class) == qinfo->qclass &&
- snamelen == s->rk.dname_len &&
- query_dname_compare(sname, s->rk.dname) == 0) {
- return s;
- }
- /* follow CNAME chain (if any) */
- if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
- ntohs(s->rk.rrset_class) == qinfo->qclass &&
- snamelen == s->rk.dname_len &&
- query_dname_compare(sname, s->rk.dname) == 0) {
- get_cname_target(s, &sname, &snamelen);
- }
- }
- return NULL;
-}
-
-struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep,
- uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass)
-{
- size_t i;
- for(i=0; i<rep->an_numrrsets; i++) {
- struct ub_packed_rrset_key* s = rep->rrsets[i];
- if(ntohs(s->rk.type) == type &&
- ntohs(s->rk.rrset_class) == dclass &&
- namelen == s->rk.dname_len &&
- query_dname_compare(name, s->rk.dname) == 0) {
- return s;
- }
- }
- return NULL;
-}
-
-struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep,
- uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass)
-{
- size_t i;
- for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) {
- struct ub_packed_rrset_key* s = rep->rrsets[i];
- if(ntohs(s->rk.type) == type &&
- ntohs(s->rk.rrset_class) == dclass &&
- namelen == s->rk.dname_len &&
- query_dname_compare(name, s->rk.dname) == 0) {
- return s;
- }
- }
- return NULL;
-}
-
-struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep,
- uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass)
-{
- size_t i;
- for(i=0; i<rep->rrset_count; i++) {
- struct ub_packed_rrset_key* s = rep->rrsets[i];
- if(ntohs(s->rk.type) == type &&
- ntohs(s->rk.rrset_class) == dclass &&
- namelen == s->rk.dname_len &&
- query_dname_compare(name, s->rk.dname) == 0) {
- return s;
- }
- }
- return NULL;
-}
-
-void
-log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
-{
- /* not particularly fast but flexible, make wireformat and print */
- sldns_buffer* buf = sldns_buffer_new(65535);
- struct regional* region = regional_create();
- if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0,
- region, 65535, 1)) {
- log_info("%s: log_dns_msg: out of memory", str);
- } else {
- char* s = sldns_wire2str_pkt(sldns_buffer_begin(buf),
- sldns_buffer_limit(buf));
- if(!s) {
- log_info("%s: log_dns_msg: ldns tostr failed", str);
- } else {
- log_info("%s %s", str, s);
- }
- free(s);
- }
- sldns_buffer_free(buf);
- regional_destroy(region);
-}
-
-void
-log_reply_info(enum verbosity_value v, struct query_info *qinf,
- struct sockaddr_storage *addr, socklen_t addrlen, struct timeval dur,
- int cached, struct sldns_buffer *rmsg)
-{
- char qname_buf[LDNS_MAX_DOMAINLEN+1];
- char clientip_buf[128];
- char rcode_buf[16];
- char type_buf[16];
- char class_buf[16];
- size_t pktlen;
- uint16_t rcode = FLAGS_GET_RCODE(sldns_buffer_read_u16_at(rmsg, 2));
-
- if(verbosity < v)
- return;
-
- sldns_wire2str_rcode_buf((int)rcode, rcode_buf, sizeof(rcode_buf));
- addr_to_str(addr, addrlen, clientip_buf, sizeof(clientip_buf));
- if(rcode == LDNS_RCODE_FORMERR)
- {
- log_info("%s - - - %s - - - ", clientip_buf, rcode_buf);
- } else {
- dname_str(qinf->qname, qname_buf);
- pktlen = sldns_buffer_limit(rmsg);
- sldns_wire2str_type_buf(qinf->qtype, type_buf, sizeof(type_buf));
- sldns_wire2str_class_buf(qinf->qclass, class_buf, sizeof(class_buf));
- log_info("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d",
- clientip_buf, qname_buf, type_buf, class_buf,
- rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec, cached, (int)pktlen);
- }
-}
-
-void
-log_query_info(enum verbosity_value v, const char* str,
- struct query_info* qinf)
-{
- log_nametypeclass(v, str, qinf->qname, qinf->qtype, qinf->qclass);
-}
-
-int
-reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep)
-{
- /* check only answer section rrs for matching cname chain.
- * the cache may return changed rdata, but owner names are untouched.*/
- size_t i;
- uint8_t* sname = qinfo->qname;
- size_t snamelen = qinfo->qname_len;
- for(i=0; i<rep->an_numrrsets; i++) {
- uint16_t t = ntohs(rep->rrsets[i]->rk.type);
- if(t == LDNS_RR_TYPE_DNAME)
- continue; /* skip dnames; note TTL 0 not cached */
- /* verify that owner matches current sname */
- if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){
- /* cname chain broken */
- return 0;
- }
- /* if this is a cname; move on */
- if(t == LDNS_RR_TYPE_CNAME) {
- get_cname_target(rep->rrsets[i], &sname, &snamelen);
- }
- }
- return 1;
-}
-
-int
-reply_all_rrsets_secure(struct reply_info* rep)
-{
- size_t i;
- for(i=0; i<rep->rrset_count; i++) {
- if( ((struct packed_rrset_data*)rep->rrsets[i]->entry.data)
- ->security != sec_status_secure )
- return 0;
- }
- return 1;
-}
-
-int edns_opt_append(struct edns_data* edns, struct regional* region,
- uint16_t code, size_t len, uint8_t* data)
-{
- struct edns_option** prevp;
- struct edns_option* opt;
-
- /* allocate new element */
- opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
- if(!opt)
- return 0;
- opt->next = NULL;
- opt->opt_code = code;
- opt->opt_len = len;
- opt->opt_data = NULL;
- if(len > 0) {
- opt->opt_data = regional_alloc_init(region, data, len);
- if(!opt->opt_data)
- return 0;
- }
-
- /* append at end of list */
- prevp = &edns->opt_list;
- while(*prevp != NULL)
- prevp = &((*prevp)->next);
- *prevp = opt;
- return 1;
-}
-
-int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
- uint8_t* data, struct regional* region)
-{
- struct edns_option** prevp;
- struct edns_option* opt;
-
- /* allocate new element */
- opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
- if(!opt)
- return 0;
- opt->next = NULL;
- opt->opt_code = code;
- opt->opt_len = len;
- opt->opt_data = NULL;
- if(len > 0) {
- opt->opt_data = regional_alloc_init(region, data, len);
- if(!opt->opt_data)
- return 0;
- }
-
- /* append at end of list */
- prevp = list;
- while(*prevp != NULL) {
- prevp = &((*prevp)->next);
- }
- *prevp = opt;
- return 1;
-}
-
-int edns_opt_list_remove(struct edns_option** list, uint16_t code)
-{
- /* The list should already be allocated in a region. Freeing the
- * allocated space in a region is not possible. We just unlink the
- * required elements and they will be freed together with the region. */
-
- struct edns_option* prev;
- struct edns_option* curr;
- if(!list || !(*list)) return 0;
-
- /* Unlink and repoint if the element(s) are first in list */
- while(list && *list && (*list)->opt_code == code) {
- *list = (*list)->next;
- }
-
- if(!list || !(*list)) return 1;
- /* Unlink elements and reattach the list */
- prev = *list;
- curr = (*list)->next;
- while(curr != NULL) {
- if(curr->opt_code == code) {
- prev->next = curr->next;
- curr = curr->next;
- } else {
- prev = curr;
- curr = curr->next;
- }
- }
- return 1;
-}
-
-static int inplace_cb_reply_call_generic(
- struct inplace_cb* callback_list, enum inplace_cb_list_type type,
- struct query_info* qinfo, struct module_qstate* qstate,
- struct reply_info* rep, int rcode, struct edns_data* edns,
- struct regional* region)
-{
- struct inplace_cb* cb;
- struct edns_option* opt_list_out = NULL;
- if(qstate)
- opt_list_out = qstate->edns_opts_front_out;
- for(cb=callback_list; cb; cb=cb->next) {
- fptr_ok(fptr_whitelist_inplace_cb_reply_generic(
- (inplace_cb_reply_func_type*)cb->cb, type));
- (void)(*(inplace_cb_reply_func_type*)cb->cb)(qinfo, qstate, rep,
- rcode, edns, &opt_list_out, region, cb->id, cb->cb_arg);
- }
- edns->opt_list = opt_list_out;
- return 1;
-}
-
-int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
- struct module_qstate* qstate, struct reply_info* rep, int rcode,
- struct edns_data* edns, struct regional* region)
-{
- return inplace_cb_reply_call_generic(
- env->inplace_cb_lists[inplace_cb_reply], inplace_cb_reply, qinfo,
- qstate, rep, rcode, edns, region);
-}
-
-int inplace_cb_reply_cache_call(struct module_env* env,
- struct query_info* qinfo, struct module_qstate* qstate,
- struct reply_info* rep, int rcode, struct edns_data* edns,
- struct regional* region)
-{
- return inplace_cb_reply_call_generic(
- env->inplace_cb_lists[inplace_cb_reply_cache], inplace_cb_reply_cache,
- qinfo, qstate, rep, rcode, edns, region);
-}
-
-int inplace_cb_reply_local_call(struct module_env* env,
- struct query_info* qinfo, struct module_qstate* qstate,
- struct reply_info* rep, int rcode, struct edns_data* edns,
- struct regional* region)
-{
- return inplace_cb_reply_call_generic(
- env->inplace_cb_lists[inplace_cb_reply_local], inplace_cb_reply_local,
- qinfo, qstate, rep, rcode, edns, region);
-}
-
-int inplace_cb_reply_servfail_call(struct module_env* env,
- struct query_info* qinfo, struct module_qstate* qstate,
- struct reply_info* rep, int rcode, struct edns_data* edns,
- struct regional* region)
-{
- /* We are going to servfail. Remove any potential edns options. */
- if(qstate)
- qstate->edns_opts_front_out = NULL;
- return inplace_cb_reply_call_generic(
- env->inplace_cb_lists[inplace_cb_reply_servfail],
- inplace_cb_reply_servfail, qinfo, qstate, rep, rcode, edns, region);
-}
-
-int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,
- uint16_t flags, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
- struct regional* region)
-{
- struct inplace_cb* cb = env->inplace_cb_lists[inplace_cb_query];
- for(; cb; cb=cb->next) {
- fptr_ok(fptr_whitelist_inplace_cb_query(
- (inplace_cb_query_func_type*)cb->cb));
- (void)(*(inplace_cb_query_func_type*)cb->cb)(qinfo, flags,
- qstate, addr, addrlen, zone, zonelen, region,
- cb->id, cb->cb_arg);
- }
- return 1;
-}
-
-int inplace_cb_edns_back_parsed_call(struct module_env* env,
- struct module_qstate* qstate)
-{
- struct inplace_cb* cb =
- env->inplace_cb_lists[inplace_cb_edns_back_parsed];
- for(; cb; cb=cb->next) {
- fptr_ok(fptr_whitelist_inplace_cb_edns_back_parsed(
- (inplace_cb_edns_back_parsed_func_type*)cb->cb));
- (void)(*(inplace_cb_edns_back_parsed_func_type*)cb->cb)(qstate,
- cb->id, cb->cb_arg);
- }
- return 1;
-}
-
-int inplace_cb_query_response_call(struct module_env* env,
- struct module_qstate* qstate, struct dns_msg* response) {
- struct inplace_cb* cb =
- env->inplace_cb_lists[inplace_cb_query_response];
- for(; cb; cb=cb->next) {
- fptr_ok(fptr_whitelist_inplace_cb_query_response(
- (inplace_cb_query_response_func_type*)cb->cb));
- (void)(*(inplace_cb_query_response_func_type*)cb->cb)(qstate,
- response, cb->id, cb->cb_arg);
- }
- return 1;
-}
-
-struct edns_option* edns_opt_copy_region(struct edns_option* list,
- struct regional* region)
-{
- struct edns_option* result = NULL, *cur = NULL, *s;
- while(list) {
- /* copy edns option structure */
- s = regional_alloc_init(region, list, sizeof(*list));
- if(!s) return NULL;
- s->next = NULL;
-
- /* copy option data */
- if(s->opt_data) {
- s->opt_data = regional_alloc_init(region, s->opt_data,
- s->opt_len);
- if(!s->opt_data)
- return NULL;
- }
-
- /* link into list */
- if(cur)
- cur->next = s;
- else result = s;
- cur = s;
-
- /* examine next element */
- list = list->next;
- }
- return result;
-}
-
-int edns_opt_compare(struct edns_option* p, struct edns_option* q)
-{
- if(!p && !q) return 0;
- if(!p) return -1;
- if(!q) return 1;
- log_assert(p && q);
- if(p->opt_code != q->opt_code)
- return (int)q->opt_code - (int)p->opt_code;
- if(p->opt_len != q->opt_len)
- return (int)q->opt_len - (int)p->opt_len;
- if(p->opt_len != 0)
- return memcmp(p->opt_data, q->opt_data, p->opt_len);
- return 0;
-}
-
-int edns_opt_list_compare(struct edns_option* p, struct edns_option* q)
-{
- int r;
- while(p && q) {
- r = edns_opt_compare(p, q);
- if(r != 0)
- return r;
- p = p->next;
- q = q->next;
- }
- if(p || q) {
- /* uneven length lists */
- if(p) return 1;
- if(q) return -1;
- }
- return 0;
-}
-
-void edns_opt_list_free(struct edns_option* list)
-{
- struct edns_option* n;
- while(list) {
- free(list->opt_data);
- n = list->next;
- free(list);
- list = n;
- }
-}
-
-struct edns_option* edns_opt_copy_alloc(struct edns_option* list)
-{
- struct edns_option* result = NULL, *cur = NULL, *s;
- while(list) {
- /* copy edns option structure */
- s = memdup(list, sizeof(*list));
- if(!s) {
- edns_opt_list_free(result);
- return NULL;
- }
- s->next = NULL;
-
- /* copy option data */
- if(s->opt_data) {
- s->opt_data = memdup(s->opt_data, s->opt_len);
- if(!s->opt_data) {
- free(s);
- edns_opt_list_free(result);
- return NULL;
- }
- }
-
- /* link into list */
- if(cur)
- cur->next = s;
- else result = s;
- cur = s;
-
- /* examine next element */
- list = list->next;
- }
- return result;
-}
-
-struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code)
-{
- struct edns_option* p;
- for(p=list; p; p=p->next) {
- if(p->opt_code == code)
- return p;
- }
- return NULL;
-}
diff --git a/external/unbound/util/data/msgreply.h b/external/unbound/util/data/msgreply.h
deleted file mode 100644
index acbdd3deb..000000000
--- a/external/unbound/util/data/msgreply.h
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * util/data/msgreply.h - store message and reply data.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains a data structure to store a message and its reply.
- */
-
-#ifndef UTIL_DATA_MSGREPLY_H
-#define UTIL_DATA_MSGREPLY_H
-#include "util/storage/lruhash.h"
-#include "util/data/packed_rrset.h"
-struct sldns_buffer;
-struct comm_reply;
-struct alloc_cache;
-struct iovec;
-struct regional;
-struct edns_data;
-struct edns_option;
-struct inplace_cb;
-struct module_qstate;
-struct module_env;
-struct msg_parse;
-struct rrset_parse;
-struct local_rrset;
-struct dns_msg;
-
-/** calculate the prefetch TTL as 90% of original. Calculation
- * without numerical overflow (uin32_t) */
-#define PREFETCH_TTL_CALC(ttl) ((ttl) - (ttl)/10)
-
-/**
- * Structure to store query information that makes answers to queries
- * different.
- */
-struct query_info {
- /**
- * Salient data on the query: qname, in wireformat.
- * can be allocated or a pointer to outside buffer.
- * User has to keep track on the status of this.
- */
- uint8_t* qname;
- /** length of qname (including last 0 octet) */
- size_t qname_len;
- /** qtype, host byte order */
- uint16_t qtype;
- /** qclass, host byte order */
- uint16_t qclass;
- /**
- * Alias local answer(s) for the qname. If 'qname' is an alias defined
- * in a local zone, this field will be set to the corresponding local
- * RRset when the alias is determined.
- * In the initial implementation this can only be a single CNAME RR
- * (or NULL), but it could possibly be extended to be a DNAME or a
- * chain of aliases.
- * Users of this structure are responsible to initialize this field
- * to be NULL; otherwise other part of query handling code may be
- * confused.
- * Users also have to be careful about the lifetime of data. On return
- * from local zone lookup, it may point to data derived from
- * configuration that may be dynamically invalidated or data allocated
- * in an ephemeral regional allocator. A deep copy of the data may
- * have to be generated if it has to be kept during iterative
- * resolution. */
- struct local_rrset* local_alias;
-};
-
-/**
- * Information to reference an rrset
- */
-struct rrset_ref {
- /** the key with lock, and ptr to packed data. */
- struct ub_packed_rrset_key* key;
- /** id needed */
- rrset_id_type id;
-};
-
-/**
- * Structure to store DNS query and the reply packet.
- * To use it, copy over the flags from reply and modify using flags from
- * the query (RD,CD if not AA). prepend ID.
- *
- * Memory layout is:
- * o struct
- * o rrset_ref array
- * o packed_rrset_key* array.
- *
- * Memory layout is sometimes not packed, when the message is synthesized,
- * for easy of the generation. It is allocated packed when it is copied
- * from the region allocation to the malloc allocation.
- */
-struct reply_info {
- /** the flags for the answer, host byte order. */
- uint16_t flags;
-
- /**
- * This flag informs unbound the answer is authoritative and
- * the AA flag should be preserved.
- */
- uint8_t authoritative;
-
- /**
- * Number of RRs in the query section.
- * If qdcount is not 0, then it is 1, and the data that appears
- * in the reply is the same as the query_info.
- * Host byte order.
- */
- uint8_t qdcount;
-
- /** 32 bit padding to pad struct member alignment to 64 bits. */
- uint32_t padding;
-
- /**
- * TTL of the entire reply (for negative caching).
- * only for use when there are 0 RRsets in this message.
- * if there are RRsets, check those instead.
- */
- time_t ttl;
-
- /**
- * TTL for prefetch. After it has expired, a prefetch is suitable.
- * Smaller than the TTL, otherwise the prefetch would not happen.
- */
- time_t prefetch_ttl;
-
- /**
- * The security status from DNSSEC validation of this message.
- */
- enum sec_status security;
-
- /**
- * Number of RRsets in each section.
- * The answer section. Add up the RRs in every RRset to calculate
- * the number of RRs, and the count for the dns packet.
- * The number of RRs in RRsets can change due to RRset updates.
- */
- size_t an_numrrsets;
-
- /** Count of authority section RRsets */
- size_t ns_numrrsets;
- /** Count of additional section RRsets */
- size_t ar_numrrsets;
-
- /** number of RRsets: an_numrrsets + ns_numrrsets + ar_numrrsets */
- size_t rrset_count;
-
- /**
- * List of pointers (only) to the rrsets in the order in which
- * they appear in the reply message.
- * Number of elements is ancount+nscount+arcount RRsets.
- * This is a pointer to that array.
- * Use the accessor function for access.
- */
- struct ub_packed_rrset_key** rrsets;
-
- /**
- * Packed array of ids (see counts) and pointers to packed_rrset_key.
- * The number equals ancount+nscount+arcount RRsets.
- * These are sorted in ascending pointer, the locking order. So
- * this list can be locked (and id, ttl checked), to see if
- * all the data is available and recent enough.
- *
- * This is defined as an array of size 1, so that the compiler
- * associates the identifier with this position in the structure.
- * Array bound overflow on this array then gives access to the further
- * elements of the array, which are allocated after the main structure.
- *
- * It could be more pure to define as array of size 0, ref[0].
- * But ref[1] may be less confusing for compilers.
- * Use the accessor function for access.
- */
- struct rrset_ref ref[1];
-};
-
-/**
- * Structure to keep hash table entry for message replies.
- */
-struct msgreply_entry {
- /** the hash table key */
- struct query_info key;
- /** the hash table entry, data is struct reply_info* */
- struct lruhash_entry entry;
-};
-
-/**
- * Constructor for replyinfo.
- * @param region: where to allocate the results, pass NULL to use malloc.
- * @param flags: flags for the replyinfo.
- * @param qd: qd count
- * @param ttl: TTL of replyinfo
- * @param prettl: prefetch ttl
- * @param an: an count
- * @param ns: ns count
- * @param ar: ar count
- * @param total: total rrset count (presumably an+ns+ar).
- * @param sec: security status of the reply info.
- * @return the reply_info base struct with the array for putting the rrsets
- * in. The array has been zeroed. Returns NULL on malloc failure.
- */
-struct reply_info*
-construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd,
- time_t ttl, time_t prettl, size_t an, size_t ns, size_t ar,
- size_t total, enum sec_status sec);
-
-/**
- * Parse wire query into a queryinfo structure, return 0 on parse error.
- * initialises the (prealloced) queryinfo structure as well.
- * This query structure contains a pointer back info the buffer!
- * This pointer avoids memory allocation. allocqname does memory allocation.
- * @param m: the prealloced queryinfo structure to put query into.
- * must be unused, or _clear()ed.
- * @param query: the wireformat packet query. starts with ID.
- * @return: 0 on format error.
- */
-int query_info_parse(struct query_info* m, struct sldns_buffer* query);
-
-/**
- * Parse query reply.
- * Fills in preallocated query_info structure (with ptr into buffer).
- * Allocates reply_info and packed_rrsets. These are not yet added to any
- * caches or anything, this is only parsing. Returns formerror on qdcount > 1.
- * @param pkt: the packet buffer. Must be positioned after the query section.
- * @param alloc: creates packed rrset key structures.
- * @param rep: allocated reply_info is returned (only on no error).
- * @param qinf: query_info is returned (only on no error).
- * @param region: where to store temporary data (for parsing).
- * @param edns: where to store edns information, does not need to be inited.
- * @return: zero is OK, or DNS error code in case of error
- * o FORMERR for parse errors.
- * o SERVFAIL for memory allocation errors.
- */
-int reply_info_parse(struct sldns_buffer* pkt, struct alloc_cache* alloc,
- struct query_info* qinf, struct reply_info** rep,
- struct regional* region, struct edns_data* edns);
-
-/**
- * Allocate and decompress parsed message and rrsets.
- * @param pkt: for name decompression.
- * @param msg: parsed message in scratch region.
- * @param alloc: alloc cache for special rrset key structures.
- * Not used if region!=NULL, it can be NULL in that case.
- * @param qinf: where to store query info.
- * qinf itself is allocated by the caller.
- * @param rep: reply info is allocated and returned.
- * @param region: if this parameter is NULL then malloc and the alloc is used.
- * otherwise, everything is allocated in this region.
- * In a region, no special rrset key structures are needed (not shared),
- * and no rrset_ref array in the reply is built up.
- * @return 0 if allocation failed.
- */
-int parse_create_msg(struct sldns_buffer* pkt, struct msg_parse* msg,
- struct alloc_cache* alloc, struct query_info* qinf,
- struct reply_info** rep, struct regional* region);
-
-/**
- * Sorts the ref array.
- * @param rep: reply info. rrsets must be filled in.
- */
-void reply_info_sortref(struct reply_info* rep);
-
-/**
- * Set TTLs inside the replyinfo to absolute values.
- * @param rep: reply info. rrsets must be filled in.
- * Also refs must be filled in.
- * @param timenow: the current time.
- */
-void reply_info_set_ttls(struct reply_info* rep, time_t timenow);
-
-/**
- * Delete reply_info and packed_rrsets (while they are not yet added to the
- * hashtables.). Returns rrsets to the alloc cache.
- * @param rep: reply_info to delete.
- * @param alloc: where to return rrset structures to.
- */
-void reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc);
-
-/**
- * Compare two queryinfo structures, on query and type, class.
- * It is _not_ sorted in canonical ordering.
- * @param m1: struct query_info* , void* here to ease use as function pointer.
- * @param m2: struct query_info* , void* here to ease use as function pointer.
- * @return: 0 = same, -1 m1 is smaller, +1 m1 is larger.
- */
-int query_info_compare(void* m1, void* m2);
-
-/** clear out query info structure */
-void query_info_clear(struct query_info* m);
-
-/** calculate size of struct query_info + reply_info */
-size_t msgreply_sizefunc(void* k, void* d);
-
-/** delete msgreply_entry key structure */
-void query_entry_delete(void *q, void* arg);
-
-/** delete reply_info data structure */
-void reply_info_delete(void* d, void* arg);
-
-/** calculate hash value of query_info, lowercases the qname,
- * uses CD flag for AAAA qtype */
-hashvalue_type query_info_hash(struct query_info *q, uint16_t flags);
-
-/**
- * Setup query info entry
- * @param q: query info to copy. Emptied as if clear is called.
- * @param r: reply to init data.
- * @param h: hash value.
- * @return: newly allocated message reply cache item.
- */
-struct msgreply_entry* query_info_entrysetup(struct query_info* q,
- struct reply_info* r, hashvalue_type h);
-
-/**
- * Copy reply_info and all rrsets in it and allocate.
- * @param rep: what to copy, probably inside region, no ref[] array in it.
- * @param alloc: how to allocate rrset keys.
- * Not used if region!=NULL, it can be NULL in that case.
- * @param region: if this parameter is NULL then malloc and the alloc is used.
- * otherwise, everything is allocated in this region.
- * In a region, no special rrset key structures are needed (not shared),
- * and no rrset_ref array in the reply is built up.
- * @return new reply info or NULL on memory error.
- */
-struct reply_info* reply_info_copy(struct reply_info* rep,
- struct alloc_cache* alloc, struct regional* region);
-
-/**
- * Allocate (special) rrset keys.
- * @param rep: reply info in which the rrset keys to be allocated, rrset[]
- * array should have bee allocated with NULL pointers.
- * @param alloc: how to allocate rrset keys.
- * Not used if region!=NULL, it can be NULL in that case.
- * @param region: if this parameter is NULL then the alloc is used.
- * otherwise, rrset keys are allocated in this region.
- * In a region, no special rrset key structures are needed (not shared).
- * and no rrset_ref array in the reply needs to be built up.
- * @return 1 on success, 0 on error
- */
-int reply_info_alloc_rrset_keys(struct reply_info* rep,
- struct alloc_cache* alloc, struct regional* region);
-
-/**
- * Copy a parsed rrset into given key, decompressing and allocating rdata.
- * @param pkt: packet for decompression
- * @param msg: the parser message (for flags for trust).
- * @param pset: the parsed rrset to copy.
- * @param region: if NULL - malloc, else data is allocated in this region.
- * @param pk: a freshly obtained rrsetkey structure. No dname is set yet,
- * will be set on return.
- * Note that TTL will still be relative on return.
- * @return false on alloc failure.
- */
-int parse_copy_decompress_rrset(struct sldns_buffer* pkt, struct msg_parse* msg,
- struct rrset_parse *pset, struct regional* region,
- struct ub_packed_rrset_key* pk);
-
-/**
- * Find final cname target in reply, the one matching qinfo. Follows CNAMEs.
- * @param qinfo: what to start with.
- * @param rep: looks in answer section of this message.
- * @return: pointer dname, or NULL if not found.
- */
-uint8_t* reply_find_final_cname_target(struct query_info* qinfo,
- struct reply_info* rep);
-
-/**
- * Check if cname chain in cached reply is still valid.
- * @param qinfo: query info with query name.
- * @param rep: reply to check.
- * @return: true if valid, false if invalid.
- */
-int reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep);
-
-/**
- * Check security status of all RRs in the message.
- * @param rep: reply to check
- * @return: true if all RRs are secure. False if not.
- * True if there are zero RRs.
- */
-int reply_all_rrsets_secure(struct reply_info* rep);
-
-/**
- * Find answer rrset in reply, the one matching qinfo. Follows CNAMEs, so the
- * result may have a different owner name.
- * @param qinfo: what to look for.
- * @param rep: looks in answer section of this message.
- * @return: pointer to rrset, or NULL if not found.
- */
-struct ub_packed_rrset_key* reply_find_answer_rrset(struct query_info* qinfo,
- struct reply_info* rep);
-
-/**
- * Find rrset in reply, inside the answer section. Does not follow CNAMEs.
- * @param rep: looks in answer section of this message.
- * @param name: what to look for.
- * @param namelen: length of name.
- * @param type: looks for (host order).
- * @param dclass: looks for (host order).
- * @return: pointer to rrset, or NULL if not found.
- */
-struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep,
- uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass);
-
-/**
- * Find rrset in reply, inside the authority section. Does not follow CNAMEs.
- * @param rep: looks in authority section of this message.
- * @param name: what to look for.
- * @param namelen: length of name.
- * @param type: looks for (host order).
- * @param dclass: looks for (host order).
- * @return: pointer to rrset, or NULL if not found.
- */
-struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep,
- uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass);
-
-/**
- * Find rrset in reply, inside any section. Does not follow CNAMEs.
- * @param rep: looks in answer,authority and additional section of this message.
- * @param name: what to look for.
- * @param namelen: length of name.
- * @param type: looks for (host order).
- * @param dclass: looks for (host order).
- * @return: pointer to rrset, or NULL if not found.
- */
-struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep,
- uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass);
-
-/**
- * Debug send the query info and reply info to the log in readable form.
- * @param str: descriptive string printed with packet content.
- * @param qinfo: query section.
- * @param rep: rest of message.
- */
-void log_dns_msg(const char* str, struct query_info* qinfo,
- struct reply_info* rep);
-
-/**
- * Print string with neat domain name, type, class,
- * status code from, and size of a query response.
- *
- * @param v: at what verbosity level to print this.
- * @param qinf: query section.
- * @param addr: address of the client.
- * @param addrlen: length of the client address.
- * @param dur: how long it took to complete the query.
- * @param cached: whether or not the reply is coming from
- * the cache, or an outside network.
- * @param rmsg: sldns buffer packet.
- */
-void log_reply_info(enum verbosity_value v, struct query_info *qinf,
- struct sockaddr_storage *addr, socklen_t addrlen, struct timeval dur,
- int cached, struct sldns_buffer *rmsg);
-
-/**
- * Print string with neat domain name, type, class from query info.
- * @param v: at what verbosity level to print this.
- * @param str: string of message.
- * @param qinf: query info structure with name, type and class.
- */
-void log_query_info(enum verbosity_value v, const char* str,
- struct query_info* qinf);
-
-/**
- * Append edns option to edns data structure
- * @param edns: the edns data structure to append the edns option to.
- * @param region: region to allocate the new edns option.
- * @param code: the edns option's code.
- * @param len: the edns option's length.
- * @param data: the edns option's data.
- * @return false on failure.
- */
-int edns_opt_append(struct edns_data* edns, struct regional* region,
- uint16_t code, size_t len, uint8_t* data);
-
-/**
- * Append edns option to edns option list
- * @param list: the edns option list to append the edns option to.
- * @param code: the edns option's code.
- * @param len: the edns option's length.
- * @param data: the edns option's data.
- * @param region: region to allocate the new edns option.
- * @return false on failure.
- */
-int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
- uint8_t* data, struct regional* region);
-
-/**
- * Remove any option found on the edns option list that matches the code.
- * @param list: the list of edns options.
- * @param code: the opt code to remove.
- * @return true when at least one edns option was removed, false otherwise.
- */
-int edns_opt_list_remove(struct edns_option** list, uint16_t code);
-
-/**
- * Find edns option in edns list
- * @param list: list of edns options (eg. edns.opt_list)
- * @param code: opt code to find.
- * @return NULL or the edns_option element.
- */
-struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code);
-
-/**
- * Call the registered functions in the inplace_cb_reply linked list.
- * This function is going to get called while answering with a resolved query.
- * @param env: module environment.
- * @param qinfo: query info.
- * @param qstate: module qstate.
- * @param rep: Reply info. Could be NULL.
- * @param rcode: return code.
- * @param edns: edns data of the reply.
- * @param region: region to store data.
- * @return false on failure (a callback function returned an error).
- */
-int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
- struct module_qstate* qstate, struct reply_info* rep, int rcode,
- struct edns_data* edns, struct regional* region);
-
-/**
- * Call the registered functions in the inplace_cb_reply_cache linked list.
- * This function is going to get called while answering from cache.
- * @param env: module environment.
- * @param qinfo: query info.
- * @param qstate: module qstate. NULL when replying from cache.
- * @param rep: Reply info.
- * @param rcode: return code.
- * @param edns: edns data of the reply. Edns input can be found here.
- * @param region: region to store data.
- * @return false on failure (a callback function returned an error).
- */
-int inplace_cb_reply_cache_call(struct module_env* env,
- struct query_info* qinfo, struct module_qstate* qstate,
- struct reply_info* rep, int rcode, struct edns_data* edns,
- struct regional* region);
-
-/**
- * Call the registered functions in the inplace_cb_reply_local linked list.
- * This function is going to get called while answering with local data.
- * @param env: module environment.
- * @param qinfo: query info.
- * @param qstate: module qstate. NULL when replying from cache.
- * @param rep: Reply info.
- * @param rcode: return code.
- * @param edns: edns data of the reply. Edns input can be found here.
- * @param region: region to store data.
- * @return false on failure (a callback function returned an error).
- */
-int inplace_cb_reply_local_call(struct module_env* env,
- struct query_info* qinfo, struct module_qstate* qstate,
- struct reply_info* rep, int rcode, struct edns_data* edns,
- struct regional* region);
-
-/**
- * Call the registered functions in the inplace_cb_reply linked list.
- * This function is going to get called while answering with a servfail.
- * @param env: module environment.
- * @param qinfo: query info.
- * @param qstate: module qstate. Contains the edns option lists. Could be NULL.
- * @param rep: Reply info. NULL when servfail.
- * @param rcode: return code. LDNS_RCODE_SERVFAIL.
- * @param edns: edns data of the reply. Edns input can be found here if qstate
- * is NULL.
- * @param region: region to store data.
- * @return false on failure (a callback function returned an error).
- */
-int inplace_cb_reply_servfail_call(struct module_env* env,
- struct query_info* qinfo, struct module_qstate* qstate,
- struct reply_info* rep, int rcode, struct edns_data* edns,
- struct regional* region);
-
-/**
- * Call the registered functions in the inplace_cb_query linked list.
- * This function is going to get called just before sending a query to a
- * nameserver.
- * @param env: module environment.
- * @param qinfo: query info.
- * @param flags: flags of the query.
- * @param addr: to which server to send the query.
- * @param addrlen: length of addr.
- * @param zone: name of the zone of the delegation point. wireformat dname.
- * This is the delegation point name for which the server is deemed
- * authoritative.
- * @param zonelen: length of zone.
- * @param qstate: module qstate.
- * @param region: region to store data.
- * @return false on failure (a callback function returned an error).
- */
-int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,
- uint16_t flags, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
- struct regional* region);
-
-/**
- * Call the registered functions in the inplace_cb_edns_back_parsed linked list.
- * This function is going to get called after parsing the EDNS data on the
- * reply from a nameserver.
- * @param env: module environment.
- * @param qstate: module qstate.
- * @return false on failure (a callback function returned an error).
- */
-int inplace_cb_edns_back_parsed_call(struct module_env* env,
- struct module_qstate* qstate);
-
-/**
- * Call the registered functions in the inplace_cb_query_reponse linked list.
- * This function is going to get called after receiving a reply from a
- * nameserver.
- * @param env: module environment.
- * @param qstate: module qstate.
- * @param response: received response
- * @return false on failure (a callback function returned an error).
- */
-int inplace_cb_query_response_call(struct module_env* env,
- struct module_qstate* qstate, struct dns_msg* response);
-
-/**
- * Copy edns option list allocated to the new region
- */
-struct edns_option* edns_opt_copy_region(struct edns_option* list,
- struct regional* region);
-
-/**
- * Copy edns option list allocated with malloc
- */
-struct edns_option* edns_opt_copy_alloc(struct edns_option* list);
-
-/**
- * Free edns option list allocated with malloc
- */
-void edns_opt_list_free(struct edns_option* list);
-
-/**
- * Compare an edns option. (not entire list). Also compares contents.
- */
-int edns_opt_compare(struct edns_option* p, struct edns_option* q);
-
-/**
- * Compare edns option lists, also the order and contents of edns-options.
- */
-int edns_opt_list_compare(struct edns_option* p, struct edns_option* q);
-
-#endif /* UTIL_DATA_MSGREPLY_H */
diff --git a/external/unbound/util/data/packed_rrset.c b/external/unbound/util/data/packed_rrset.c
deleted file mode 100644
index 9944087cb..000000000
--- a/external/unbound/util/data/packed_rrset.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * util/data/packed_rrset.c - data storage for a set of resource records.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains the data storage for RRsets.
- */
-
-#include "config.h"
-#include "util/data/packed_rrset.h"
-#include "util/data/dname.h"
-#include "util/storage/lookup3.h"
-#include "util/log.h"
-#include "util/alloc.h"
-#include "util/regional.h"
-#include "util/net_help.h"
-#include "sldns/rrdef.h"
-#include "sldns/sbuffer.h"
-#include "sldns/wire2str.h"
-
-void
-ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey,
- struct alloc_cache* alloc)
-{
- if(!pkey)
- return;
- free(pkey->entry.data);
- pkey->entry.data = NULL;
- free(pkey->rk.dname);
- pkey->rk.dname = NULL;
- pkey->id = 0;
- alloc_special_release(alloc, pkey);
-}
-
-size_t
-ub_rrset_sizefunc(void* key, void* data)
-{
- struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key;
- struct packed_rrset_data* d = (struct packed_rrset_data*)data;
- size_t s = sizeof(struct ub_packed_rrset_key) + k->rk.dname_len;
- s += packed_rrset_sizeof(d) + lock_get_mem(&k->entry.lock);
- return s;
-}
-
-size_t
-packed_rrset_sizeof(struct packed_rrset_data* d)
-{
- size_t s;
- if(d->rrsig_count > 0) {
- s = ((uint8_t*)d->rr_data[d->count+d->rrsig_count-1] -
- (uint8_t*)d) + d->rr_len[d->count+d->rrsig_count-1];
- } else {
- log_assert(d->count > 0);
- s = ((uint8_t*)d->rr_data[d->count-1] - (uint8_t*)d) +
- d->rr_len[d->count-1];
- }
- return s;
-}
-
-int
-ub_rrset_compare(void* k1, void* k2)
-{
- struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1;
- struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2;
- int c;
- if(key1 == key2)
- return 0;
- if(key1->rk.type != key2->rk.type) {
- if(key1->rk.type < key2->rk.type)
- return -1;
- return 1;
- }
- if(key1->rk.dname_len != key2->rk.dname_len) {
- if(key1->rk.dname_len < key2->rk.dname_len)
- return -1;
- return 1;
- }
- if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0)
- return c;
- if(key1->rk.rrset_class != key2->rk.rrset_class) {
- if(key1->rk.rrset_class < key2->rk.rrset_class)
- return -1;
- return 1;
- }
- if(key1->rk.flags != key2->rk.flags) {
- if(key1->rk.flags < key2->rk.flags)
- return -1;
- return 1;
- }
- return 0;
-}
-
-void
-ub_rrset_key_delete(void* key, void* userdata)
-{
- struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key;
- struct alloc_cache* a = (struct alloc_cache*)userdata;
- k->id = 0;
- free(k->rk.dname);
- k->rk.dname = NULL;
- alloc_special_release(a, k);
-}
-
-void
-rrset_data_delete(void* data, void* ATTR_UNUSED(userdata))
-{
- struct packed_rrset_data* d = (struct packed_rrset_data*)data;
- free(d);
-}
-
-int
-rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2)
-{
- size_t i;
- size_t total;
- if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count)
- return 0;
- total = d1->count + d1->rrsig_count;
- for(i=0; i<total; i++) {
- if(d1->rr_len[i] != d2->rr_len[i])
- return 0;
- if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0)
- return 0;
- }
- return 1;
-}
-
-hashvalue_type
-rrset_key_hash(struct packed_rrset_key* key)
-{
- /* type is hashed in host order */
- uint16_t t = ntohs(key->type);
- /* Note this MUST be identical to pkt_hash_rrset in msgparse.c */
- /* this routine does not have a compressed name */
- hashvalue_type h = 0xab;
- h = dname_query_hash(key->dname, h);
- h = hashlittle(&t, sizeof(t), h);
- h = hashlittle(&key->rrset_class, sizeof(uint16_t), h);
- h = hashlittle(&key->flags, sizeof(uint32_t), h);
- return h;
-}
-
-void
-packed_rrset_ptr_fixup(struct packed_rrset_data* data)
-{
- size_t i;
- size_t total = data->count + data->rrsig_count;
- uint8_t* nextrdata;
- /* fixup pointers in packed rrset data */
- data->rr_len = (size_t*)((uint8_t*)data +
- sizeof(struct packed_rrset_data));
- data->rr_data = (uint8_t**)&(data->rr_len[total]);
- data->rr_ttl = (time_t*)&(data->rr_data[total]);
- nextrdata = (uint8_t*)&(data->rr_ttl[total]);
- for(i=0; i<total; i++) {
- data->rr_data[i] = nextrdata;
- nextrdata += data->rr_len[i];
- }
-}
-
-void
-get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname,
- size_t* dname_len)
-{
- struct packed_rrset_data* d;
- size_t len;
- if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME &&
- ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME)
- return;
- d = (struct packed_rrset_data*)rrset->entry.data;
- if(d->count < 1)
- return;
- if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */
- return;
- len = sldns_read_uint16(d->rr_data[0]);
- if(len != d->rr_len[0] - sizeof(uint16_t))
- return;
- if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len)
- return;
- *dname = d->rr_data[0]+sizeof(uint16_t);
- *dname_len = len;
-}
-
-void
-packed_rrset_ttl_add(struct packed_rrset_data* data, time_t add)
-{
- size_t i;
- size_t total = data->count + data->rrsig_count;
- data->ttl += add;
- for(i=0; i<total; i++)
- data->rr_ttl[i] += add;
-}
-
-const char*
-rrset_trust_to_string(enum rrset_trust s)
-{
- switch(s) {
- case rrset_trust_none: return "rrset_trust_none";
- case rrset_trust_add_noAA: return "rrset_trust_add_noAA";
- case rrset_trust_auth_noAA: return "rrset_trust_auth_noAA";
- case rrset_trust_add_AA: return "rrset_trust_add_AA";
- case rrset_trust_nonauth_ans_AA:return "rrset_trust_nonauth_ans_AA";
- case rrset_trust_ans_noAA: return "rrset_trust_ans_noAA";
- case rrset_trust_glue: return "rrset_trust_glue";
- case rrset_trust_auth_AA: return "rrset_trust_auth_AA";
- case rrset_trust_ans_AA: return "rrset_trust_ans_AA";
- case rrset_trust_sec_noglue: return "rrset_trust_sec_noglue";
- case rrset_trust_prim_noglue: return "rrset_trust_prim_noglue";
- case rrset_trust_validated: return "rrset_trust_validated";
- case rrset_trust_ultimate: return "rrset_trust_ultimate";
- }
- return "unknown_rrset_trust_value";
-}
-
-const char*
-sec_status_to_string(enum sec_status s)
-{
- switch(s) {
- case sec_status_unchecked: return "sec_status_unchecked";
- case sec_status_bogus: return "sec_status_bogus";
- case sec_status_indeterminate: return "sec_status_indeterminate";
- case sec_status_insecure: return "sec_status_insecure";
- case sec_status_secure: return "sec_status_secure";
- }
- return "unknown_sec_status_value";
-}
-
-void log_rrset_key(enum verbosity_value v, const char* str,
- struct ub_packed_rrset_key* rrset)
-{
- if(verbosity >= v)
- log_nametypeclass(v, str, rrset->rk.dname,
- ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
-}
-
-int packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i,
- time_t now, char* dest, size_t dest_len)
-{
- struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
- entry.data;
- uint8_t rr[65535];
- size_t rlen = rrset->rk.dname_len + 2 + 2 + 4 + d->rr_len[i];
- log_assert(dest_len > 0 && dest);
- if(rlen > dest_len) {
- dest[0] = 0;
- return 0;
- }
- memmove(rr, rrset->rk.dname, rrset->rk.dname_len);
- if(i < d->count)
- memmove(rr+rrset->rk.dname_len, &rrset->rk.type, 2);
- else sldns_write_uint16(rr+rrset->rk.dname_len, LDNS_RR_TYPE_RRSIG);
- memmove(rr+rrset->rk.dname_len+2, &rrset->rk.rrset_class, 2);
- sldns_write_uint32(rr+rrset->rk.dname_len+4,
- (uint32_t)(d->rr_ttl[i]-now));
- memmove(rr+rrset->rk.dname_len+8, d->rr_data[i], d->rr_len[i]);
- if(sldns_wire2str_rr_buf(rr, rlen, dest, dest_len) == -1) {
- log_info("rrbuf failure %d %s", (int)d->rr_len[i], dest);
- dest[0] = 0;
- return 0;
- }
- return 1;
-}
-
-void log_packed_rrset(enum verbosity_value v, const char* str,
- struct ub_packed_rrset_key* rrset)
-{
- struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
- entry.data;
- char buf[65535];
- size_t i;
- if(verbosity < v)
- return;
- for(i=0; i<d->count+d->rrsig_count; i++) {
- if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf))) {
- log_info("%s: rr %d wire2str-error", str, (int)i);
- } else {
- log_info("%s: %s", str, buf);
- }
- }
-}
-
-time_t
-ub_packed_rrset_ttl(struct ub_packed_rrset_key* key)
-{
- struct packed_rrset_data* d = (struct packed_rrset_data*)key->
- entry.data;
- return d->ttl;
-}
-
-struct ub_packed_rrset_key*
-packed_rrset_copy_region(struct ub_packed_rrset_key* key,
- struct regional* region, time_t now)
-{
- struct ub_packed_rrset_key* ck = regional_alloc(region,
- sizeof(struct ub_packed_rrset_key));
- struct packed_rrset_data* d;
- struct packed_rrset_data* data = (struct packed_rrset_data*)
- key->entry.data;
- size_t dsize, i;
- if(!ck)
- return NULL;
- ck->id = key->id;
- memset(&ck->entry, 0, sizeof(ck->entry));
- ck->entry.hash = key->entry.hash;
- ck->entry.key = ck;
- ck->rk = key->rk;
- ck->rk.dname = regional_alloc_init(region, key->rk.dname,
- key->rk.dname_len);
- if(!ck->rk.dname)
- return NULL;
- dsize = packed_rrset_sizeof(data);
- d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize);
- if(!d)
- return NULL;
- ck->entry.data = d;
- packed_rrset_ptr_fixup(d);
- /* make TTLs relative - once per rrset */
- for(i=0; i<d->count + d->rrsig_count; i++) {
- if(d->rr_ttl[i] < now)
- d->rr_ttl[i] = 0;
- else d->rr_ttl[i] -= now;
- }
- if(d->ttl < now)
- d->ttl = 0;
- else d->ttl -= now;
- return ck;
-}
-
-struct ub_packed_rrset_key*
-packed_rrset_copy_alloc(struct ub_packed_rrset_key* key,
- struct alloc_cache* alloc, time_t now)
-{
- struct packed_rrset_data* fd, *dd;
- struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc);
- if(!dk) return NULL;
- fd = (struct packed_rrset_data*)key->entry.data;
- dk->entry.hash = key->entry.hash;
- dk->rk = key->rk;
- dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len);
- if(!dk->rk.dname) {
- alloc_special_release(alloc, dk);
- return NULL;
- }
- dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd));
- if(!dd) {
- free(dk->rk.dname);
- alloc_special_release(alloc, dk);
- return NULL;
- }
- packed_rrset_ptr_fixup(dd);
- dk->entry.data = (void*)dd;
- packed_rrset_ttl_add(dd, now);
- return dk;
-}
diff --git a/external/unbound/util/data/packed_rrset.h b/external/unbound/util/data/packed_rrset.h
deleted file mode 100644
index 28f603d6f..000000000
--- a/external/unbound/util/data/packed_rrset.h
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * util/data/packed_rrset.h - data storage for a set of resource records.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains the data storage for RRsets.
- */
-
-#ifndef UTIL_DATA_PACKED_RRSET_H
-#define UTIL_DATA_PACKED_RRSET_H
-#include "util/storage/lruhash.h"
-struct alloc_cache;
-struct regional;
-
-/** type used to uniquely identify rrsets. Cannot be reused without
- * clearing the cache. */
-typedef uint64_t rrset_id_type;
-
-/** this rrset is NSEC and is at zone apex (at child side of zonecut) */
-#define PACKED_RRSET_NSEC_AT_APEX 0x1
-/** this rrset is A/AAAA and is in-zone-glue (from parent side of zonecut) */
-#define PACKED_RRSET_PARENT_SIDE 0x2
-/** this rrset is SOA and has the negative ttl (from nxdomain or nodata),
- * this is set on SOA rrsets in the authority section, to keep its TTL separate
- * from the SOA in the answer section from a direct SOA query or ANY query. */
-#define PACKED_RRSET_SOA_NEG 0x4
-/** This rrset is considered to have a fixed TTL; its TTL doesn't have to be
- * updated on encoding in a reply. This flag is not expected to be set in
- * cached data. */
-#define PACKED_RRSET_FIXEDTTL 0x80000000
-
-/** number of rrs and rrsets for integer overflow protection. More than
- * this is not really possible (64K packet has much less RRs and RRsets) in
- * a message. And this is small enough that also multiplied there is no
- * integer overflow. */
-#define RR_COUNT_MAX 0xffffff
-
-/**
- * The identifying information for an RRset.
- */
-struct packed_rrset_key {
- /**
- * The domain name. If not null (for id=0) it is allocated, and
- * contains the wireformat domain name.
- * This dname is not canonicalized.
- */
- uint8_t* dname;
- /**
- * Length of the domain name, including last 0 root octet.
- */
- size_t dname_len;
- /**
- * Flags. 32bit to be easy for hashing:
- * o PACKED_RRSET_NSEC_AT_APEX
- * o PACKED_RRSET_PARENT_SIDE
- * o PACKED_RRSET_SOA_NEG
- * o PACKED_RRSET_FIXEDTTL (not supposed to be cached)
- */
- uint32_t flags;
- /** the rrset type in network format */
- uint16_t type;
- /** the rrset class in network format */
- uint16_t rrset_class;
-};
-
-/**
- * This structure contains an RRset. A set of resource records that
- * share the same domain name, type and class.
- *
- * Due to memory management and threading, the key structure cannot be
- * deleted, although the data can be. The id can be set to 0 to store and the
- * structure can be recycled with a new id.
- */
-struct ub_packed_rrset_key {
- /**
- * entry into hashtable. Note the lock is never destroyed,
- * even when this key is retired to the cache.
- * the data pointer (if not null) points to a struct packed_rrset.
- */
- struct lruhash_entry entry;
- /**
- * the ID of this rrset. unique, based on threadid + sequenceno.
- * ids are not reused, except after flushing the cache.
- * zero is an unused entry, and never a valid id.
- * Check this value after getting entry.lock.
- * The other values in this struct may only be altered after changing
- * the id (which needs a writelock on entry.lock).
- */
- rrset_id_type id;
- /** key data: dname, type and class */
- struct packed_rrset_key rk;
-};
-
-/**
- * RRset trustworthiness. Bigger value is more trust. RFC 2181.
- * The rrset_trust_add_noAA, rrset_trust_auth_noAA, rrset_trust_add_AA,
- * are mentioned as the same trustworthiness in 2181, but split up here
- * for ease of processing.
- *
- * rrset_trust_nonauth_ans_AA, rrset_trust_ans_noAA
- * are also mentioned as the same trustworthiness in 2181, but split up here
- * for ease of processing.
- *
- * Added trust_none for a sane initial value, smaller than anything else.
- * Added validated and ultimate trust for keys and rrsig validated content.
- */
-enum rrset_trust {
- /** initial value for trust */
- rrset_trust_none = 0,
- /** Additional information from non-authoritative answers */
- rrset_trust_add_noAA,
- /** Data from the authority section of a non-authoritative answer */
- rrset_trust_auth_noAA,
- /** Additional information from an authoritative answer */
- rrset_trust_add_AA,
- /** non-authoritative data from the answer section of authoritative
- * answers */
- rrset_trust_nonauth_ans_AA,
- /** Data from the answer section of a non-authoritative answer */
- rrset_trust_ans_noAA,
- /** Glue from a primary zone, or glue from a zone transfer */
- rrset_trust_glue,
- /** Data from the authority section of an authoritative answer */
- rrset_trust_auth_AA,
- /** The authoritative data included in the answer section of an
- * authoritative reply */
- rrset_trust_ans_AA,
- /** Data from a zone transfer, other than glue */
- rrset_trust_sec_noglue,
- /** Data from a primary zone file, other than glue data */
- rrset_trust_prim_noglue,
- /** DNSSEC(rfc4034) validated with trusted keys */
- rrset_trust_validated,
- /** ultimately trusted, no more trust is possible;
- * trusted keys from the unbound configuration setup. */
- rrset_trust_ultimate
-};
-
-/**
- * Security status from validation for data.
- * The order is significant; more secure, more proven later.
- */
-enum sec_status {
- /** UNCHECKED means that object has yet to be validated. */
- sec_status_unchecked = 0,
- /** BOGUS means that the object (RRset or message) failed to validate
- * (according to local policy), but should have validated. */
- sec_status_bogus,
- /** INDETERMINATE means that the object is insecure, but not
- * authoritatively so. Generally this means that the RRset is not
- * below a configured trust anchor. */
- sec_status_indeterminate,
- /** INSECURE means that the object is authoritatively known to be
- * insecure. Generally this means that this RRset is below a trust
- * anchor, but also below a verified, insecure delegation. */
- sec_status_insecure,
- /** SECURE means that the object (RRset or message) validated
- * according to local policy. */
- sec_status_secure
-};
-
-/**
- * RRset data.
- *
- * The data is packed, stored contiguously in memory.
- *
- * It is not always stored contiguously, in that case, an unpacked-packed
- * rrset has the arrays separate. A bunch of routines work on that, but
- * the packed rrset that is contiguous is for the rrset-cache and the
- * cache-response routines in daemon/worker.c.
- *
- * memory layout:
- * o base struct
- * o rr_len size_t array
- * o rr_data uint8_t* array
- * o rr_ttl time_t array (after size_t and ptrs because those may be
- * 64bit and this array before those would make them unaligned).
- * Since the stuff before is 32/64bit, rr_ttl is 32 bit aligned.
- * o rr_data rdata wireformats
- * o rrsig_data rdata wireformat(s)
- *
- * Rdata is stored in wireformat. The dname is stored in wireformat.
- * TTLs are stored as absolute values (and could be expired).
- *
- * RRSIGs are stored in the arrays after the regular rrs.
- *
- * You need the packed_rrset_key to know dname, type, class of the
- * resource records in this RRset. (if signed the rrsig gives the type too).
- *
- * On the wire an RR is:
- * name, type, class, ttl, rdlength, rdata.
- * So we need to send the following per RR:
- * key.dname, ttl, rr_data[i].
- * since key.dname ends with type and class.
- * and rr_data starts with the rdlength.
- * the ttl value to send changes due to time.
- */
-struct packed_rrset_data {
- /** TTL (in seconds like time()) of the rrset.
- * Same for all RRs see rfc2181(5.2). */
- time_t ttl;
- /** number of rrs. */
- size_t count;
- /** number of rrsigs, if 0 no rrsigs */
- size_t rrsig_count;
- /** the trustworthiness of the rrset data */
- enum rrset_trust trust;
- /** security status of the rrset data */
- enum sec_status security;
- /** length of every rr's rdata, rr_len[i] is size of rr_data[i]. */
- size_t* rr_len;
- /** ttl of every rr. rr_ttl[i] ttl of rr i. */
- time_t *rr_ttl;
- /**
- * Array of pointers to every rr's rdata.
- * The rr_data[i] rdata is stored in uncompressed wireformat.
- * The first uint16_t of rr_data[i] is network format rdlength.
- *
- * rr_data[count] to rr_data[count+rrsig_count] contain the rrsig data.
- */
- uint8_t** rr_data;
-};
-
-/**
- * An RRset can be represented using both key and data together.
- * Split into key and data structures to simplify implementation of
- * caching schemes.
- */
-struct packed_rrset {
- /** domain name, type and class */
- struct packed_rrset_key* k;
- /** ttl, count and rdatas (and rrsig) */
- struct packed_rrset_data* d;
-};
-
-/**
- * list of packed rrsets
- */
-struct packed_rrset_list {
- /** next in list */
- struct packed_rrset_list* next;
- /** rrset key and data */
- struct packed_rrset rrset;
-};
-
-/**
- * Delete packed rrset key and data, not entered in hashtables yet.
- * Used during parsing.
- * @param pkey: rrset key structure with locks, key and data pointers.
- * @param alloc: where to return the unfree-able key structure.
- */
-void ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey,
- struct alloc_cache* alloc);
-
-/**
- * Memory size of rrset data. RRset data must be filled in correctly.
- * @param data: data to examine.
- * @return size in bytes.
- */
-size_t packed_rrset_sizeof(struct packed_rrset_data* data);
-
-/**
- * Get TTL of rrset. RRset data must be filled in correctly.
- * @param key: rrset key, with data to examine.
- * @return ttl value.
- */
-time_t ub_packed_rrset_ttl(struct ub_packed_rrset_key* key);
-
-/**
- * Calculate memory size of rrset entry. For hash table usage.
- * @param key: struct ub_packed_rrset_key*.
- * @param data: struct packed_rrset_data*.
- * @return size in bytes.
- */
-size_t ub_rrset_sizefunc(void* key, void* data);
-
-/**
- * compares two rrset keys.
- * @param k1: struct ub_packed_rrset_key*.
- * @param k2: struct ub_packed_rrset_key*.
- * @return 0 if equal.
- */
-int ub_rrset_compare(void* k1, void* k2);
-
-/**
- * compare two rrset data structures.
- * Compared rdata and rrsigdata, not the trust or ttl value.
- * @param d1: data to compare.
- * @param d2: data to compare.
- * @return 1 if equal.
- */
-int rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2);
-
-/**
- * Old key to be deleted. RRset keys are recycled via alloc.
- * The id is set to 0. So that other threads, after acquiring a lock always
- * get the correct value, in this case the 0 deleted-special value.
- * @param key: struct ub_packed_rrset_key*.
- * @param userdata: alloc structure to use for recycling.
- */
-void ub_rrset_key_delete(void* key, void* userdata);
-
-/**
- * Old data to be deleted.
- * @param data: what to delete.
- * @param userdata: user data ptr.
- */
-void rrset_data_delete(void* data, void* userdata);
-
-/**
- * Calculate hash value for a packed rrset key.
- * @param key: the rrset key with name, type, class, flags.
- * @return hash value.
- */
-hashvalue_type rrset_key_hash(struct packed_rrset_key* key);
-
-/**
- * Fixup pointers in fixed data packed_rrset_data blob.
- * After a memcpy of the data for example. Will set internal pointers right.
- * @param data: rrset data structure. Otherwise correctly filled in.
- */
-void packed_rrset_ptr_fixup(struct packed_rrset_data* data);
-
-/**
- * Fixup TTLs in fixed data packed_rrset_data blob.
- * @param data: rrset data structure. Otherwise correctly filled in.
- * @param add: how many seconds to add, pass time(0) for example.
- */
-void packed_rrset_ttl_add(struct packed_rrset_data* data, time_t add);
-
-/**
- * Utility procedure to extract CNAME target name from its rdata.
- * Failsafes; it will change passed dname to a valid dname or do nothing.
- * @param rrset: the rrset structure. Must be a CNAME.
- * Only first RR is used (multiple RRs are technically illegal anyway).
- * Also works on type DNAME. Returns target name.
- * @param dname: this pointer is updated to point into the cname rdata.
- * If a failsafe fails, nothing happens to the pointer (such as the
- * rdata was not a valid dname, not a CNAME, ...).
- * @param dname_len: length of dname is returned.
- */
-void get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname,
- size_t* dname_len);
-
-/**
- * Get a printable string for a rrset trust value
- * @param s: rrset trust value
- * @return printable string.
- */
-const char* rrset_trust_to_string(enum rrset_trust s);
-
-/**
- * Get a printable string for a security status value
- * @param s: security status
- * @return printable string.
- */
-const char* sec_status_to_string(enum sec_status s);
-
-/**
- * Print string with neat domain name, type, class from rrset.
- * @param v: at what verbosity level to print this.
- * @param str: string of message.
- * @param rrset: structure with name, type and class.
- */
-void log_rrset_key(enum verbosity_value v, const char* str,
- struct ub_packed_rrset_key* rrset);
-
-/**
- * Convert RR from RRset to string.
- * @param rrset: structure with data.
- * @param i: index of rr or RRSIG.
- * @param now: time that is subtracted from ttl before printout. Can be 0.
- * @param dest: destination string buffer. Must be nonNULL.
- * @param dest_len: length of dest buffer (>0).
- * @return false on failure.
- */
-int packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i,
- time_t now, char* dest, size_t dest_len);
-
-/**
- * Print the string with prefix, one rr per line.
- * @param v: at what verbosity level to print this.
- * @param str: string of message.
- * @param rrset: with name, and rdata, and rrsigs.
- */
-void log_packed_rrset(enum verbosity_value v, const char* str,
- struct ub_packed_rrset_key* rrset);
-
-/**
- * Allocate rrset in region - no more locks needed
- * @param key: a (just from rrset cache looked up) rrset key + valid,
- * packed data record.
- * @param region: where to alloc the copy
- * @param now: adjust the TTLs to be relative (subtract from all TTLs).
- * @return new region-alloced rrset key or NULL on alloc failure.
- */
-struct ub_packed_rrset_key* packed_rrset_copy_region(
- struct ub_packed_rrset_key* key, struct regional* region,
- time_t now);
-
-/**
- * Allocate rrset with malloc (from region or you are holding the lock).
- * @param key: key with data entry.
- * @param alloc: alloc_cache to create rrset_keys
- * @param now: adjust the TTLs to be absolute (add to all TTLs).
- * @return new region-alloced rrset key or NULL on alloc failure.
- */
-struct ub_packed_rrset_key* packed_rrset_copy_alloc(
- struct ub_packed_rrset_key* key, struct alloc_cache* alloc,
- time_t now);
-
-#endif /* UTIL_DATA_PACKED_RRSET_H */