xref: /freebsd/contrib/unbound/util/data/packed_rrset.c (revision b7c0c8c18e0f12bc22e251fbcabad719b364a38a)
1b7579f77SDag-Erling Smørgrav /*
2b7579f77SDag-Erling Smørgrav  * util/data/packed_rrset.c - data storage for a set of resource records.
3b7579f77SDag-Erling Smørgrav  *
4b7579f77SDag-Erling Smørgrav  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5b7579f77SDag-Erling Smørgrav  *
6b7579f77SDag-Erling Smørgrav  * This software is open source.
7b7579f77SDag-Erling Smørgrav  *
8b7579f77SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
9b7579f77SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
10b7579f77SDag-Erling Smørgrav  * are met:
11b7579f77SDag-Erling Smørgrav  *
12b7579f77SDag-Erling Smørgrav  * Redistributions of source code must retain the above copyright notice,
13b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer.
14b7579f77SDag-Erling Smørgrav  *
15b7579f77SDag-Erling Smørgrav  * Redistributions in binary form must reproduce the above copyright notice,
16b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer in the documentation
17b7579f77SDag-Erling Smørgrav  * and/or other materials provided with the distribution.
18b7579f77SDag-Erling Smørgrav  *
19b7579f77SDag-Erling Smørgrav  * Neither the name of the NLNET LABS nor the names of its contributors may
20b7579f77SDag-Erling Smørgrav  * be used to endorse or promote products derived from this software without
21b7579f77SDag-Erling Smørgrav  * specific prior written permission.
22b7579f77SDag-Erling Smørgrav  *
23b7579f77SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2417d15b25SDag-Erling Smørgrav  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2517d15b25SDag-Erling Smørgrav  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2617d15b25SDag-Erling Smørgrav  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2717d15b25SDag-Erling Smørgrav  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2817d15b25SDag-Erling Smørgrav  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2917d15b25SDag-Erling Smørgrav  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3017d15b25SDag-Erling Smørgrav  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3117d15b25SDag-Erling Smørgrav  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3217d15b25SDag-Erling Smørgrav  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3317d15b25SDag-Erling Smørgrav  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34b7579f77SDag-Erling Smørgrav  */
35b7579f77SDag-Erling Smørgrav 
36b7579f77SDag-Erling Smørgrav /**
37b7579f77SDag-Erling Smørgrav  * \file
38b7579f77SDag-Erling Smørgrav  *
39b7579f77SDag-Erling Smørgrav  * This file contains the data storage for RRsets.
40b7579f77SDag-Erling Smørgrav  */
41b7579f77SDag-Erling Smørgrav 
42b7579f77SDag-Erling Smørgrav #include "config.h"
43091e9e46SCy Schubert #include "util/data/msgparse.h"
44b7579f77SDag-Erling Smørgrav #include "util/data/packed_rrset.h"
45b7579f77SDag-Erling Smørgrav #include "util/data/dname.h"
46b7579f77SDag-Erling Smørgrav #include "util/storage/lookup3.h"
47b7579f77SDag-Erling Smørgrav #include "util/log.h"
48b7579f77SDag-Erling Smørgrav #include "util/alloc.h"
49b7579f77SDag-Erling Smørgrav #include "util/regional.h"
50b7579f77SDag-Erling Smørgrav #include "util/net_help.h"
5109a3aaf3SDag-Erling Smørgrav #include "sldns/rrdef.h"
5209a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h"
5309a3aaf3SDag-Erling Smørgrav #include "sldns/wire2str.h"
54b7579f77SDag-Erling Smørgrav 
55b7579f77SDag-Erling Smørgrav void
ub_packed_rrset_parsedelete(struct ub_packed_rrset_key * pkey,struct alloc_cache * alloc)56b7579f77SDag-Erling Smørgrav ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey,
57b7579f77SDag-Erling Smørgrav         struct alloc_cache* alloc)
58b7579f77SDag-Erling Smørgrav {
59b7579f77SDag-Erling Smørgrav 	if(!pkey)
60b7579f77SDag-Erling Smørgrav 		return;
61b7579f77SDag-Erling Smørgrav 	free(pkey->entry.data);
62b7579f77SDag-Erling Smørgrav 	pkey->entry.data = NULL;
63b7579f77SDag-Erling Smørgrav 	free(pkey->rk.dname);
64b7579f77SDag-Erling Smørgrav 	pkey->rk.dname = NULL;
65b7579f77SDag-Erling Smørgrav 	pkey->id = 0;
66b7579f77SDag-Erling Smørgrav 	alloc_special_release(alloc, pkey);
67b7579f77SDag-Erling Smørgrav }
68b7579f77SDag-Erling Smørgrav 
69b7579f77SDag-Erling Smørgrav size_t
ub_rrset_sizefunc(void * key,void * data)70b7579f77SDag-Erling Smørgrav ub_rrset_sizefunc(void* key, void* data)
71b7579f77SDag-Erling Smørgrav {
72b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key;
73b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* d = (struct packed_rrset_data*)data;
74b7579f77SDag-Erling Smørgrav 	size_t s = sizeof(struct ub_packed_rrset_key) + k->rk.dname_len;
75b7579f77SDag-Erling Smørgrav 	s += packed_rrset_sizeof(d) + lock_get_mem(&k->entry.lock);
76b7579f77SDag-Erling Smørgrav 	return s;
77b7579f77SDag-Erling Smørgrav }
78b7579f77SDag-Erling Smørgrav 
79b7579f77SDag-Erling Smørgrav size_t
packed_rrset_sizeof(struct packed_rrset_data * d)80b7579f77SDag-Erling Smørgrav packed_rrset_sizeof(struct packed_rrset_data* d)
81b7579f77SDag-Erling Smørgrav {
82b7579f77SDag-Erling Smørgrav 	size_t s;
83b7579f77SDag-Erling Smørgrav 	if(d->rrsig_count > 0) {
84b7579f77SDag-Erling Smørgrav 		s = ((uint8_t*)d->rr_data[d->count+d->rrsig_count-1] -
85b7579f77SDag-Erling Smørgrav 			(uint8_t*)d) + d->rr_len[d->count+d->rrsig_count-1];
86b7579f77SDag-Erling Smørgrav 	} else {
87b7579f77SDag-Erling Smørgrav 		log_assert(d->count > 0);
88b7579f77SDag-Erling Smørgrav 		s = ((uint8_t*)d->rr_data[d->count-1] - (uint8_t*)d) +
89b7579f77SDag-Erling Smørgrav 			d->rr_len[d->count-1];
90b7579f77SDag-Erling Smørgrav 	}
91b7579f77SDag-Erling Smørgrav 	return s;
92b7579f77SDag-Erling Smørgrav }
93b7579f77SDag-Erling Smørgrav 
94b7579f77SDag-Erling Smørgrav int
ub_rrset_compare(void * k1,void * k2)95b7579f77SDag-Erling Smørgrav ub_rrset_compare(void* k1, void* k2)
96b7579f77SDag-Erling Smørgrav {
97b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1;
98b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2;
99b7579f77SDag-Erling Smørgrav 	int c;
100b7579f77SDag-Erling Smørgrav 	if(key1 == key2)
101b7579f77SDag-Erling Smørgrav 		return 0;
102b7579f77SDag-Erling Smørgrav 	if(key1->rk.type != key2->rk.type) {
103b7579f77SDag-Erling Smørgrav 		if(key1->rk.type < key2->rk.type)
104b7579f77SDag-Erling Smørgrav 			return -1;
105b7579f77SDag-Erling Smørgrav 		return 1;
106b7579f77SDag-Erling Smørgrav 	}
107b7579f77SDag-Erling Smørgrav 	if(key1->rk.dname_len != key2->rk.dname_len) {
108b7579f77SDag-Erling Smørgrav 		if(key1->rk.dname_len < key2->rk.dname_len)
109b7579f77SDag-Erling Smørgrav 			return -1;
110b7579f77SDag-Erling Smørgrav 		return 1;
111b7579f77SDag-Erling Smørgrav 	}
112b7579f77SDag-Erling Smørgrav 	if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0)
113b7579f77SDag-Erling Smørgrav 		return c;
114b7579f77SDag-Erling Smørgrav 	if(key1->rk.rrset_class != key2->rk.rrset_class) {
115b7579f77SDag-Erling Smørgrav 		if(key1->rk.rrset_class < key2->rk.rrset_class)
116b7579f77SDag-Erling Smørgrav 			return -1;
117b7579f77SDag-Erling Smørgrav 		return 1;
118b7579f77SDag-Erling Smørgrav 	}
119b7579f77SDag-Erling Smørgrav 	if(key1->rk.flags != key2->rk.flags) {
120b7579f77SDag-Erling Smørgrav 		if(key1->rk.flags < key2->rk.flags)
121b7579f77SDag-Erling Smørgrav 			return -1;
122b7579f77SDag-Erling Smørgrav 		return 1;
123b7579f77SDag-Erling Smørgrav 	}
124b7579f77SDag-Erling Smørgrav 	return 0;
125b7579f77SDag-Erling Smørgrav }
126b7579f77SDag-Erling Smørgrav 
127b7579f77SDag-Erling Smørgrav void
ub_rrset_key_delete(void * key,void * userdata)128b7579f77SDag-Erling Smørgrav ub_rrset_key_delete(void* key, void* userdata)
129b7579f77SDag-Erling Smørgrav {
130b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key;
131b7579f77SDag-Erling Smørgrav 	struct alloc_cache* a = (struct alloc_cache*)userdata;
132b7579f77SDag-Erling Smørgrav 	k->id = 0;
133b7579f77SDag-Erling Smørgrav 	free(k->rk.dname);
134b7579f77SDag-Erling Smørgrav 	k->rk.dname = NULL;
135b7579f77SDag-Erling Smørgrav 	alloc_special_release(a, k);
136b7579f77SDag-Erling Smørgrav }
137b7579f77SDag-Erling Smørgrav 
138b7579f77SDag-Erling Smørgrav void
rrset_data_delete(void * data,void * ATTR_UNUSED (userdata))139b7579f77SDag-Erling Smørgrav rrset_data_delete(void* data, void* ATTR_UNUSED(userdata))
140b7579f77SDag-Erling Smørgrav {
141b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* d = (struct packed_rrset_data*)data;
142b7579f77SDag-Erling Smørgrav 	free(d);
143b7579f77SDag-Erling Smørgrav }
144b7579f77SDag-Erling Smørgrav 
145b7579f77SDag-Erling Smørgrav int
rrsetdata_equal(struct packed_rrset_data * d1,struct packed_rrset_data * d2)146b7579f77SDag-Erling Smørgrav rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2)
147b7579f77SDag-Erling Smørgrav {
148b7579f77SDag-Erling Smørgrav 	size_t i;
149b7579f77SDag-Erling Smørgrav 	size_t total;
150b7579f77SDag-Erling Smørgrav 	if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count)
151b7579f77SDag-Erling Smørgrav 		return 0;
152b7579f77SDag-Erling Smørgrav 	total = d1->count + d1->rrsig_count;
153b7579f77SDag-Erling Smørgrav 	for(i=0; i<total; i++) {
154b7579f77SDag-Erling Smørgrav 		if(d1->rr_len[i] != d2->rr_len[i])
155b7579f77SDag-Erling Smørgrav 			return 0;
156b7579f77SDag-Erling Smørgrav 		if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0)
157b7579f77SDag-Erling Smørgrav 			return 0;
158b7579f77SDag-Erling Smørgrav 	}
159b7579f77SDag-Erling Smørgrav 	return 1;
160b7579f77SDag-Erling Smørgrav }
161b7579f77SDag-Erling Smørgrav 
1623005e0a3SDag-Erling Smørgrav hashvalue_type
rrset_key_hash(struct packed_rrset_key * key)163b7579f77SDag-Erling Smørgrav rrset_key_hash(struct packed_rrset_key* key)
164b7579f77SDag-Erling Smørgrav {
165b7579f77SDag-Erling Smørgrav 	/* type is hashed in host order */
166b7579f77SDag-Erling Smørgrav 	uint16_t t = ntohs(key->type);
167b7579f77SDag-Erling Smørgrav 	/* Note this MUST be identical to pkt_hash_rrset in msgparse.c */
168b7579f77SDag-Erling Smørgrav 	/* this routine does not have a compressed name */
1693005e0a3SDag-Erling Smørgrav 	hashvalue_type h = 0xab;
170b7579f77SDag-Erling Smørgrav 	h = dname_query_hash(key->dname, h);
171b7579f77SDag-Erling Smørgrav 	h = hashlittle(&t, sizeof(t), h);
172b7579f77SDag-Erling Smørgrav 	h = hashlittle(&key->rrset_class, sizeof(uint16_t), h);
173b7579f77SDag-Erling Smørgrav 	h = hashlittle(&key->flags, sizeof(uint32_t), h);
174b7579f77SDag-Erling Smørgrav 	return h;
175b7579f77SDag-Erling Smørgrav }
176b7579f77SDag-Erling Smørgrav 
177b7579f77SDag-Erling Smørgrav void
packed_rrset_ptr_fixup(struct packed_rrset_data * data)178b7579f77SDag-Erling Smørgrav packed_rrset_ptr_fixup(struct packed_rrset_data* data)
179b7579f77SDag-Erling Smørgrav {
180b7579f77SDag-Erling Smørgrav 	size_t i;
181b7579f77SDag-Erling Smørgrav 	size_t total = data->count + data->rrsig_count;
182b7579f77SDag-Erling Smørgrav 	uint8_t* nextrdata;
183b7579f77SDag-Erling Smørgrav 	/* fixup pointers in packed rrset data */
184b7579f77SDag-Erling Smørgrav 	data->rr_len = (size_t*)((uint8_t*)data +
185b7579f77SDag-Erling Smørgrav 		sizeof(struct packed_rrset_data));
186b7579f77SDag-Erling Smørgrav 	data->rr_data = (uint8_t**)&(data->rr_len[total]);
18717d15b25SDag-Erling Smørgrav 	data->rr_ttl = (time_t*)&(data->rr_data[total]);
188b7579f77SDag-Erling Smørgrav 	nextrdata = (uint8_t*)&(data->rr_ttl[total]);
189b7579f77SDag-Erling Smørgrav 	for(i=0; i<total; i++) {
190b7579f77SDag-Erling Smørgrav 		data->rr_data[i] = nextrdata;
191b7579f77SDag-Erling Smørgrav 		nextrdata += data->rr_len[i];
192b7579f77SDag-Erling Smørgrav 	}
193b7579f77SDag-Erling Smørgrav }
194b7579f77SDag-Erling Smørgrav 
195b7579f77SDag-Erling Smørgrav void
get_cname_target(struct ub_packed_rrset_key * rrset,uint8_t ** dname,size_t * dname_len)196b7579f77SDag-Erling Smørgrav get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname,
197b7579f77SDag-Erling Smørgrav 	size_t* dname_len)
198b7579f77SDag-Erling Smørgrav {
199b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* d;
200b7579f77SDag-Erling Smørgrav 	size_t len;
201b7579f77SDag-Erling Smørgrav 	if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME &&
202b7579f77SDag-Erling Smørgrav 		ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME)
203b7579f77SDag-Erling Smørgrav 		return;
204b7579f77SDag-Erling Smørgrav 	d = (struct packed_rrset_data*)rrset->entry.data;
205b7579f77SDag-Erling Smørgrav 	if(d->count < 1)
206b7579f77SDag-Erling Smørgrav 		return;
207b7579f77SDag-Erling Smørgrav 	if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */
208b7579f77SDag-Erling Smørgrav 		return;
20917d15b25SDag-Erling Smørgrav 	len = sldns_read_uint16(d->rr_data[0]);
210b7579f77SDag-Erling Smørgrav 	if(len != d->rr_len[0] - sizeof(uint16_t))
211b7579f77SDag-Erling Smørgrav 		return;
212b7579f77SDag-Erling Smørgrav 	if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len)
213b7579f77SDag-Erling Smørgrav 		return;
214b7579f77SDag-Erling Smørgrav 	*dname = d->rr_data[0]+sizeof(uint16_t);
215b7579f77SDag-Erling Smørgrav 	*dname_len = len;
216b7579f77SDag-Erling Smørgrav }
217b7579f77SDag-Erling Smørgrav 
218b7579f77SDag-Erling Smørgrav void
packed_rrset_ttl_add(struct packed_rrset_data * data,time_t add)21917d15b25SDag-Erling Smørgrav packed_rrset_ttl_add(struct packed_rrset_data* data, time_t add)
220b7579f77SDag-Erling Smørgrav {
221b7579f77SDag-Erling Smørgrav 	size_t i;
222b7579f77SDag-Erling Smørgrav 	size_t total = data->count + data->rrsig_count;
223f44e67d1SCy Schubert 	data->ttl_add = add;
224b7579f77SDag-Erling Smørgrav 	data->ttl += add;
225b7579f77SDag-Erling Smørgrav 	for(i=0; i<total; i++)
226b7579f77SDag-Erling Smørgrav 		data->rr_ttl[i] += add;
227b7579f77SDag-Erling Smørgrav }
228b7579f77SDag-Erling Smørgrav 
229b7579f77SDag-Erling Smørgrav const char*
rrset_trust_to_string(enum rrset_trust s)230b7579f77SDag-Erling Smørgrav rrset_trust_to_string(enum rrset_trust s)
231b7579f77SDag-Erling Smørgrav {
232b7579f77SDag-Erling Smørgrav 	switch(s) {
233b7579f77SDag-Erling Smørgrav 	case rrset_trust_none: 		return "rrset_trust_none";
234b7579f77SDag-Erling Smørgrav 	case rrset_trust_add_noAA: 	return "rrset_trust_add_noAA";
235b7579f77SDag-Erling Smørgrav 	case rrset_trust_auth_noAA: 	return "rrset_trust_auth_noAA";
236b7579f77SDag-Erling Smørgrav 	case rrset_trust_add_AA: 	return "rrset_trust_add_AA";
237b7579f77SDag-Erling Smørgrav 	case rrset_trust_nonauth_ans_AA:return "rrset_trust_nonauth_ans_AA";
238b7579f77SDag-Erling Smørgrav 	case rrset_trust_ans_noAA: 	return "rrset_trust_ans_noAA";
239b7579f77SDag-Erling Smørgrav 	case rrset_trust_glue: 		return "rrset_trust_glue";
240b7579f77SDag-Erling Smørgrav 	case rrset_trust_auth_AA: 	return "rrset_trust_auth_AA";
241b7579f77SDag-Erling Smørgrav 	case rrset_trust_ans_AA: 	return "rrset_trust_ans_AA";
242b7579f77SDag-Erling Smørgrav 	case rrset_trust_sec_noglue: 	return "rrset_trust_sec_noglue";
243b7579f77SDag-Erling Smørgrav 	case rrset_trust_prim_noglue: 	return "rrset_trust_prim_noglue";
244b7579f77SDag-Erling Smørgrav 	case rrset_trust_validated: 	return "rrset_trust_validated";
245b7579f77SDag-Erling Smørgrav 	case rrset_trust_ultimate: 	return "rrset_trust_ultimate";
246b7579f77SDag-Erling Smørgrav 	}
247b7579f77SDag-Erling Smørgrav 	return "unknown_rrset_trust_value";
248b7579f77SDag-Erling Smørgrav }
249b7579f77SDag-Erling Smørgrav 
250b7579f77SDag-Erling Smørgrav const char*
sec_status_to_string(enum sec_status s)251b7579f77SDag-Erling Smørgrav sec_status_to_string(enum sec_status s)
252b7579f77SDag-Erling Smørgrav {
253b7579f77SDag-Erling Smørgrav 	switch(s) {
254b7579f77SDag-Erling Smørgrav 	case sec_status_unchecked: 	return "sec_status_unchecked";
255b7579f77SDag-Erling Smørgrav 	case sec_status_bogus: 		return "sec_status_bogus";
256b7579f77SDag-Erling Smørgrav 	case sec_status_indeterminate: 	return "sec_status_indeterminate";
257b7579f77SDag-Erling Smørgrav 	case sec_status_insecure: 	return "sec_status_insecure";
2580fb34990SDag-Erling Smørgrav 	case sec_status_secure_sentinel_fail: 	return "sec_status_secure_sentinel_fail";
259b7579f77SDag-Erling Smørgrav 	case sec_status_secure: 	return "sec_status_secure";
260b7579f77SDag-Erling Smørgrav 	}
261b7579f77SDag-Erling Smørgrav 	return "unknown_sec_status_value";
262b7579f77SDag-Erling Smørgrav }
263b7579f77SDag-Erling Smørgrav 
log_rrset_key(enum verbosity_value v,const char * str,struct ub_packed_rrset_key * rrset)264b7579f77SDag-Erling Smørgrav void log_rrset_key(enum verbosity_value v, const char* str,
265b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* rrset)
266b7579f77SDag-Erling Smørgrav {
267b7579f77SDag-Erling Smørgrav 	if(verbosity >= v)
268b7579f77SDag-Erling Smørgrav 		log_nametypeclass(v, str, rrset->rk.dname,
269b7579f77SDag-Erling Smørgrav 			ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
270b7579f77SDag-Erling Smørgrav }
271b7579f77SDag-Erling Smørgrav 
packed_rr_to_string(struct ub_packed_rrset_key * rrset,size_t i,time_t now,char * dest,size_t dest_len)27217d15b25SDag-Erling Smørgrav int packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i,
27317d15b25SDag-Erling Smørgrav 	time_t now, char* dest, size_t dest_len)
27417d15b25SDag-Erling Smørgrav {
27517d15b25SDag-Erling Smørgrav 	struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
27617d15b25SDag-Erling Smørgrav 		entry.data;
27717d15b25SDag-Erling Smørgrav 	uint8_t rr[65535];
278*b7c0c8c1SCy Schubert 	size_t wlen;
27917d15b25SDag-Erling Smørgrav 	size_t rlen = rrset->rk.dname_len + 2 + 2 + 4 + d->rr_len[i];
280f44e67d1SCy Schubert 	time_t adjust = 0;
28117d15b25SDag-Erling Smørgrav 	log_assert(dest_len > 0 && dest);
28217d15b25SDag-Erling Smørgrav 	if(rlen > dest_len) {
28317d15b25SDag-Erling Smørgrav 		dest[0] = 0;
28417d15b25SDag-Erling Smørgrav 		return 0;
28517d15b25SDag-Erling Smørgrav 	}
28617d15b25SDag-Erling Smørgrav 	memmove(rr, rrset->rk.dname, rrset->rk.dname_len);
28717d15b25SDag-Erling Smørgrav 	if(i < d->count)
28817d15b25SDag-Erling Smørgrav 		memmove(rr+rrset->rk.dname_len, &rrset->rk.type, 2);
28917d15b25SDag-Erling Smørgrav 	else	sldns_write_uint16(rr+rrset->rk.dname_len, LDNS_RR_TYPE_RRSIG);
29017d15b25SDag-Erling Smørgrav 	memmove(rr+rrset->rk.dname_len+2, &rrset->rk.rrset_class, 2);
291f44e67d1SCy Schubert 	adjust = SERVE_ORIGINAL_TTL ? d->ttl_add : now;
292f44e67d1SCy Schubert 	if (d->rr_ttl[i] < adjust) adjust = d->rr_ttl[i]; /* Prevent negative TTL overflow */
29317d15b25SDag-Erling Smørgrav 	sldns_write_uint32(rr+rrset->rk.dname_len+4,
294f44e67d1SCy Schubert 		(uint32_t)(d->rr_ttl[i]-adjust));
29517d15b25SDag-Erling Smørgrav 	memmove(rr+rrset->rk.dname_len+8, d->rr_data[i], d->rr_len[i]);
296*b7c0c8c1SCy Schubert 	wlen = (size_t)sldns_wire2str_rr_buf(rr, rlen, dest, dest_len);
297*b7c0c8c1SCy Schubert 	if(wlen >= dest_len) {
298*b7c0c8c1SCy Schubert 		/* the output string was truncated */
29917d15b25SDag-Erling Smørgrav 		log_info("rrbuf failure %d %s", (int)d->rr_len[i], dest);
30017d15b25SDag-Erling Smørgrav 		dest[0] = 0;
30117d15b25SDag-Erling Smørgrav 		return 0;
30217d15b25SDag-Erling Smørgrav 	}
30317d15b25SDag-Erling Smørgrav 	return 1;
30417d15b25SDag-Erling Smørgrav }
30517d15b25SDag-Erling Smørgrav 
log_packed_rrset(enum verbosity_value v,const char * str,struct ub_packed_rrset_key * rrset)30617d15b25SDag-Erling Smørgrav void log_packed_rrset(enum verbosity_value v, const char* str,
30717d15b25SDag-Erling Smørgrav 	struct ub_packed_rrset_key* rrset)
30817d15b25SDag-Erling Smørgrav {
30917d15b25SDag-Erling Smørgrav 	struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
31017d15b25SDag-Erling Smørgrav 		entry.data;
31117d15b25SDag-Erling Smørgrav 	char buf[65535];
31217d15b25SDag-Erling Smørgrav 	size_t i;
31317d15b25SDag-Erling Smørgrav 	if(verbosity < v)
31417d15b25SDag-Erling Smørgrav 		return;
31517d15b25SDag-Erling Smørgrav 	for(i=0; i<d->count+d->rrsig_count; i++) {
31617d15b25SDag-Erling Smørgrav 		if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf))) {
31717d15b25SDag-Erling Smørgrav 			log_info("%s: rr %d wire2str-error", str, (int)i);
31817d15b25SDag-Erling Smørgrav 		} else {
31917d15b25SDag-Erling Smørgrav 			log_info("%s: %s", str, buf);
32017d15b25SDag-Erling Smørgrav 		}
32117d15b25SDag-Erling Smørgrav 	}
32217d15b25SDag-Erling Smørgrav }
32317d15b25SDag-Erling Smørgrav 
32417d15b25SDag-Erling Smørgrav time_t
ub_packed_rrset_ttl(struct ub_packed_rrset_key * key)325b7579f77SDag-Erling Smørgrav ub_packed_rrset_ttl(struct ub_packed_rrset_key* key)
326b7579f77SDag-Erling Smørgrav {
327b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* d = (struct packed_rrset_data*)key->
328b7579f77SDag-Erling Smørgrav 		entry.data;
329b7579f77SDag-Erling Smørgrav 	return d->ttl;
330b7579f77SDag-Erling Smørgrav }
331b7579f77SDag-Erling Smørgrav 
332b7579f77SDag-Erling Smørgrav struct ub_packed_rrset_key*
packed_rrset_copy_region(struct ub_packed_rrset_key * key,struct regional * region,time_t now)333b7579f77SDag-Erling Smørgrav packed_rrset_copy_region(struct ub_packed_rrset_key* key,
33417d15b25SDag-Erling Smørgrav 	struct regional* region, time_t now)
335b7579f77SDag-Erling Smørgrav {
336b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* ck = regional_alloc(region,
337b7579f77SDag-Erling Smørgrav 		sizeof(struct ub_packed_rrset_key));
338b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* d;
339b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* data = (struct packed_rrset_data*)
340b7579f77SDag-Erling Smørgrav 		key->entry.data;
341b7579f77SDag-Erling Smørgrav 	size_t dsize, i;
342f44e67d1SCy Schubert 	time_t adjust = 0;
343b7579f77SDag-Erling Smørgrav 	if(!ck)
344b7579f77SDag-Erling Smørgrav 		return NULL;
345b7579f77SDag-Erling Smørgrav 	ck->id = key->id;
346b7579f77SDag-Erling Smørgrav 	memset(&ck->entry, 0, sizeof(ck->entry));
347b7579f77SDag-Erling Smørgrav 	ck->entry.hash = key->entry.hash;
348b7579f77SDag-Erling Smørgrav 	ck->entry.key = ck;
349b7579f77SDag-Erling Smørgrav 	ck->rk = key->rk;
350b7579f77SDag-Erling Smørgrav 	ck->rk.dname = regional_alloc_init(region, key->rk.dname,
351b7579f77SDag-Erling Smørgrav 		key->rk.dname_len);
352b7579f77SDag-Erling Smørgrav 	if(!ck->rk.dname)
353b7579f77SDag-Erling Smørgrav 		return NULL;
354b7579f77SDag-Erling Smørgrav 	dsize = packed_rrset_sizeof(data);
355b7579f77SDag-Erling Smørgrav 	d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize);
356b7579f77SDag-Erling Smørgrav 	if(!d)
357b7579f77SDag-Erling Smørgrav 		return NULL;
358b7579f77SDag-Erling Smørgrav 	ck->entry.data = d;
359b7579f77SDag-Erling Smørgrav 	packed_rrset_ptr_fixup(d);
360b7579f77SDag-Erling Smørgrav 	/* make TTLs relative - once per rrset */
361f44e67d1SCy Schubert 	adjust = SERVE_ORIGINAL_TTL ? data->ttl_add : now;
362b7579f77SDag-Erling Smørgrav 	for(i=0; i<d->count + d->rrsig_count; i++) {
363f44e67d1SCy Schubert 		if(d->rr_ttl[i] < adjust)
364091e9e46SCy Schubert 			d->rr_ttl[i] = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0;
365f44e67d1SCy Schubert 		else	d->rr_ttl[i] -= adjust;
366b7579f77SDag-Erling Smørgrav 	}
367f44e67d1SCy Schubert 	if(d->ttl < adjust)
368091e9e46SCy Schubert 		d->ttl = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0;
369f44e67d1SCy Schubert 	else	d->ttl -= adjust;
370f44e67d1SCy Schubert 	d->ttl_add = 0; /* TTLs have been made relative */
371b7579f77SDag-Erling Smørgrav 	return ck;
372b7579f77SDag-Erling Smørgrav }
373b7579f77SDag-Erling Smørgrav 
374b7579f77SDag-Erling Smørgrav struct ub_packed_rrset_key*
packed_rrset_copy_alloc(struct ub_packed_rrset_key * key,struct alloc_cache * alloc,time_t now)375b7579f77SDag-Erling Smørgrav packed_rrset_copy_alloc(struct ub_packed_rrset_key* key,
37617d15b25SDag-Erling Smørgrav 	struct alloc_cache* alloc, time_t now)
377b7579f77SDag-Erling Smørgrav {
378b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* fd, *dd;
379b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc);
380b7579f77SDag-Erling Smørgrav 	if(!dk) return NULL;
381b7579f77SDag-Erling Smørgrav 	fd = (struct packed_rrset_data*)key->entry.data;
382b7579f77SDag-Erling Smørgrav 	dk->entry.hash = key->entry.hash;
383b7579f77SDag-Erling Smørgrav 	dk->rk = key->rk;
384b7579f77SDag-Erling Smørgrav 	dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len);
385b7579f77SDag-Erling Smørgrav 	if(!dk->rk.dname) {
386b7579f77SDag-Erling Smørgrav 		alloc_special_release(alloc, dk);
387b7579f77SDag-Erling Smørgrav 		return NULL;
388b7579f77SDag-Erling Smørgrav 	}
389b7579f77SDag-Erling Smørgrav 	dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd));
390b7579f77SDag-Erling Smørgrav 	if(!dd) {
391b7579f77SDag-Erling Smørgrav 		free(dk->rk.dname);
392b7579f77SDag-Erling Smørgrav 		alloc_special_release(alloc, dk);
393b7579f77SDag-Erling Smørgrav 		return NULL;
394b7579f77SDag-Erling Smørgrav 	}
395b7579f77SDag-Erling Smørgrav 	packed_rrset_ptr_fixup(dd);
396b7579f77SDag-Erling Smørgrav 	dk->entry.data = (void*)dd;
397b7579f77SDag-Erling Smørgrav 	packed_rrset_ttl_add(dd, now);
398b7579f77SDag-Erling Smørgrav 	return dk;
399b7579f77SDag-Erling Smørgrav }
400091e9e46SCy Schubert 
401091e9e46SCy Schubert int
packed_rrset_find_rr(struct packed_rrset_data * d,uint8_t * rdata,size_t len,size_t * index)402091e9e46SCy Schubert packed_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
403091e9e46SCy Schubert 	size_t* index)
404091e9e46SCy Schubert {
405091e9e46SCy Schubert 	size_t i;
406091e9e46SCy Schubert 	for(i=0; i<d->count; i++) {
407091e9e46SCy Schubert 		if(d->rr_len[i] != len)
408091e9e46SCy Schubert 			continue;
409091e9e46SCy Schubert 		if(memcmp(d->rr_data[i], rdata, len) == 0) {
410091e9e46SCy Schubert 			*index = i;
411091e9e46SCy Schubert 			return 1;
412091e9e46SCy Schubert 		}
413091e9e46SCy Schubert 	}
414091e9e46SCy Schubert 	return 0;
415091e9e46SCy Schubert }
416