xref: /openbsd/sbin/unwind/libunbound/util/data/dname.c (revision 5a7d75e6)
1ae8c6e27Sflorian /*
2ae8c6e27Sflorian  * util/data/dname.h - domain name handling
3ae8c6e27Sflorian  *
4ae8c6e27Sflorian  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5ae8c6e27Sflorian  *
6ae8c6e27Sflorian  * This software is open source.
7ae8c6e27Sflorian  *
8ae8c6e27Sflorian  * Redistribution and use in source and binary forms, with or without
9ae8c6e27Sflorian  * modification, are permitted provided that the following conditions
10ae8c6e27Sflorian  * are met:
11ae8c6e27Sflorian  *
12ae8c6e27Sflorian  * Redistributions of source code must retain the above copyright notice,
13ae8c6e27Sflorian  * this list of conditions and the following disclaimer.
14ae8c6e27Sflorian  *
15ae8c6e27Sflorian  * Redistributions in binary form must reproduce the above copyright notice,
16ae8c6e27Sflorian  * this list of conditions and the following disclaimer in the documentation
17ae8c6e27Sflorian  * and/or other materials provided with the distribution.
18ae8c6e27Sflorian  *
19ae8c6e27Sflorian  * Neither the name of the NLNET LABS nor the names of its contributors may
20ae8c6e27Sflorian  * be used to endorse or promote products derived from this software without
21ae8c6e27Sflorian  * specific prior written permission.
22ae8c6e27Sflorian  *
23ae8c6e27Sflorian  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24ae8c6e27Sflorian  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25ae8c6e27Sflorian  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26ae8c6e27Sflorian  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27ae8c6e27Sflorian  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28ae8c6e27Sflorian  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29ae8c6e27Sflorian  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30ae8c6e27Sflorian  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31ae8c6e27Sflorian  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32ae8c6e27Sflorian  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33ae8c6e27Sflorian  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34ae8c6e27Sflorian  */
35ae8c6e27Sflorian 
36ae8c6e27Sflorian /**
37ae8c6e27Sflorian  * \file
38ae8c6e27Sflorian  *
39ae8c6e27Sflorian  * This file contains domain name handling functions.
40ae8c6e27Sflorian  */
41ae8c6e27Sflorian 
42ae8c6e27Sflorian #include "config.h"
43ae8c6e27Sflorian #include <ctype.h>
44ae8c6e27Sflorian #include "util/data/dname.h"
45ae8c6e27Sflorian #include "util/data/msgparse.h"
46ae8c6e27Sflorian #include "util/log.h"
47ae8c6e27Sflorian #include "util/storage/lookup3.h"
48ae8c6e27Sflorian #include "sldns/sbuffer.h"
49ae8c6e27Sflorian 
50ae8c6e27Sflorian /* determine length of a dname in buffer, no compression pointers allowed */
51ae8c6e27Sflorian size_t
query_dname_len(sldns_buffer * query)52ae8c6e27Sflorian query_dname_len(sldns_buffer* query)
53ae8c6e27Sflorian {
54ae8c6e27Sflorian 	size_t len = 0;
55ae8c6e27Sflorian 	size_t labellen;
56ae8c6e27Sflorian 	while(1) {
57ae8c6e27Sflorian 		if(sldns_buffer_remaining(query) < 1)
58ae8c6e27Sflorian 			return 0; /* parse error, need label len */
59ae8c6e27Sflorian 		labellen = sldns_buffer_read_u8(query);
60ae8c6e27Sflorian 		if(labellen&0xc0)
61ae8c6e27Sflorian 			return 0; /* no compression allowed in queries */
62ae8c6e27Sflorian 		len += labellen + 1;
63ae8c6e27Sflorian 		if(len > LDNS_MAX_DOMAINLEN)
64ae8c6e27Sflorian 			return 0; /* too long */
65ae8c6e27Sflorian 		if(labellen == 0)
66ae8c6e27Sflorian 			return len;
67ae8c6e27Sflorian 		if(sldns_buffer_remaining(query) < labellen)
68ae8c6e27Sflorian 			return 0; /* parse error, need content */
69ae8c6e27Sflorian 		sldns_buffer_skip(query, (ssize_t)labellen);
70ae8c6e27Sflorian 	}
71ae8c6e27Sflorian }
72ae8c6e27Sflorian 
73ae8c6e27Sflorian size_t
dname_valid(uint8_t * dname,size_t maxlen)74ae8c6e27Sflorian dname_valid(uint8_t* dname, size_t maxlen)
75ae8c6e27Sflorian {
76ae8c6e27Sflorian 	size_t len = 0;
77ae8c6e27Sflorian 	size_t labellen;
7857403691Sflorian 	if(maxlen == 0)
7957403691Sflorian 		return 0; /* too short, shortest is '0' root label */
80ae8c6e27Sflorian 	labellen = *dname++;
81ae8c6e27Sflorian 	while(labellen) {
82ae8c6e27Sflorian 		if(labellen&0xc0)
83ae8c6e27Sflorian 			return 0; /* no compression ptrs allowed */
84ae8c6e27Sflorian 		len += labellen + 1;
85ae8c6e27Sflorian 		if(len >= LDNS_MAX_DOMAINLEN)
86ae8c6e27Sflorian 			return 0; /* too long */
87ae8c6e27Sflorian 		if(len > maxlen)
88ae8c6e27Sflorian 			return 0; /* does not fit in memory allocation */
89ae8c6e27Sflorian 		dname += labellen;
90ae8c6e27Sflorian 		labellen = *dname++;
91ae8c6e27Sflorian 	}
92ae8c6e27Sflorian 	len += 1;
93ae8c6e27Sflorian 	if(len > maxlen)
94ae8c6e27Sflorian 		return 0; /* does not fit in memory allocation */
95ae8c6e27Sflorian 	return len;
96ae8c6e27Sflorian }
97ae8c6e27Sflorian 
98ae8c6e27Sflorian /** compare uncompressed, noncanonical, registers are hints for speed */
99ae8c6e27Sflorian int
query_dname_compare(register uint8_t * d1,register uint8_t * d2)100ae8c6e27Sflorian query_dname_compare(register uint8_t* d1, register uint8_t* d2)
101ae8c6e27Sflorian {
102ae8c6e27Sflorian 	register uint8_t lab1, lab2;
103ae8c6e27Sflorian 	log_assert(d1 && d2);
104ae8c6e27Sflorian 	lab1 = *d1++;
105ae8c6e27Sflorian 	lab2 = *d2++;
106ae8c6e27Sflorian 	while( lab1 != 0 || lab2 != 0 ) {
107ae8c6e27Sflorian 		/* compare label length */
108ae8c6e27Sflorian 		/* if one dname ends, it has labellength 0 */
109ae8c6e27Sflorian 		if(lab1 != lab2) {
110ae8c6e27Sflorian 			if(lab1 < lab2)
111ae8c6e27Sflorian 				return -1;
112ae8c6e27Sflorian 			return 1;
113ae8c6e27Sflorian 		}
114ae8c6e27Sflorian 		log_assert(lab1 == lab2 && lab1 != 0);
115ae8c6e27Sflorian 		/* compare lowercased labels. */
116ae8c6e27Sflorian 		while(lab1--) {
117ae8c6e27Sflorian 			/* compare bytes first for speed */
118ae8c6e27Sflorian 			if(*d1 != *d2 &&
119ae8c6e27Sflorian 				tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) {
120ae8c6e27Sflorian 				if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2))
121ae8c6e27Sflorian 					return -1;
122ae8c6e27Sflorian 				return 1;
123ae8c6e27Sflorian 			}
124ae8c6e27Sflorian 			d1++;
125ae8c6e27Sflorian 			d2++;
126ae8c6e27Sflorian 		}
127ae8c6e27Sflorian 		/* next pair of labels. */
128ae8c6e27Sflorian 		lab1 = *d1++;
129ae8c6e27Sflorian 		lab2 = *d2++;
130ae8c6e27Sflorian 	}
131ae8c6e27Sflorian 	return 0;
132ae8c6e27Sflorian }
133ae8c6e27Sflorian 
134ae8c6e27Sflorian void
query_dname_tolower(uint8_t * dname)135ae8c6e27Sflorian query_dname_tolower(uint8_t* dname)
136ae8c6e27Sflorian {
137ae8c6e27Sflorian 	/* the dname is stored uncompressed */
138ae8c6e27Sflorian 	uint8_t labellen;
139ae8c6e27Sflorian 	labellen = *dname;
140ae8c6e27Sflorian 	while(labellen) {
141ae8c6e27Sflorian 		dname++;
142ae8c6e27Sflorian 		while(labellen--) {
143ae8c6e27Sflorian 			*dname = (uint8_t)tolower((unsigned char)*dname);
144ae8c6e27Sflorian 			dname++;
145ae8c6e27Sflorian 		}
146ae8c6e27Sflorian 		labellen = *dname;
147ae8c6e27Sflorian 	}
148ae8c6e27Sflorian }
149ae8c6e27Sflorian 
150ae8c6e27Sflorian void
pkt_dname_tolower(sldns_buffer * pkt,uint8_t * dname)151ae8c6e27Sflorian pkt_dname_tolower(sldns_buffer* pkt, uint8_t* dname)
152ae8c6e27Sflorian {
153ae8c6e27Sflorian 	uint8_t lablen;
154ae8c6e27Sflorian 	int count = 0;
155ae8c6e27Sflorian 	if(dname >= sldns_buffer_end(pkt))
156ae8c6e27Sflorian 		return;
157ae8c6e27Sflorian 	lablen = *dname++;
158ae8c6e27Sflorian 	while(lablen) {
159ae8c6e27Sflorian 		if(LABEL_IS_PTR(lablen)) {
160ae8c6e27Sflorian 			if((size_t)PTR_OFFSET(lablen, *dname)
161ae8c6e27Sflorian 				>= sldns_buffer_limit(pkt))
162ae8c6e27Sflorian 				return;
163ae8c6e27Sflorian 			dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
164ae8c6e27Sflorian 			lablen = *dname++;
165ae8c6e27Sflorian 			if(count++ > MAX_COMPRESS_PTRS)
166ae8c6e27Sflorian 				return;
167ae8c6e27Sflorian 			continue;
168ae8c6e27Sflorian 		}
169ae8c6e27Sflorian 		if(dname+lablen >= sldns_buffer_end(pkt))
170ae8c6e27Sflorian 			return;
171ae8c6e27Sflorian 		while(lablen--) {
172ae8c6e27Sflorian 			*dname = (uint8_t)tolower((unsigned char)*dname);
173ae8c6e27Sflorian 			dname++;
174ae8c6e27Sflorian 		}
175ae8c6e27Sflorian 		if(dname >= sldns_buffer_end(pkt))
176ae8c6e27Sflorian 			return;
177ae8c6e27Sflorian 		lablen = *dname++;
178ae8c6e27Sflorian 	}
179ae8c6e27Sflorian }
180ae8c6e27Sflorian 
181ae8c6e27Sflorian 
182ae8c6e27Sflorian size_t
pkt_dname_len(sldns_buffer * pkt)183ae8c6e27Sflorian pkt_dname_len(sldns_buffer* pkt)
184ae8c6e27Sflorian {
185ae8c6e27Sflorian 	size_t len = 0;
186ae8c6e27Sflorian 	int ptrcount = 0;
187ae8c6e27Sflorian 	uint8_t labellen;
188ae8c6e27Sflorian 	size_t endpos = 0;
189ae8c6e27Sflorian 
190ae8c6e27Sflorian 	/* read dname and determine length */
191ae8c6e27Sflorian 	/* check compression pointers, loops, out of bounds */
192ae8c6e27Sflorian 	while(1) {
193ae8c6e27Sflorian 		/* read next label */
194ae8c6e27Sflorian 		if(sldns_buffer_remaining(pkt) < 1)
195ae8c6e27Sflorian 			return 0;
196ae8c6e27Sflorian 		labellen = sldns_buffer_read_u8(pkt);
197ae8c6e27Sflorian 		if(LABEL_IS_PTR(labellen)) {
198ae8c6e27Sflorian 			/* compression ptr */
199ae8c6e27Sflorian 			uint16_t ptr;
200ae8c6e27Sflorian 			if(sldns_buffer_remaining(pkt) < 1)
201ae8c6e27Sflorian 				return 0;
202ae8c6e27Sflorian 			ptr = PTR_OFFSET(labellen, sldns_buffer_read_u8(pkt));
203ae8c6e27Sflorian 			if(ptrcount++ > MAX_COMPRESS_PTRS)
204ae8c6e27Sflorian 				return 0; /* loop! */
205ae8c6e27Sflorian 			if(sldns_buffer_limit(pkt) <= ptr)
206ae8c6e27Sflorian 				return 0; /* out of bounds! */
207ae8c6e27Sflorian 			if(!endpos)
208ae8c6e27Sflorian 				endpos = sldns_buffer_position(pkt);
209ae8c6e27Sflorian 			sldns_buffer_set_position(pkt, ptr);
210ae8c6e27Sflorian 		} else {
211ae8c6e27Sflorian 			/* label contents */
212ae8c6e27Sflorian 			if(labellen > 0x3f)
213ae8c6e27Sflorian 				return 0; /* label too long */
214ae8c6e27Sflorian 			len += 1 + labellen;
215ae8c6e27Sflorian 			if(len > LDNS_MAX_DOMAINLEN)
216ae8c6e27Sflorian 				return 0;
217ae8c6e27Sflorian 			if(labellen == 0) {
218ae8c6e27Sflorian 				/* end of dname */
219ae8c6e27Sflorian 				break;
220ae8c6e27Sflorian 			}
221ae8c6e27Sflorian 			if(sldns_buffer_remaining(pkt) < labellen)
222ae8c6e27Sflorian 				return 0;
223ae8c6e27Sflorian 			sldns_buffer_skip(pkt, (ssize_t)labellen);
224ae8c6e27Sflorian 		}
225ae8c6e27Sflorian 	}
226ae8c6e27Sflorian 	if(endpos)
227ae8c6e27Sflorian 		sldns_buffer_set_position(pkt, endpos);
228ae8c6e27Sflorian 
229ae8c6e27Sflorian 	return len;
230ae8c6e27Sflorian }
231ae8c6e27Sflorian 
232ae8c6e27Sflorian int
dname_pkt_compare(sldns_buffer * pkt,uint8_t * d1,uint8_t * d2)233ae8c6e27Sflorian dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2)
234ae8c6e27Sflorian {
235ae8c6e27Sflorian 	uint8_t len1, len2;
236*5a7d75e6Ssthen 	int count1 = 0, count2 = 0;
237ae8c6e27Sflorian 	log_assert(pkt && d1 && d2);
238ae8c6e27Sflorian 	len1 = *d1++;
239ae8c6e27Sflorian 	len2 = *d2++;
240ae8c6e27Sflorian 	while( len1 != 0 || len2 != 0 ) {
241ae8c6e27Sflorian 		/* resolve ptrs */
242ae8c6e27Sflorian 		if(LABEL_IS_PTR(len1)) {
243*5a7d75e6Ssthen 			if((size_t)PTR_OFFSET(len1, *d1)
244*5a7d75e6Ssthen 				>= sldns_buffer_limit(pkt))
245*5a7d75e6Ssthen 				return -1;
246*5a7d75e6Ssthen 			if(count1++ > MAX_COMPRESS_PTRS)
247*5a7d75e6Ssthen 				return -1;
248ae8c6e27Sflorian 			d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1));
249ae8c6e27Sflorian 			len1 = *d1++;
250ae8c6e27Sflorian 			continue;
251ae8c6e27Sflorian 		}
252ae8c6e27Sflorian 		if(LABEL_IS_PTR(len2)) {
253*5a7d75e6Ssthen 			if((size_t)PTR_OFFSET(len2, *d2)
254*5a7d75e6Ssthen 				>= sldns_buffer_limit(pkt))
255*5a7d75e6Ssthen 				return 1;
256*5a7d75e6Ssthen 			if(count2++ > MAX_COMPRESS_PTRS)
257*5a7d75e6Ssthen 				return 1;
258ae8c6e27Sflorian 			d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2));
259ae8c6e27Sflorian 			len2 = *d2++;
260ae8c6e27Sflorian 			continue;
261ae8c6e27Sflorian 		}
262ae8c6e27Sflorian 		/* check label length */
263ae8c6e27Sflorian 		log_assert(len1 <= LDNS_MAX_LABELLEN);
264ae8c6e27Sflorian 		log_assert(len2 <= LDNS_MAX_LABELLEN);
265ae8c6e27Sflorian 		if(len1 != len2) {
266ae8c6e27Sflorian 			if(len1 < len2) return -1;
267ae8c6e27Sflorian 			return 1;
268ae8c6e27Sflorian 		}
269ae8c6e27Sflorian 		log_assert(len1 == len2 && len1 != 0);
270ae8c6e27Sflorian 		/* compare labels */
271ae8c6e27Sflorian 		while(len1--) {
272ae8c6e27Sflorian 			if(tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) {
273ae8c6e27Sflorian 				if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2))
274ae8c6e27Sflorian 					return -1;
275ae8c6e27Sflorian 				return 1;
276ae8c6e27Sflorian 			}
277ae8c6e27Sflorian 			d1++;
278ae8c6e27Sflorian 			d2++;
279ae8c6e27Sflorian 		}
280ae8c6e27Sflorian 		len1 = *d1++;
281ae8c6e27Sflorian 		len2 = *d2++;
282ae8c6e27Sflorian 	}
283ae8c6e27Sflorian 	return 0;
284ae8c6e27Sflorian }
285ae8c6e27Sflorian 
286ae8c6e27Sflorian hashvalue_type
dname_query_hash(uint8_t * dname,hashvalue_type h)287ae8c6e27Sflorian dname_query_hash(uint8_t* dname, hashvalue_type h)
288ae8c6e27Sflorian {
289ae8c6e27Sflorian 	uint8_t labuf[LDNS_MAX_LABELLEN+1];
290ae8c6e27Sflorian 	uint8_t lablen;
291ae8c6e27Sflorian 	int i;
292ae8c6e27Sflorian 
293ae8c6e27Sflorian 	/* preserve case of query, make hash label by label */
294ae8c6e27Sflorian 	lablen = *dname++;
295ae8c6e27Sflorian 	while(lablen) {
296ae8c6e27Sflorian 		log_assert(lablen <= LDNS_MAX_LABELLEN);
297ae8c6e27Sflorian 		labuf[0] = lablen;
298ae8c6e27Sflorian 		i=0;
299ae8c6e27Sflorian 		while(lablen--) {
300ae8c6e27Sflorian 			labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
301ae8c6e27Sflorian 			dname++;
302ae8c6e27Sflorian 		}
303ae8c6e27Sflorian 		h = hashlittle(labuf, labuf[0] + 1, h);
304ae8c6e27Sflorian 		lablen = *dname++;
305ae8c6e27Sflorian 	}
306ae8c6e27Sflorian 
307ae8c6e27Sflorian 	return h;
308ae8c6e27Sflorian }
309ae8c6e27Sflorian 
310ae8c6e27Sflorian hashvalue_type
dname_pkt_hash(sldns_buffer * pkt,uint8_t * dname,hashvalue_type h)311ae8c6e27Sflorian dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h)
312ae8c6e27Sflorian {
313ae8c6e27Sflorian 	uint8_t labuf[LDNS_MAX_LABELLEN+1];
314ae8c6e27Sflorian 	uint8_t lablen;
315ae8c6e27Sflorian 	int i;
316*5a7d75e6Ssthen 	int count = 0;
317ae8c6e27Sflorian 
318ae8c6e27Sflorian 	/* preserve case of query, make hash label by label */
319ae8c6e27Sflorian 	lablen = *dname++;
320ae8c6e27Sflorian 	while(lablen) {
321ae8c6e27Sflorian 		if(LABEL_IS_PTR(lablen)) {
322ae8c6e27Sflorian 			/* follow pointer */
323*5a7d75e6Ssthen 			if((size_t)PTR_OFFSET(lablen, *dname)
324*5a7d75e6Ssthen 				>= sldns_buffer_limit(pkt))
325*5a7d75e6Ssthen 				return h;
326*5a7d75e6Ssthen 			if(count++ > MAX_COMPRESS_PTRS)
327*5a7d75e6Ssthen 				return h;
328ae8c6e27Sflorian 			dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
329ae8c6e27Sflorian 			lablen = *dname++;
330ae8c6e27Sflorian 			continue;
331ae8c6e27Sflorian 		}
332ae8c6e27Sflorian 		log_assert(lablen <= LDNS_MAX_LABELLEN);
333ae8c6e27Sflorian 		labuf[0] = lablen;
334ae8c6e27Sflorian 		i=0;
335ae8c6e27Sflorian 		while(lablen--) {
336ae8c6e27Sflorian 			labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
337ae8c6e27Sflorian 			dname++;
338ae8c6e27Sflorian 		}
339ae8c6e27Sflorian 		h = hashlittle(labuf, labuf[0] + 1, h);
340ae8c6e27Sflorian 		lablen = *dname++;
341ae8c6e27Sflorian 	}
342ae8c6e27Sflorian 
343ae8c6e27Sflorian 	return h;
344ae8c6e27Sflorian }
345ae8c6e27Sflorian 
dname_pkt_copy(sldns_buffer * pkt,uint8_t * to,uint8_t * dname)346ae8c6e27Sflorian void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)
347ae8c6e27Sflorian {
348ae8c6e27Sflorian 	/* copy over the dname and decompress it at the same time */
34957403691Sflorian 	size_t comprcount = 0;
350ae8c6e27Sflorian 	size_t len = 0;
351ae8c6e27Sflorian 	uint8_t lablen;
352ae8c6e27Sflorian 	lablen = *dname++;
353ae8c6e27Sflorian 	while(lablen) {
354ae8c6e27Sflorian 		if(LABEL_IS_PTR(lablen)) {
35557403691Sflorian 			if(comprcount++ > MAX_COMPRESS_PTRS) {
35657403691Sflorian 				/* too many compression pointers */
35757403691Sflorian 				*to = 0; /* end the result prematurely */
35857403691Sflorian 				return;
35957403691Sflorian 			}
360ae8c6e27Sflorian 			/* follow pointer */
361*5a7d75e6Ssthen 			if((size_t)PTR_OFFSET(lablen, *dname)
362*5a7d75e6Ssthen 				>= sldns_buffer_limit(pkt))
363*5a7d75e6Ssthen 				return;
364ae8c6e27Sflorian 			dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
365ae8c6e27Sflorian 			lablen = *dname++;
366ae8c6e27Sflorian 			continue;
367ae8c6e27Sflorian 		}
36857403691Sflorian 		if(lablen > LDNS_MAX_LABELLEN) {
36957403691Sflorian 			*to = 0; /* end the result prematurely */
37057403691Sflorian 			return;
37157403691Sflorian 		}
372ae8c6e27Sflorian 		log_assert(lablen <= LDNS_MAX_LABELLEN);
373ae8c6e27Sflorian 		len += (size_t)lablen+1;
374ae8c6e27Sflorian 		if(len >= LDNS_MAX_DOMAINLEN) {
375ae8c6e27Sflorian 			*to = 0; /* end the result prematurely */
376ae8c6e27Sflorian 			log_err("bad dname in dname_pkt_copy");
377ae8c6e27Sflorian 			return;
378ae8c6e27Sflorian 		}
379ae8c6e27Sflorian 		*to++ = lablen;
380ae8c6e27Sflorian 		memmove(to, dname, lablen);
381ae8c6e27Sflorian 		dname += lablen;
382ae8c6e27Sflorian 		to += lablen;
383ae8c6e27Sflorian 		lablen = *dname++;
384ae8c6e27Sflorian 	}
385ae8c6e27Sflorian 	/* copy last \0 */
386ae8c6e27Sflorian 	*to = 0;
387ae8c6e27Sflorian }
388ae8c6e27Sflorian 
dname_print(FILE * out,struct sldns_buffer * pkt,uint8_t * dname)389ae8c6e27Sflorian void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname)
390ae8c6e27Sflorian {
391ae8c6e27Sflorian 	uint8_t lablen;
392*5a7d75e6Ssthen 	int count = 0;
393ae8c6e27Sflorian 	if(!out) out = stdout;
394ae8c6e27Sflorian 	if(!dname) return;
395ae8c6e27Sflorian 
396ae8c6e27Sflorian 	lablen = *dname++;
397ae8c6e27Sflorian 	if(!lablen)
398ae8c6e27Sflorian 		fputc('.', out);
399ae8c6e27Sflorian 	while(lablen) {
400ae8c6e27Sflorian 		if(LABEL_IS_PTR(lablen)) {
401ae8c6e27Sflorian 			/* follow pointer */
402ae8c6e27Sflorian 			if(!pkt) {
403ae8c6e27Sflorian 				fputs("??compressionptr??", out);
404ae8c6e27Sflorian 				return;
405ae8c6e27Sflorian 			}
406*5a7d75e6Ssthen 			if((size_t)PTR_OFFSET(lablen, *dname)
407*5a7d75e6Ssthen 				>= sldns_buffer_limit(pkt)) {
408*5a7d75e6Ssthen 				fputs("??compressionptr??", out);
409*5a7d75e6Ssthen 				return;
410*5a7d75e6Ssthen 			}
411*5a7d75e6Ssthen 			if(count++ > MAX_COMPRESS_PTRS) {
412*5a7d75e6Ssthen 				fputs("??compressionptr??", out);
413*5a7d75e6Ssthen 				return;
414*5a7d75e6Ssthen 			}
415ae8c6e27Sflorian 			dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
416ae8c6e27Sflorian 			lablen = *dname++;
417ae8c6e27Sflorian 			continue;
418ae8c6e27Sflorian 		}
419ae8c6e27Sflorian 		if(lablen > LDNS_MAX_LABELLEN) {
420ae8c6e27Sflorian 			fputs("??extendedlabel??", out);
421ae8c6e27Sflorian 			return;
422ae8c6e27Sflorian 		}
423ae8c6e27Sflorian 		while(lablen--)
424ae8c6e27Sflorian 			fputc((int)*dname++, out);
425ae8c6e27Sflorian 		fputc('.', out);
426ae8c6e27Sflorian 		lablen = *dname++;
427ae8c6e27Sflorian 	}
428ae8c6e27Sflorian }
429ae8c6e27Sflorian 
430ae8c6e27Sflorian int
dname_count_labels(uint8_t * dname)431ae8c6e27Sflorian dname_count_labels(uint8_t* dname)
432ae8c6e27Sflorian {
433ae8c6e27Sflorian 	uint8_t lablen;
434ae8c6e27Sflorian 	int labs = 1;
435ae8c6e27Sflorian 
436ae8c6e27Sflorian 	lablen = *dname++;
437ae8c6e27Sflorian 	while(lablen) {
438ae8c6e27Sflorian 		labs++;
439ae8c6e27Sflorian 		dname += lablen;
440ae8c6e27Sflorian 		lablen = *dname++;
441ae8c6e27Sflorian 	}
442ae8c6e27Sflorian 	return labs;
443ae8c6e27Sflorian }
444ae8c6e27Sflorian 
445ae8c6e27Sflorian int
dname_count_size_labels(uint8_t * dname,size_t * size)446ae8c6e27Sflorian dname_count_size_labels(uint8_t* dname, size_t* size)
447ae8c6e27Sflorian {
448ae8c6e27Sflorian 	uint8_t lablen;
449ae8c6e27Sflorian 	int labs = 1;
450ae8c6e27Sflorian 	size_t sz = 1;
451ae8c6e27Sflorian 
452ae8c6e27Sflorian 	lablen = *dname++;
453ae8c6e27Sflorian 	while(lablen) {
454ae8c6e27Sflorian 		labs++;
455ae8c6e27Sflorian 		sz += lablen+1;
456ae8c6e27Sflorian 		dname += lablen;
457ae8c6e27Sflorian 		lablen = *dname++;
458ae8c6e27Sflorian 	}
459ae8c6e27Sflorian 	*size = sz;
460ae8c6e27Sflorian 	return labs;
461ae8c6e27Sflorian }
462ae8c6e27Sflorian 
463ae8c6e27Sflorian /**
464ae8c6e27Sflorian  * Compare labels in memory, lowercase while comparing.
465ae8c6e27Sflorian  * @param p1: label 1
466ae8c6e27Sflorian  * @param p2: label 2
467ae8c6e27Sflorian  * @param len: number of bytes to compare.
468ae8c6e27Sflorian  * @return: 0, -1, +1 comparison result.
469ae8c6e27Sflorian  */
470ae8c6e27Sflorian static int
memlowercmp(uint8_t * p1,uint8_t * p2,uint8_t len)471ae8c6e27Sflorian memlowercmp(uint8_t* p1, uint8_t* p2, uint8_t len)
472ae8c6e27Sflorian {
473ae8c6e27Sflorian 	while(len--) {
474ae8c6e27Sflorian 		if(*p1 != *p2 && tolower((unsigned char)*p1) != tolower((unsigned char)*p2)) {
475ae8c6e27Sflorian 			if(tolower((unsigned char)*p1) < tolower((unsigned char)*p2))
476ae8c6e27Sflorian 				return -1;
477ae8c6e27Sflorian 			return 1;
478ae8c6e27Sflorian 		}
479ae8c6e27Sflorian 		p1++;
480ae8c6e27Sflorian 		p2++;
481ae8c6e27Sflorian 	}
482ae8c6e27Sflorian 	return 0;
483ae8c6e27Sflorian }
484ae8c6e27Sflorian 
485ae8c6e27Sflorian int
dname_lab_cmp(uint8_t * d1,int labs1,uint8_t * d2,int labs2,int * mlabs)486ae8c6e27Sflorian dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs)
487ae8c6e27Sflorian {
488ae8c6e27Sflorian 	uint8_t len1, len2;
489ae8c6e27Sflorian 	int atlabel = labs1;
490ae8c6e27Sflorian 	int lastmlabs;
491ae8c6e27Sflorian 	int lastdiff = 0;
492ae8c6e27Sflorian 	/* first skip so that we compare same label. */
493ae8c6e27Sflorian 	if(labs1 > labs2) {
494ae8c6e27Sflorian 		while(atlabel > labs2) {
495ae8c6e27Sflorian 			len1 = *d1++;
496ae8c6e27Sflorian 			d1 += len1;
497ae8c6e27Sflorian 			atlabel--;
498ae8c6e27Sflorian 		}
499ae8c6e27Sflorian 		log_assert(atlabel == labs2);
500ae8c6e27Sflorian 	} else if(labs1 < labs2) {
501ae8c6e27Sflorian 		atlabel = labs2;
502ae8c6e27Sflorian 		while(atlabel > labs1) {
503ae8c6e27Sflorian 			len2 = *d2++;
504ae8c6e27Sflorian 			d2 += len2;
505ae8c6e27Sflorian 			atlabel--;
506ae8c6e27Sflorian 		}
507ae8c6e27Sflorian 		log_assert(atlabel == labs1);
508ae8c6e27Sflorian 	}
509ae8c6e27Sflorian 	lastmlabs = atlabel+1;
510ae8c6e27Sflorian 	/* now at same label in d1 and d2, atlabel */
511ae8c6e27Sflorian 	/* www.example.com.                  */
512ae8c6e27Sflorian 	/* 4   3       2  1   atlabel number */
513ae8c6e27Sflorian 	/* repeat until at root label (which is always the same) */
514ae8c6e27Sflorian 	while(atlabel > 1) {
515ae8c6e27Sflorian 		len1 = *d1++;
516ae8c6e27Sflorian 		len2 = *d2++;
517ae8c6e27Sflorian 		if(len1 != len2) {
518ae8c6e27Sflorian 			log_assert(len1 != 0 && len2 != 0);
519ae8c6e27Sflorian 			if(len1<len2)
520ae8c6e27Sflorian 				lastdiff = -1;
521ae8c6e27Sflorian 			else	lastdiff = 1;
522ae8c6e27Sflorian 			lastmlabs = atlabel;
523ae8c6e27Sflorian 			d1 += len1;
524ae8c6e27Sflorian 			d2 += len2;
525ae8c6e27Sflorian 		} else {
526ae8c6e27Sflorian 			/* memlowercmp is inlined here; or just like
527ae8c6e27Sflorian 			 * if((c=memlowercmp(d1, d2, len1)) != 0) {
528ae8c6e27Sflorian 			 *	lastdiff = c;
529ae8c6e27Sflorian 			 *	lastmlabs = atlabel; } apart from d1++,d2++ */
530ae8c6e27Sflorian 			while(len1) {
531ae8c6e27Sflorian 				if(*d1 != *d2 && tolower((unsigned char)*d1)
532ae8c6e27Sflorian 					!= tolower((unsigned char)*d2)) {
533ae8c6e27Sflorian 					if(tolower((unsigned char)*d1) <
534ae8c6e27Sflorian 						tolower((unsigned char)*d2)) {
535ae8c6e27Sflorian 						lastdiff = -1;
536ae8c6e27Sflorian 						lastmlabs = atlabel;
537ae8c6e27Sflorian 						d1 += len1;
538ae8c6e27Sflorian 						d2 += len1;
539ae8c6e27Sflorian 						break;
540ae8c6e27Sflorian 					}
541ae8c6e27Sflorian 					lastdiff = 1;
542ae8c6e27Sflorian 					lastmlabs = atlabel;
543ae8c6e27Sflorian 					d1 += len1;
544ae8c6e27Sflorian 					d2 += len1;
545ae8c6e27Sflorian 					break; /* out of memlowercmp */
546ae8c6e27Sflorian 				}
547ae8c6e27Sflorian 				d1++;
548ae8c6e27Sflorian 				d2++;
549ae8c6e27Sflorian 				len1--;
550ae8c6e27Sflorian 			}
551ae8c6e27Sflorian 		}
552ae8c6e27Sflorian 		atlabel--;
553ae8c6e27Sflorian 	}
554ae8c6e27Sflorian 	/* last difference atlabel number, so number of labels matching,
555ae8c6e27Sflorian 	 * at the right side, is one less. */
556ae8c6e27Sflorian 	*mlabs = lastmlabs-1;
557ae8c6e27Sflorian 	if(lastdiff == 0) {
558ae8c6e27Sflorian 		/* all labels compared were equal, check if one has more
559ae8c6e27Sflorian 		 * labels, so that example.com. > com. */
560ae8c6e27Sflorian 		if(labs1 > labs2)
561ae8c6e27Sflorian 			return 1;
562ae8c6e27Sflorian 		else if(labs1 < labs2)
563ae8c6e27Sflorian 			return -1;
564ae8c6e27Sflorian 	}
565ae8c6e27Sflorian 	return lastdiff;
566ae8c6e27Sflorian }
567ae8c6e27Sflorian 
568ae8c6e27Sflorian int
dname_lab_startswith(uint8_t * label,char * prefix,char ** endptr)569ae8c6e27Sflorian dname_lab_startswith(uint8_t* label, char* prefix, char** endptr)
570ae8c6e27Sflorian {
571ae8c6e27Sflorian 	size_t plen = strlen(prefix);
572ae8c6e27Sflorian 	size_t orig_plen = plen;
573ae8c6e27Sflorian 	size_t lablen = (size_t)*label;
574ae8c6e27Sflorian 	if(plen > lablen)
575ae8c6e27Sflorian 		return 0;
576ae8c6e27Sflorian 	label++;
577ae8c6e27Sflorian 	while(plen--) {
578ae8c6e27Sflorian 		if(*prefix != tolower((unsigned char)*label)) {
579ae8c6e27Sflorian 			return 0;
580ae8c6e27Sflorian 		}
581ae8c6e27Sflorian 		prefix++; label++;
582ae8c6e27Sflorian 	}
583ae8c6e27Sflorian 	if(orig_plen < lablen)
584ae8c6e27Sflorian 		*endptr = (char *)label;
585ae8c6e27Sflorian 	else
586ae8c6e27Sflorian 		/* prefix length == label length */
587ae8c6e27Sflorian 		*endptr = NULL;
588ae8c6e27Sflorian 	return 1;
589ae8c6e27Sflorian }
590ae8c6e27Sflorian 
591ae8c6e27Sflorian int
dname_has_label(uint8_t * dname,size_t dnamelen,uint8_t * label)592d32eb43cSflorian dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label)
593d32eb43cSflorian {
594d32eb43cSflorian 	size_t len;
595d32eb43cSflorian 
596d32eb43cSflorian 	/* 1 byte needed for the label length */
597d32eb43cSflorian 	if(dnamelen < 1)
598d32eb43cSflorian 		return 0;
599d32eb43cSflorian 
600d32eb43cSflorian 	len = *dname;
601d32eb43cSflorian 	while(len <= dnamelen) {
602d32eb43cSflorian 		if(!(*dname)) {
603d32eb43cSflorian 			if(*dname == *label)
604d32eb43cSflorian 				return 1; /* empty label match */
605d32eb43cSflorian 			/* termination label found, stop iterating */
606d32eb43cSflorian 			return 0;
607d32eb43cSflorian 		}
608d32eb43cSflorian 		if(*dname == *label && *label &&
609d32eb43cSflorian 			memlowercmp(dname+1, label+1, *dname) == 0)
610d32eb43cSflorian 			return 1;
611d32eb43cSflorian 		len += *dname;
612d32eb43cSflorian 		dname += *dname;
613d32eb43cSflorian 		dname++;
614d32eb43cSflorian 		len++;
615d32eb43cSflorian 	}
616d32eb43cSflorian 	return 0;
617d32eb43cSflorian }
618d32eb43cSflorian 
619d32eb43cSflorian int
dname_buffer_write(sldns_buffer * pkt,uint8_t * dname)620ae8c6e27Sflorian dname_buffer_write(sldns_buffer* pkt, uint8_t* dname)
621ae8c6e27Sflorian {
622ae8c6e27Sflorian 	uint8_t lablen;
623ae8c6e27Sflorian 
624ae8c6e27Sflorian 	if(sldns_buffer_remaining(pkt) < 1)
625ae8c6e27Sflorian 		return 0;
626ae8c6e27Sflorian 	lablen = *dname++;
627ae8c6e27Sflorian 	sldns_buffer_write_u8(pkt, lablen);
628ae8c6e27Sflorian 	while(lablen) {
629ae8c6e27Sflorian 		if(sldns_buffer_remaining(pkt) < (size_t)lablen+1)
630ae8c6e27Sflorian 			return 0;
631ae8c6e27Sflorian 		sldns_buffer_write(pkt, dname, lablen);
632ae8c6e27Sflorian 		dname += lablen;
633ae8c6e27Sflorian 		lablen = *dname++;
634ae8c6e27Sflorian 		sldns_buffer_write_u8(pkt, lablen);
635ae8c6e27Sflorian 	}
636ae8c6e27Sflorian 	return 1;
637ae8c6e27Sflorian }
638ae8c6e27Sflorian 
dname_str(uint8_t * dname,char * str)639ae8c6e27Sflorian void dname_str(uint8_t* dname, char* str)
640ae8c6e27Sflorian {
641ae8c6e27Sflorian 	size_t len = 0;
642ae8c6e27Sflorian 	uint8_t lablen = 0;
643ae8c6e27Sflorian 	char* s = str;
644ae8c6e27Sflorian 	if(!dname || !*dname) {
645ae8c6e27Sflorian 		*s++ = '.';
646ae8c6e27Sflorian 		*s = 0;
647ae8c6e27Sflorian 		return;
648ae8c6e27Sflorian 	}
649ae8c6e27Sflorian 	lablen = *dname++;
650ae8c6e27Sflorian 	while(lablen) {
651ae8c6e27Sflorian 		if(lablen > LDNS_MAX_LABELLEN) {
652ae8c6e27Sflorian 			*s++ = '#';
653ae8c6e27Sflorian 			*s = 0;
654ae8c6e27Sflorian 			return;
655ae8c6e27Sflorian 		}
656ae8c6e27Sflorian 		len += lablen+1;
657ae8c6e27Sflorian 		if(len >= LDNS_MAX_DOMAINLEN-1) {
658ae8c6e27Sflorian 			*s++ = '&';
659ae8c6e27Sflorian 			*s = 0;
660ae8c6e27Sflorian 			return;
661ae8c6e27Sflorian 		}
662ae8c6e27Sflorian 		while(lablen--) {
663ae8c6e27Sflorian 			if(isalnum((unsigned char)*dname)
664ae8c6e27Sflorian 				|| *dname == '-' || *dname == '_'
665ae8c6e27Sflorian 				|| *dname == '*')
666ae8c6e27Sflorian 				*s++ = *(char*)dname++;
667ae8c6e27Sflorian 			else	{
668ae8c6e27Sflorian 				*s++ = '?';
669ae8c6e27Sflorian 				dname++;
670ae8c6e27Sflorian 			}
671ae8c6e27Sflorian 		}
672ae8c6e27Sflorian 		*s++ = '.';
673ae8c6e27Sflorian 		lablen = *dname++;
674ae8c6e27Sflorian 	}
675ae8c6e27Sflorian 	*s = 0;
676ae8c6e27Sflorian }
677ae8c6e27Sflorian 
678ae8c6e27Sflorian int
dname_strict_subdomain(uint8_t * d1,int labs1,uint8_t * d2,int labs2)679ae8c6e27Sflorian dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2)
680ae8c6e27Sflorian {
681ae8c6e27Sflorian 	int m;
682ae8c6e27Sflorian 	/* check subdomain: d1: www.example.com. and d2: example.com. */
683ae8c6e27Sflorian 	if(labs2 >= labs1)
684ae8c6e27Sflorian 		return 0;
685ae8c6e27Sflorian 	if(dname_lab_cmp(d1, labs1, d2, labs2, &m) > 0) {
686ae8c6e27Sflorian 		/* subdomain if all labels match */
687ae8c6e27Sflorian 		return (m == labs2);
688ae8c6e27Sflorian 	}
689ae8c6e27Sflorian 	return 0;
690ae8c6e27Sflorian }
691ae8c6e27Sflorian 
692ae8c6e27Sflorian int
dname_strict_subdomain_c(uint8_t * d1,uint8_t * d2)693ae8c6e27Sflorian dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2)
694ae8c6e27Sflorian {
695ae8c6e27Sflorian 	return dname_strict_subdomain(d1, dname_count_labels(d1), d2,
696ae8c6e27Sflorian 		dname_count_labels(d2));
697ae8c6e27Sflorian }
698ae8c6e27Sflorian 
699ae8c6e27Sflorian int
dname_subdomain_c(uint8_t * d1,uint8_t * d2)700ae8c6e27Sflorian dname_subdomain_c(uint8_t* d1, uint8_t* d2)
701ae8c6e27Sflorian {
702ae8c6e27Sflorian 	int m;
703ae8c6e27Sflorian 	/* check subdomain: d1: www.example.com. and d2: example.com. */
704ae8c6e27Sflorian 	/*  	or 	    d1: example.com. and d2: example.com. */
705ae8c6e27Sflorian 	int labs1 = dname_count_labels(d1);
706ae8c6e27Sflorian 	int labs2 = dname_count_labels(d2);
707ae8c6e27Sflorian 	if(labs2 > labs1)
708ae8c6e27Sflorian 		return 0;
709ae8c6e27Sflorian 	if(dname_lab_cmp(d1, labs1, d2, labs2, &m) < 0) {
710ae8c6e27Sflorian 		/* must have been example.com , www.example.com - wrong */
711ae8c6e27Sflorian 		/* or otherwise different dnames */
712ae8c6e27Sflorian 		return 0;
713ae8c6e27Sflorian 	}
714ae8c6e27Sflorian 	return (m == labs2);
715ae8c6e27Sflorian }
716ae8c6e27Sflorian 
717ae8c6e27Sflorian int
dname_is_root(uint8_t * dname)718ae8c6e27Sflorian dname_is_root(uint8_t* dname)
719ae8c6e27Sflorian {
720ae8c6e27Sflorian 	uint8_t len;
721ae8c6e27Sflorian 	log_assert(dname);
722ae8c6e27Sflorian 	len = dname[0];
723ae8c6e27Sflorian 	log_assert(!LABEL_IS_PTR(len));
724ae8c6e27Sflorian 	return (len == 0);
725ae8c6e27Sflorian }
726ae8c6e27Sflorian 
727ae8c6e27Sflorian void
dname_remove_label(uint8_t ** dname,size_t * len)728ae8c6e27Sflorian dname_remove_label(uint8_t** dname, size_t* len)
729ae8c6e27Sflorian {
730ae8c6e27Sflorian 	size_t lablen;
731ae8c6e27Sflorian 	log_assert(dname && *dname && len);
732ae8c6e27Sflorian 	lablen = (*dname)[0];
733ae8c6e27Sflorian 	log_assert(!LABEL_IS_PTR(lablen));
734ae8c6e27Sflorian 	log_assert(*len > lablen);
735ae8c6e27Sflorian 	if(lablen == 0)
736ae8c6e27Sflorian 		return; /* do not modify root label */
737ae8c6e27Sflorian 	*len -= lablen+1;
738ae8c6e27Sflorian 	*dname += lablen+1;
739ae8c6e27Sflorian }
740ae8c6e27Sflorian 
741ae8c6e27Sflorian void
dname_remove_labels(uint8_t ** dname,size_t * len,int n)742ae8c6e27Sflorian dname_remove_labels(uint8_t** dname, size_t* len, int n)
743ae8c6e27Sflorian {
744ae8c6e27Sflorian 	int i;
745ae8c6e27Sflorian 	for(i=0; i<n; i++)
746ae8c6e27Sflorian 		dname_remove_label(dname, len);
747ae8c6e27Sflorian }
748ae8c6e27Sflorian 
749ae8c6e27Sflorian int
dname_signame_label_count(uint8_t * dname)750ae8c6e27Sflorian dname_signame_label_count(uint8_t* dname)
751ae8c6e27Sflorian {
752ae8c6e27Sflorian 	uint8_t lablen;
753ae8c6e27Sflorian 	int count = 0;
754ae8c6e27Sflorian 	if(!*dname)
755ae8c6e27Sflorian 		return 0;
756ae8c6e27Sflorian 	if(dname[0] == 1 && dname[1] == '*')
757ae8c6e27Sflorian 		dname += 2;
758ae8c6e27Sflorian 	lablen = dname[0];
759ae8c6e27Sflorian 	while(lablen) {
760ae8c6e27Sflorian 		count++;
761ae8c6e27Sflorian 		dname += lablen;
762ae8c6e27Sflorian 		dname += 1;
763ae8c6e27Sflorian 		lablen = dname[0];
764ae8c6e27Sflorian 	}
765ae8c6e27Sflorian 	return count;
766ae8c6e27Sflorian }
767ae8c6e27Sflorian 
768ae8c6e27Sflorian int
dname_is_wild(uint8_t * dname)769ae8c6e27Sflorian dname_is_wild(uint8_t* dname)
770ae8c6e27Sflorian {
771ae8c6e27Sflorian 	return (dname[0] == 1 && dname[1] == '*');
772ae8c6e27Sflorian }
773ae8c6e27Sflorian 
774ae8c6e27Sflorian /**
775ae8c6e27Sflorian  * Compare labels in memory, lowercase while comparing.
776ae8c6e27Sflorian  * Returns canonical order for labels. If all is equal, the
777ae8c6e27Sflorian  * shortest is first.
778ae8c6e27Sflorian  *
779ae8c6e27Sflorian  * @param p1: label 1
780ae8c6e27Sflorian  * @param len1: length of label 1.
781ae8c6e27Sflorian  * @param p2: label 2
782ae8c6e27Sflorian  * @param len2: length of label 2.
783ae8c6e27Sflorian  * @return: 0, -1, +1 comparison result.
784ae8c6e27Sflorian  */
785ae8c6e27Sflorian static int
memcanoncmp(uint8_t * p1,uint8_t len1,uint8_t * p2,uint8_t len2)786ae8c6e27Sflorian memcanoncmp(uint8_t* p1, uint8_t len1, uint8_t* p2, uint8_t len2)
787ae8c6e27Sflorian {
788ae8c6e27Sflorian 	uint8_t min = (len1<len2)?len1:len2;
789ae8c6e27Sflorian 	int c = memlowercmp(p1, p2, min);
790ae8c6e27Sflorian 	if(c != 0)
791ae8c6e27Sflorian 		return c;
792ae8c6e27Sflorian 	/* equal, see who is shortest */
793ae8c6e27Sflorian 	if(len1 < len2)
794ae8c6e27Sflorian 		return -1;
795ae8c6e27Sflorian 	if(len1 > len2)
796ae8c6e27Sflorian 		return 1;
797ae8c6e27Sflorian 	return 0;
798ae8c6e27Sflorian }
799ae8c6e27Sflorian 
800ae8c6e27Sflorian 
801ae8c6e27Sflorian int
dname_canon_lab_cmp(uint8_t * d1,int labs1,uint8_t * d2,int labs2,int * mlabs)802ae8c6e27Sflorian dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs)
803ae8c6e27Sflorian {
804ae8c6e27Sflorian 	/* like dname_lab_cmp, but with different label comparison,
805ae8c6e27Sflorian 	 * empty character sorts before \000.
806ae8c6e27Sflorian 	 * So   ylyly is before z. */
807ae8c6e27Sflorian 	uint8_t len1, len2;
808ae8c6e27Sflorian 	int atlabel = labs1;
809ae8c6e27Sflorian 	int lastmlabs;
810ae8c6e27Sflorian 	int lastdiff = 0;
811ae8c6e27Sflorian 	int c;
812ae8c6e27Sflorian 	/* first skip so that we compare same label. */
813ae8c6e27Sflorian 	if(labs1 > labs2) {
814ae8c6e27Sflorian 		while(atlabel > labs2) {
815ae8c6e27Sflorian 			len1 = *d1++;
816ae8c6e27Sflorian 			d1 += len1;
817ae8c6e27Sflorian 			atlabel--;
818ae8c6e27Sflorian 		}
819ae8c6e27Sflorian 		log_assert(atlabel == labs2);
820ae8c6e27Sflorian 	} else if(labs1 < labs2) {
821ae8c6e27Sflorian 		atlabel = labs2;
822ae8c6e27Sflorian 		while(atlabel > labs1) {
823ae8c6e27Sflorian 			len2 = *d2++;
824ae8c6e27Sflorian 			d2 += len2;
825ae8c6e27Sflorian 			atlabel--;
826ae8c6e27Sflorian 		}
827ae8c6e27Sflorian 		log_assert(atlabel == labs1);
828ae8c6e27Sflorian 	}
829ae8c6e27Sflorian 	lastmlabs = atlabel+1;
830ae8c6e27Sflorian 	/* now at same label in d1 and d2, atlabel */
831ae8c6e27Sflorian 	/* www.example.com.                  */
832ae8c6e27Sflorian 	/* 4   3       2  1   atlabel number */
833ae8c6e27Sflorian 	/* repeat until at root label (which is always the same) */
834ae8c6e27Sflorian 	while(atlabel > 1) {
835ae8c6e27Sflorian 		len1 = *d1++;
836ae8c6e27Sflorian 		len2 = *d2++;
837ae8c6e27Sflorian 
838ae8c6e27Sflorian 		if((c=memcanoncmp(d1, len1, d2, len2)) != 0) {
839ae8c6e27Sflorian 			if(c<0)
840ae8c6e27Sflorian 				lastdiff = -1;
841ae8c6e27Sflorian 			else	lastdiff = 1;
842ae8c6e27Sflorian 			lastmlabs = atlabel;
843ae8c6e27Sflorian 		}
844ae8c6e27Sflorian 
845ae8c6e27Sflorian 		d1 += len1;
846ae8c6e27Sflorian 		d2 += len2;
847ae8c6e27Sflorian 		atlabel--;
848ae8c6e27Sflorian 	}
849ae8c6e27Sflorian 	/* last difference atlabel number, so number of labels matching,
850ae8c6e27Sflorian 	 * at the right side, is one less. */
851ae8c6e27Sflorian 	*mlabs = lastmlabs-1;
852ae8c6e27Sflorian 	if(lastdiff == 0) {
853ae8c6e27Sflorian 		/* all labels compared were equal, check if one has more
854ae8c6e27Sflorian 		 * labels, so that example.com. > com. */
855ae8c6e27Sflorian 		if(labs1 > labs2)
856ae8c6e27Sflorian 			return 1;
857ae8c6e27Sflorian 		else if(labs1 < labs2)
858ae8c6e27Sflorian 			return -1;
859ae8c6e27Sflorian 	}
860ae8c6e27Sflorian 	return lastdiff;
861ae8c6e27Sflorian }
862ae8c6e27Sflorian 
863ae8c6e27Sflorian int
dname_canonical_compare(uint8_t * d1,uint8_t * d2)864ae8c6e27Sflorian dname_canonical_compare(uint8_t* d1, uint8_t* d2)
865ae8c6e27Sflorian {
866ae8c6e27Sflorian 	int labs1, labs2, m;
867ae8c6e27Sflorian 	labs1 = dname_count_labels(d1);
868ae8c6e27Sflorian 	labs2 = dname_count_labels(d2);
869ae8c6e27Sflorian 	return dname_canon_lab_cmp(d1, labs1, d2, labs2, &m);
870ae8c6e27Sflorian }
871ae8c6e27Sflorian 
dname_get_shared_topdomain(uint8_t * d1,uint8_t * d2)872ae8c6e27Sflorian uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2)
873ae8c6e27Sflorian {
874ae8c6e27Sflorian 	int labs1, labs2, m;
875ae8c6e27Sflorian 	size_t len = LDNS_MAX_DOMAINLEN;
876ae8c6e27Sflorian 	labs1 = dname_count_labels(d1);
877ae8c6e27Sflorian 	labs2 = dname_count_labels(d2);
878ae8c6e27Sflorian 	(void)dname_lab_cmp(d1, labs1, d2, labs2, &m);
879ae8c6e27Sflorian 	dname_remove_labels(&d1, &len, labs1-m);
880ae8c6e27Sflorian 	return d1;
881ae8c6e27Sflorian }
882