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