1933707f3Ssthen /*
2933707f3Ssthen  * util/data/packed_rrset.c - data storage for a set of resource records.
3933707f3Ssthen  *
4933707f3Ssthen  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5933707f3Ssthen  *
6933707f3Ssthen  * This software is open source.
7933707f3Ssthen  *
8933707f3Ssthen  * Redistribution and use in source and binary forms, with or without
9933707f3Ssthen  * modification, are permitted provided that the following conditions
10933707f3Ssthen  * are met:
11933707f3Ssthen  *
12933707f3Ssthen  * Redistributions of source code must retain the above copyright notice,
13933707f3Ssthen  * this list of conditions and the following disclaimer.
14933707f3Ssthen  *
15933707f3Ssthen  * Redistributions in binary form must reproduce the above copyright notice,
16933707f3Ssthen  * this list of conditions and the following disclaimer in the documentation
17933707f3Ssthen  * and/or other materials provided with the distribution.
18933707f3Ssthen  *
19933707f3Ssthen  * Neither the name of the NLNET LABS nor the names of its contributors may
20933707f3Ssthen  * be used to endorse or promote products derived from this software without
21933707f3Ssthen  * specific prior written permission.
22933707f3Ssthen  *
23933707f3Ssthen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
245d76a658Ssthen  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
255d76a658Ssthen  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
265d76a658Ssthen  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
275d76a658Ssthen  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
285d76a658Ssthen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
295d76a658Ssthen  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
305d76a658Ssthen  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
315d76a658Ssthen  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
325d76a658Ssthen  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
335d76a658Ssthen  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34933707f3Ssthen  */
35933707f3Ssthen 
36933707f3Ssthen /**
37933707f3Ssthen  * \file
38933707f3Ssthen  *
39933707f3Ssthen  * This file contains the data storage for RRsets.
40933707f3Ssthen  */
41933707f3Ssthen 
42933707f3Ssthen #include "config.h"
43eaf2578eSsthen #include "util/data/msgparse.h"
44933707f3Ssthen #include "util/data/packed_rrset.h"
45933707f3Ssthen #include "util/data/dname.h"
46933707f3Ssthen #include "util/storage/lookup3.h"
47933707f3Ssthen #include "util/log.h"
48933707f3Ssthen #include "util/alloc.h"
49933707f3Ssthen #include "util/regional.h"
50933707f3Ssthen #include "util/net_help.h"
51fdfb4ba6Ssthen #include "sldns/rrdef.h"
52fdfb4ba6Ssthen #include "sldns/sbuffer.h"
53fdfb4ba6Ssthen #include "sldns/wire2str.h"
54933707f3Ssthen 
55933707f3Ssthen void
ub_packed_rrset_parsedelete(struct ub_packed_rrset_key * pkey,struct alloc_cache * alloc)56933707f3Ssthen ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey,
57933707f3Ssthen         struct alloc_cache* alloc)
58933707f3Ssthen {
59933707f3Ssthen 	if(!pkey)
60933707f3Ssthen 		return;
61933707f3Ssthen 	free(pkey->entry.data);
62933707f3Ssthen 	pkey->entry.data = NULL;
63933707f3Ssthen 	free(pkey->rk.dname);
64933707f3Ssthen 	pkey->rk.dname = NULL;
65933707f3Ssthen 	pkey->id = 0;
66933707f3Ssthen 	alloc_special_release(alloc, pkey);
67933707f3Ssthen }
68933707f3Ssthen 
69933707f3Ssthen size_t
ub_rrset_sizefunc(void * key,void * data)70933707f3Ssthen ub_rrset_sizefunc(void* key, void* data)
71933707f3Ssthen {
72933707f3Ssthen 	struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key;
73933707f3Ssthen 	struct packed_rrset_data* d = (struct packed_rrset_data*)data;
74933707f3Ssthen 	size_t s = sizeof(struct ub_packed_rrset_key) + k->rk.dname_len;
75933707f3Ssthen 	s += packed_rrset_sizeof(d) + lock_get_mem(&k->entry.lock);
76933707f3Ssthen 	return s;
77933707f3Ssthen }
78933707f3Ssthen 
79933707f3Ssthen size_t
packed_rrset_sizeof(struct packed_rrset_data * d)80933707f3Ssthen packed_rrset_sizeof(struct packed_rrset_data* d)
81933707f3Ssthen {
82933707f3Ssthen 	size_t s;
83933707f3Ssthen 	if(d->rrsig_count > 0) {
84933707f3Ssthen 		s = ((uint8_t*)d->rr_data[d->count+d->rrsig_count-1] -
85933707f3Ssthen 			(uint8_t*)d) + d->rr_len[d->count+d->rrsig_count-1];
86933707f3Ssthen 	} else {
87933707f3Ssthen 		log_assert(d->count > 0);
88933707f3Ssthen 		s = ((uint8_t*)d->rr_data[d->count-1] - (uint8_t*)d) +
89933707f3Ssthen 			d->rr_len[d->count-1];
90933707f3Ssthen 	}
91933707f3Ssthen 	return s;
92933707f3Ssthen }
93933707f3Ssthen 
94933707f3Ssthen int
ub_rrset_compare(void * k1,void * k2)95933707f3Ssthen ub_rrset_compare(void* k1, void* k2)
96933707f3Ssthen {
97933707f3Ssthen 	struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1;
98933707f3Ssthen 	struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2;
99933707f3Ssthen 	int c;
100933707f3Ssthen 	if(key1 == key2)
101933707f3Ssthen 		return 0;
102933707f3Ssthen 	if(key1->rk.type != key2->rk.type) {
103933707f3Ssthen 		if(key1->rk.type < key2->rk.type)
104933707f3Ssthen 			return -1;
105933707f3Ssthen 		return 1;
106933707f3Ssthen 	}
107933707f3Ssthen 	if(key1->rk.dname_len != key2->rk.dname_len) {
108933707f3Ssthen 		if(key1->rk.dname_len < key2->rk.dname_len)
109933707f3Ssthen 			return -1;
110933707f3Ssthen 		return 1;
111933707f3Ssthen 	}
112933707f3Ssthen 	if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0)
113933707f3Ssthen 		return c;
114933707f3Ssthen 	if(key1->rk.rrset_class != key2->rk.rrset_class) {
115933707f3Ssthen 		if(key1->rk.rrset_class < key2->rk.rrset_class)
116933707f3Ssthen 			return -1;
117933707f3Ssthen 		return 1;
118933707f3Ssthen 	}
119933707f3Ssthen 	if(key1->rk.flags != key2->rk.flags) {
120933707f3Ssthen 		if(key1->rk.flags < key2->rk.flags)
121933707f3Ssthen 			return -1;
122933707f3Ssthen 		return 1;
123933707f3Ssthen 	}
124933707f3Ssthen 	return 0;
125933707f3Ssthen }
126933707f3Ssthen 
127933707f3Ssthen void
ub_rrset_key_delete(void * key,void * userdata)128933707f3Ssthen ub_rrset_key_delete(void* key, void* userdata)
129933707f3Ssthen {
130933707f3Ssthen 	struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key;
131933707f3Ssthen 	struct alloc_cache* a = (struct alloc_cache*)userdata;
132933707f3Ssthen 	k->id = 0;
133933707f3Ssthen 	free(k->rk.dname);
134933707f3Ssthen 	k->rk.dname = NULL;
135933707f3Ssthen 	alloc_special_release(a, k);
136933707f3Ssthen }
137933707f3Ssthen 
138933707f3Ssthen void
rrset_data_delete(void * data,void * ATTR_UNUSED (userdata))139933707f3Ssthen rrset_data_delete(void* data, void* ATTR_UNUSED(userdata))
140933707f3Ssthen {
141933707f3Ssthen 	struct packed_rrset_data* d = (struct packed_rrset_data*)data;
142933707f3Ssthen 	free(d);
143933707f3Ssthen }
144933707f3Ssthen 
145933707f3Ssthen int
rrsetdata_equal(struct packed_rrset_data * d1,struct packed_rrset_data * d2)146933707f3Ssthen rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2)
147933707f3Ssthen {
148933707f3Ssthen 	size_t i;
149933707f3Ssthen 	size_t total;
150933707f3Ssthen 	if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count)
151933707f3Ssthen 		return 0;
152933707f3Ssthen 	total = d1->count + d1->rrsig_count;
153933707f3Ssthen 	for(i=0; i<total; i++) {
154933707f3Ssthen 		if(d1->rr_len[i] != d2->rr_len[i])
155933707f3Ssthen 			return 0;
156933707f3Ssthen 		if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0)
157933707f3Ssthen 			return 0;
158933707f3Ssthen 	}
159933707f3Ssthen 	return 1;
160933707f3Ssthen }
161933707f3Ssthen 
16277079be7Ssthen hashvalue_type
rrset_key_hash(struct packed_rrset_key * key)163933707f3Ssthen rrset_key_hash(struct packed_rrset_key* key)
164933707f3Ssthen {
165933707f3Ssthen 	/* type is hashed in host order */
166933707f3Ssthen 	uint16_t t = ntohs(key->type);
167933707f3Ssthen 	/* Note this MUST be identical to pkt_hash_rrset in msgparse.c */
168933707f3Ssthen 	/* this routine does not have a compressed name */
16977079be7Ssthen 	hashvalue_type h = 0xab;
170933707f3Ssthen 	h = dname_query_hash(key->dname, h);
171933707f3Ssthen 	h = hashlittle(&t, sizeof(t), h);
172933707f3Ssthen 	h = hashlittle(&key->rrset_class, sizeof(uint16_t), h);
173933707f3Ssthen 	h = hashlittle(&key->flags, sizeof(uint32_t), h);
174933707f3Ssthen 	return h;
175933707f3Ssthen }
176933707f3Ssthen 
177933707f3Ssthen void
packed_rrset_ptr_fixup(struct packed_rrset_data * data)178933707f3Ssthen packed_rrset_ptr_fixup(struct packed_rrset_data* data)
179933707f3Ssthen {
180933707f3Ssthen 	size_t i;
181933707f3Ssthen 	size_t total = data->count + data->rrsig_count;
182933707f3Ssthen 	uint8_t* nextrdata;
183933707f3Ssthen 	/* fixup pointers in packed rrset data */
184933707f3Ssthen 	data->rr_len = (size_t*)((uint8_t*)data +
185933707f3Ssthen 		sizeof(struct packed_rrset_data));
186933707f3Ssthen 	data->rr_data = (uint8_t**)&(data->rr_len[total]);
187229e174cSsthen 	data->rr_ttl = (time_t*)&(data->rr_data[total]);
188933707f3Ssthen 	nextrdata = (uint8_t*)&(data->rr_ttl[total]);
189933707f3Ssthen 	for(i=0; i<total; i++) {
190933707f3Ssthen 		data->rr_data[i] = nextrdata;
191933707f3Ssthen 		nextrdata += data->rr_len[i];
192933707f3Ssthen 	}
193933707f3Ssthen }
194933707f3Ssthen 
195933707f3Ssthen void
get_cname_target(struct ub_packed_rrset_key * rrset,uint8_t ** dname,size_t * dname_len)196933707f3Ssthen get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname,
197933707f3Ssthen 	size_t* dname_len)
198933707f3Ssthen {
199933707f3Ssthen 	struct packed_rrset_data* d;
200933707f3Ssthen 	size_t len;
201933707f3Ssthen 	if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME &&
202933707f3Ssthen 		ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME)
203933707f3Ssthen 		return;
204933707f3Ssthen 	d = (struct packed_rrset_data*)rrset->entry.data;
205933707f3Ssthen 	if(d->count < 1)
206933707f3Ssthen 		return;
207933707f3Ssthen 	if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */
208933707f3Ssthen 		return;
2095d76a658Ssthen 	len = sldns_read_uint16(d->rr_data[0]);
210933707f3Ssthen 	if(len != d->rr_len[0] - sizeof(uint16_t))
211933707f3Ssthen 		return;
212933707f3Ssthen 	if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len)
213933707f3Ssthen 		return;
214933707f3Ssthen 	*dname = d->rr_data[0]+sizeof(uint16_t);
215933707f3Ssthen 	*dname_len = len;
216933707f3Ssthen }
217933707f3Ssthen 
218933707f3Ssthen void
packed_rrset_ttl_add(struct packed_rrset_data * data,time_t add)219229e174cSsthen packed_rrset_ttl_add(struct packed_rrset_data* data, time_t add)
220933707f3Ssthen {
221933707f3Ssthen 	size_t i;
222933707f3Ssthen 	size_t total = data->count + data->rrsig_count;
2239982a05dSsthen 	data->ttl_add = add;
224933707f3Ssthen 	data->ttl += add;
225933707f3Ssthen 	for(i=0; i<total; i++)
226933707f3Ssthen 		data->rr_ttl[i] += add;
227933707f3Ssthen }
228933707f3Ssthen 
229933707f3Ssthen const char*
rrset_trust_to_string(enum rrset_trust s)230933707f3Ssthen rrset_trust_to_string(enum rrset_trust s)
231933707f3Ssthen {
232933707f3Ssthen 	switch(s) {
233933707f3Ssthen 	case rrset_trust_none: 		return "rrset_trust_none";
234933707f3Ssthen 	case rrset_trust_add_noAA: 	return "rrset_trust_add_noAA";
235933707f3Ssthen 	case rrset_trust_auth_noAA: 	return "rrset_trust_auth_noAA";
236933707f3Ssthen 	case rrset_trust_add_AA: 	return "rrset_trust_add_AA";
237933707f3Ssthen 	case rrset_trust_nonauth_ans_AA:return "rrset_trust_nonauth_ans_AA";
238933707f3Ssthen 	case rrset_trust_ans_noAA: 	return "rrset_trust_ans_noAA";
239933707f3Ssthen 	case rrset_trust_glue: 		return "rrset_trust_glue";
240933707f3Ssthen 	case rrset_trust_auth_AA: 	return "rrset_trust_auth_AA";
241933707f3Ssthen 	case rrset_trust_ans_AA: 	return "rrset_trust_ans_AA";
242933707f3Ssthen 	case rrset_trust_sec_noglue: 	return "rrset_trust_sec_noglue";
243933707f3Ssthen 	case rrset_trust_prim_noglue: 	return "rrset_trust_prim_noglue";
244933707f3Ssthen 	case rrset_trust_validated: 	return "rrset_trust_validated";
245933707f3Ssthen 	case rrset_trust_ultimate: 	return "rrset_trust_ultimate";
246933707f3Ssthen 	}
247933707f3Ssthen 	return "unknown_rrset_trust_value";
248933707f3Ssthen }
249933707f3Ssthen 
250933707f3Ssthen const char*
sec_status_to_string(enum sec_status s)251933707f3Ssthen sec_status_to_string(enum sec_status s)
252933707f3Ssthen {
253933707f3Ssthen 	switch(s) {
254933707f3Ssthen 	case sec_status_unchecked: 	return "sec_status_unchecked";
255933707f3Ssthen 	case sec_status_bogus: 		return "sec_status_bogus";
256933707f3Ssthen 	case sec_status_indeterminate: 	return "sec_status_indeterminate";
257933707f3Ssthen 	case sec_status_insecure: 	return "sec_status_insecure";
25820237c55Ssthen 	case sec_status_secure_sentinel_fail: 	return "sec_status_secure_sentinel_fail";
259933707f3Ssthen 	case sec_status_secure: 	return "sec_status_secure";
260933707f3Ssthen 	}
261933707f3Ssthen 	return "unknown_sec_status_value";
262933707f3Ssthen }
263933707f3Ssthen 
log_rrset_key(enum verbosity_value v,const char * str,struct ub_packed_rrset_key * rrset)264933707f3Ssthen void log_rrset_key(enum verbosity_value v, const char* str,
265933707f3Ssthen 	struct ub_packed_rrset_key* rrset)
266933707f3Ssthen {
267933707f3Ssthen 	if(verbosity >= v)
268933707f3Ssthen 		log_nametypeclass(v, str, rrset->rk.dname,
269933707f3Ssthen 			ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
270933707f3Ssthen }
271933707f3Ssthen 
packed_rr_to_string(struct ub_packed_rrset_key * rrset,size_t i,time_t now,char * dest,size_t dest_len)2725d76a658Ssthen int packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i,
2735d76a658Ssthen 	time_t now, char* dest, size_t dest_len)
2745d76a658Ssthen {
2755d76a658Ssthen 	struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
2765d76a658Ssthen 		entry.data;
2775d76a658Ssthen 	uint8_t rr[65535];
278*f46c52bfSsthen 	size_t wlen;
2795d76a658Ssthen 	size_t rlen = rrset->rk.dname_len + 2 + 2 + 4 + d->rr_len[i];
2809982a05dSsthen 	time_t adjust = 0;
2815d76a658Ssthen 	log_assert(dest_len > 0 && dest);
2825d76a658Ssthen 	if(rlen > dest_len) {
2835d76a658Ssthen 		dest[0] = 0;
2845d76a658Ssthen 		return 0;
2855d76a658Ssthen 	}
2865d76a658Ssthen 	memmove(rr, rrset->rk.dname, rrset->rk.dname_len);
2875d76a658Ssthen 	if(i < d->count)
2885d76a658Ssthen 		memmove(rr+rrset->rk.dname_len, &rrset->rk.type, 2);
2895d76a658Ssthen 	else	sldns_write_uint16(rr+rrset->rk.dname_len, LDNS_RR_TYPE_RRSIG);
2905d76a658Ssthen 	memmove(rr+rrset->rk.dname_len+2, &rrset->rk.rrset_class, 2);
2919982a05dSsthen 	adjust = SERVE_ORIGINAL_TTL ? d->ttl_add : now;
2929982a05dSsthen 	if (d->rr_ttl[i] < adjust) adjust = d->rr_ttl[i]; /* Prevent negative TTL overflow */
2935d76a658Ssthen 	sldns_write_uint32(rr+rrset->rk.dname_len+4,
2949982a05dSsthen 		(uint32_t)(d->rr_ttl[i]-adjust));
2955d76a658Ssthen 	memmove(rr+rrset->rk.dname_len+8, d->rr_data[i], d->rr_len[i]);
296*f46c52bfSsthen 	wlen = (size_t)sldns_wire2str_rr_buf(rr, rlen, dest, dest_len);
297*f46c52bfSsthen 	if(wlen >= dest_len) {
298*f46c52bfSsthen 		/* the output string was truncated */
2995d76a658Ssthen 		log_info("rrbuf failure %d %s", (int)d->rr_len[i], dest);
3005d76a658Ssthen 		dest[0] = 0;
3015d76a658Ssthen 		return 0;
3025d76a658Ssthen 	}
3035d76a658Ssthen 	return 1;
3045d76a658Ssthen }
3055d76a658Ssthen 
log_packed_rrset(enum verbosity_value v,const char * str,struct ub_packed_rrset_key * rrset)3065d76a658Ssthen void log_packed_rrset(enum verbosity_value v, const char* str,
3075d76a658Ssthen 	struct ub_packed_rrset_key* rrset)
3085d76a658Ssthen {
3095d76a658Ssthen 	struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
3105d76a658Ssthen 		entry.data;
3115d76a658Ssthen 	char buf[65535];
3125d76a658Ssthen 	size_t i;
3135d76a658Ssthen 	if(verbosity < v)
3145d76a658Ssthen 		return;
3155d76a658Ssthen 	for(i=0; i<d->count+d->rrsig_count; i++) {
3165d76a658Ssthen 		if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf))) {
3175d76a658Ssthen 			log_info("%s: rr %d wire2str-error", str, (int)i);
3185d76a658Ssthen 		} else {
3195d76a658Ssthen 			log_info("%s: %s", str, buf);
3205d76a658Ssthen 		}
3215d76a658Ssthen 	}
3225d76a658Ssthen }
3235d76a658Ssthen 
324229e174cSsthen time_t
ub_packed_rrset_ttl(struct ub_packed_rrset_key * key)325933707f3Ssthen ub_packed_rrset_ttl(struct ub_packed_rrset_key* key)
326933707f3Ssthen {
327933707f3Ssthen 	struct packed_rrset_data* d = (struct packed_rrset_data*)key->
328933707f3Ssthen 		entry.data;
329933707f3Ssthen 	return d->ttl;
330933707f3Ssthen }
331933707f3Ssthen 
332933707f3Ssthen struct ub_packed_rrset_key*
packed_rrset_copy_region(struct ub_packed_rrset_key * key,struct regional * region,time_t now)333933707f3Ssthen packed_rrset_copy_region(struct ub_packed_rrset_key* key,
334229e174cSsthen 	struct regional* region, time_t now)
335933707f3Ssthen {
336933707f3Ssthen 	struct ub_packed_rrset_key* ck = regional_alloc(region,
337933707f3Ssthen 		sizeof(struct ub_packed_rrset_key));
338933707f3Ssthen 	struct packed_rrset_data* d;
339933707f3Ssthen 	struct packed_rrset_data* data = (struct packed_rrset_data*)
340933707f3Ssthen 		key->entry.data;
341933707f3Ssthen 	size_t dsize, i;
3429982a05dSsthen 	time_t adjust = 0;
343933707f3Ssthen 	if(!ck)
344933707f3Ssthen 		return NULL;
345933707f3Ssthen 	ck->id = key->id;
346933707f3Ssthen 	memset(&ck->entry, 0, sizeof(ck->entry));
347933707f3Ssthen 	ck->entry.hash = key->entry.hash;
348933707f3Ssthen 	ck->entry.key = ck;
349933707f3Ssthen 	ck->rk = key->rk;
350933707f3Ssthen 	ck->rk.dname = regional_alloc_init(region, key->rk.dname,
351933707f3Ssthen 		key->rk.dname_len);
352933707f3Ssthen 	if(!ck->rk.dname)
353933707f3Ssthen 		return NULL;
354933707f3Ssthen 	dsize = packed_rrset_sizeof(data);
355933707f3Ssthen 	d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize);
356933707f3Ssthen 	if(!d)
357933707f3Ssthen 		return NULL;
358933707f3Ssthen 	ck->entry.data = d;
359933707f3Ssthen 	packed_rrset_ptr_fixup(d);
360933707f3Ssthen 	/* make TTLs relative - once per rrset */
3619982a05dSsthen 	adjust = SERVE_ORIGINAL_TTL ? data->ttl_add : now;
362933707f3Ssthen 	for(i=0; i<d->count + d->rrsig_count; i++) {
3639982a05dSsthen 		if(d->rr_ttl[i] < adjust)
364eaf2578eSsthen 			d->rr_ttl[i] = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0;
3659982a05dSsthen 		else	d->rr_ttl[i] -= adjust;
366933707f3Ssthen 	}
3679982a05dSsthen 	if(d->ttl < adjust)
368eaf2578eSsthen 		d->ttl = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0;
3699982a05dSsthen 	else	d->ttl -= adjust;
3709982a05dSsthen 	d->ttl_add = 0; /* TTLs have been made relative */
371933707f3Ssthen 	return ck;
372933707f3Ssthen }
373933707f3Ssthen 
374933707f3Ssthen struct ub_packed_rrset_key*
packed_rrset_copy_alloc(struct ub_packed_rrset_key * key,struct alloc_cache * alloc,time_t now)375933707f3Ssthen packed_rrset_copy_alloc(struct ub_packed_rrset_key* key,
376229e174cSsthen 	struct alloc_cache* alloc, time_t now)
377933707f3Ssthen {
378933707f3Ssthen 	struct packed_rrset_data* fd, *dd;
379933707f3Ssthen 	struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc);
380933707f3Ssthen 	if(!dk) return NULL;
381933707f3Ssthen 	fd = (struct packed_rrset_data*)key->entry.data;
382933707f3Ssthen 	dk->entry.hash = key->entry.hash;
383933707f3Ssthen 	dk->rk = key->rk;
384933707f3Ssthen 	dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len);
385933707f3Ssthen 	if(!dk->rk.dname) {
386933707f3Ssthen 		alloc_special_release(alloc, dk);
387933707f3Ssthen 		return NULL;
388933707f3Ssthen 	}
389933707f3Ssthen 	dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd));
390933707f3Ssthen 	if(!dd) {
391933707f3Ssthen 		free(dk->rk.dname);
392933707f3Ssthen 		alloc_special_release(alloc, dk);
393933707f3Ssthen 		return NULL;
394933707f3Ssthen 	}
395933707f3Ssthen 	packed_rrset_ptr_fixup(dd);
396933707f3Ssthen 	dk->entry.data = (void*)dd;
397933707f3Ssthen 	packed_rrset_ttl_add(dd, now);
398933707f3Ssthen 	return dk;
399933707f3Ssthen }
400eaf2578eSsthen 
401eaf2578eSsthen int
packed_rrset_find_rr(struct packed_rrset_data * d,uint8_t * rdata,size_t len,size_t * index)402eaf2578eSsthen packed_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
403eaf2578eSsthen 	size_t* index)
404eaf2578eSsthen {
405eaf2578eSsthen 	size_t i;
406eaf2578eSsthen 	for(i=0; i<d->count; i++) {
407eaf2578eSsthen 		if(d->rr_len[i] != len)
408eaf2578eSsthen 			continue;
409eaf2578eSsthen 		if(memcmp(d->rr_data[i], rdata, len) == 0) {
410eaf2578eSsthen 			*index = i;
411eaf2578eSsthen 			return 1;
412eaf2578eSsthen 		}
413eaf2578eSsthen 	}
414eaf2578eSsthen 	return 0;
415eaf2578eSsthen }
416