diff options
Diffstat (limited to 'external/unbound/util/data/dname.c')
-rw-r--r-- | external/unbound/util/data/dname.c | 788 |
1 files changed, 0 insertions, 788 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; -} |