packed_rrset.c revision 291767
1180740Sdes/*
2180740Sdes * util/data/packed_rrset.c - data storage for a set of resource records.
3226046Sdes *
4226046Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved.
5226046Sdes *
6180740Sdes * This software is open source.
7180740Sdes *
8180740Sdes * Redistribution and use in source and binary forms, with or without
9180740Sdes * modification, are permitted provided that the following conditions
10180740Sdes * are met:
11180740Sdes *
12180740Sdes * Redistributions of source code must retain the above copyright notice,
13180746Sdes * this list of conditions and the following disclaimer.
14180746Sdes *
15180746Sdes * Redistributions in binary form must reproduce the above copyright notice,
16180740Sdes * this list of conditions and the following disclaimer in the documentation
17180740Sdes * and/or other materials provided with the distribution.
18180740Sdes *
19240075Sdes * Neither the name of the NLNET LABS nor the names of its contributors may
20240075Sdes * be used to endorse or promote products derived from this software without
21240075Sdes * specific prior written permission.
22180740Sdes *
23180740Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24180740Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25180740Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26180740Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27180740Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28180740Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29180740Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30180740Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31180746Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32180746Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33180746Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34180740Sdes */
35180740Sdes
36180740Sdes/**
37180740Sdes * \file
38180740Sdes *
39180740Sdes * This file contains the data storage for RRsets.
40180740Sdes */
41180740Sdes
42180740Sdes#include "config.h"
43180740Sdes#include "util/data/packed_rrset.h"
44180740Sdes#include "util/data/dname.h"
45180740Sdes#include "util/storage/lookup3.h"
46180740Sdes#include "util/log.h"
47180750Sdes#include "util/alloc.h"
48180750Sdes#include "util/regional.h"
49180750Sdes#include "util/net_help.h"
50262566Sdes#include "sldns/rrdef.h"
51262566Sdes#include "sldns/sbuffer.h"
52262566Sdes#include "sldns/wire2str.h"
53262566Sdes
54180740Sdesvoid
55180740Sdesub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey,
56180740Sdes        struct alloc_cache* alloc)
57180740Sdes{
58180740Sdes	if(!pkey)
59180740Sdes		return;
60180740Sdes	if(pkey->entry.data)
61180740Sdes		free(pkey->entry.data);
62180740Sdes	pkey->entry.data = NULL;
63180740Sdes	if(pkey->rk.dname)
64180740Sdes		free(pkey->rk.dname);
65180740Sdes	pkey->rk.dname = NULL;
66180740Sdes	pkey->id = 0;
67180740Sdes	alloc_special_release(alloc, pkey);
68180740Sdes}
69180740Sdes
70180740Sdessize_t
71180740Sdesub_rrset_sizefunc(void* key, void* data)
72180740Sdes{
73180740Sdes	struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key;
74180740Sdes	struct packed_rrset_data* d = (struct packed_rrset_data*)data;
75180746Sdes	size_t s = sizeof(struct ub_packed_rrset_key) + k->rk.dname_len;
76180746Sdes	s += packed_rrset_sizeof(d) + lock_get_mem(&k->entry.lock);
77180746Sdes	return s;
78180740Sdes}
79180740Sdes
80180740Sdessize_t
81262566Sdespacked_rrset_sizeof(struct packed_rrset_data* d)
82248619Sdes{
83248619Sdes	size_t s;
84197679Sdes	if(d->rrsig_count > 0) {
85197679Sdes		s = ((uint8_t*)d->rr_data[d->count+d->rrsig_count-1] -
86197679Sdes			(uint8_t*)d) + d->rr_len[d->count+d->rrsig_count-1];
87180740Sdes	} else {
88180740Sdes		log_assert(d->count > 0);
89180740Sdes		s = ((uint8_t*)d->rr_data[d->count-1] - (uint8_t*)d) +
90180740Sdes			d->rr_len[d->count-1];
91180740Sdes	}
92180740Sdes	return s;
93180740Sdes}
94180740Sdes
95180740Sdesint
96180740Sdesub_rrset_compare(void* k1, void* k2)
97180740Sdes{
98180740Sdes	struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1;
99180740Sdes	struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2;
100180740Sdes	int c;
101180740Sdes	if(key1 == key2)
102180740Sdes		return 0;
103180740Sdes	if(key1->rk.type != key2->rk.type) {
104180740Sdes		if(key1->rk.type < key2->rk.type)
105180740Sdes			return -1;
106180740Sdes		return 1;
107180740Sdes	}
108180740Sdes	if(key1->rk.dname_len != key2->rk.dname_len) {
109180740Sdes		if(key1->rk.dname_len < key2->rk.dname_len)
110180740Sdes			return -1;
111180740Sdes		return 1;
112180740Sdes	}
113180740Sdes	if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0)
114180740Sdes		return c;
115180740Sdes	if(key1->rk.rrset_class != key2->rk.rrset_class) {
116180740Sdes		if(key1->rk.rrset_class < key2->rk.rrset_class)
117180740Sdes			return -1;
118180740Sdes		return 1;
119180740Sdes	}
120180740Sdes	if(key1->rk.flags != key2->rk.flags) {
121180740Sdes		if(key1->rk.flags < key2->rk.flags)
122180740Sdes			return -1;
123180740Sdes		return 1;
124180740Sdes	}
125180740Sdes	return 0;
126180740Sdes}
127180740Sdes
128180740Sdesvoid
129180740Sdesub_rrset_key_delete(void* key, void* userdata)
130180740Sdes{
131180740Sdes	struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key;
132180740Sdes	struct alloc_cache* a = (struct alloc_cache*)userdata;
133180740Sdes	k->id = 0;
134180740Sdes	free(k->rk.dname);
135204917Sdes	k->rk.dname = NULL;
136204917Sdes	alloc_special_release(a, k);
137204917Sdes}
138221420Sdes
139221420Sdesvoid
140221420Sdesrrset_data_delete(void* data, void* ATTR_UNUSED(userdata))
141197679Sdes{
142180750Sdes	struct packed_rrset_data* d = (struct packed_rrset_data*)data;
143180750Sdes	free(d);
144197679Sdes}
145197679Sdes
146197679Sdesint
147180740Sdesrrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2)
148180740Sdes{
149180740Sdes	size_t i;
150180740Sdes	size_t total;
151180740Sdes	if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count)
152180740Sdes		return 0;
153180740Sdes	total = d1->count + d1->rrsig_count;
154180740Sdes	for(i=0; i<total; i++) {
155180740Sdes		if(d1->rr_len[i] != d2->rr_len[i])
156180740Sdes			return 0;
157180740Sdes		if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0)
158180740Sdes			return 0;
159221420Sdes	}
160221420Sdes	return 1;
161221420Sdes}
162180740Sdes
163180740Sdeshashvalue_t
164180740Sdesrrset_key_hash(struct packed_rrset_key* key)
165180740Sdes{
166180740Sdes	/* type is hashed in host order */
167180740Sdes	uint16_t t = ntohs(key->type);
168180740Sdes	/* Note this MUST be identical to pkt_hash_rrset in msgparse.c */
169180740Sdes	/* this routine does not have a compressed name */
170180740Sdes	hashvalue_t h = 0xab;
171180740Sdes	h = dname_query_hash(key->dname, h);
172180740Sdes	h = hashlittle(&t, sizeof(t), h);
173180740Sdes	h = hashlittle(&key->rrset_class, sizeof(uint16_t), h);
174180740Sdes	h = hashlittle(&key->flags, sizeof(uint32_t), h);
175180740Sdes	return h;
176180740Sdes}
177180740Sdes
178180740Sdesvoid
179180740Sdespacked_rrset_ptr_fixup(struct packed_rrset_data* data)
180180740Sdes{
181180740Sdes	size_t i;
182180740Sdes	size_t total = data->count + data->rrsig_count;
183180740Sdes	uint8_t* nextrdata;
184180740Sdes	/* fixup pointers in packed rrset data */
185180740Sdes	data->rr_len = (size_t*)((uint8_t*)data +
186180750Sdes		sizeof(struct packed_rrset_data));
187180750Sdes	data->rr_data = (uint8_t**)&(data->rr_len[total]);
188180750Sdes	data->rr_ttl = (time_t*)&(data->rr_data[total]);
189262566Sdes	nextrdata = (uint8_t*)&(data->rr_ttl[total]);
190262566Sdes	for(i=0; i<total; i++) {
191262566Sdes		data->rr_data[i] = nextrdata;
192180750Sdes		nextrdata += data->rr_len[i];
193180750Sdes	}
194180750Sdes}
195180740Sdes
196180740Sdesvoid
197180740Sdesget_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname,
198180740Sdes	size_t* dname_len)
199180740Sdes{
200180740Sdes	struct packed_rrset_data* d;
201180744Sdes	size_t len;
202180744Sdes	if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME &&
203180744Sdes		ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME)
204180740Sdes		return;
205180740Sdes	d = (struct packed_rrset_data*)rrset->entry.data;
206180740Sdes	if(d->count < 1)
207180746Sdes		return;
208180746Sdes	if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */
209180746Sdes		return;
210180740Sdes	len = sldns_read_uint16(d->rr_data[0]);
211180740Sdes	if(len != d->rr_len[0] - sizeof(uint16_t))
212180740Sdes		return;
213180740Sdes	if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len)
214180740Sdes		return;
215180740Sdes	*dname = d->rr_data[0]+sizeof(uint16_t);
216180740Sdes	*dname_len = len;
217180740Sdes}
218180740Sdes
219180740Sdesvoid
220180740Sdespacked_rrset_ttl_add(struct packed_rrset_data* data, time_t add)
221180740Sdes{
222262566Sdes	size_t i;
223262566Sdes	size_t total = data->count + data->rrsig_count;
224262566Sdes	data->ttl += add;
225180740Sdes	for(i=0; i<total; i++)
226180740Sdes		data->rr_ttl[i] += add;
227180740Sdes}
228262566Sdes
229262566Sdesconst char*
230262566Sdesrrset_trust_to_string(enum rrset_trust s)
231262566Sdes{
232262566Sdes	switch(s) {
233262566Sdes	case rrset_trust_none: 		return "rrset_trust_none";
234262566Sdes	case rrset_trust_add_noAA: 	return "rrset_trust_add_noAA";
235262566Sdes	case rrset_trust_auth_noAA: 	return "rrset_trust_auth_noAA";
236262566Sdes	case rrset_trust_add_AA: 	return "rrset_trust_add_AA";
237262566Sdes	case rrset_trust_nonauth_ans_AA:return "rrset_trust_nonauth_ans_AA";
238262566Sdes	case rrset_trust_ans_noAA: 	return "rrset_trust_ans_noAA";
239262566Sdes	case rrset_trust_glue: 		return "rrset_trust_glue";
240262566Sdes	case rrset_trust_auth_AA: 	return "rrset_trust_auth_AA";
241262566Sdes	case rrset_trust_ans_AA: 	return "rrset_trust_ans_AA";
242262566Sdes	case rrset_trust_sec_noglue: 	return "rrset_trust_sec_noglue";
243262566Sdes	case rrset_trust_prim_noglue: 	return "rrset_trust_prim_noglue";
244262566Sdes	case rrset_trust_validated: 	return "rrset_trust_validated";
245262566Sdes	case rrset_trust_ultimate: 	return "rrset_trust_ultimate";
246221420Sdes	}
247221420Sdes	return "unknown_rrset_trust_value";
248221420Sdes}
249248619Sdes
250248619Sdesconst char*
251248619Sdessec_status_to_string(enum sec_status s)
252180740Sdes{
253180740Sdes	switch(s) {
254180740Sdes	case sec_status_unchecked: 	return "sec_status_unchecked";
255180740Sdes	case sec_status_bogus: 		return "sec_status_bogus";
256180740Sdes	case sec_status_indeterminate: 	return "sec_status_indeterminate";
257180740Sdes	case sec_status_insecure: 	return "sec_status_insecure";
258262566Sdes	case sec_status_secure: 	return "sec_status_secure";
259262566Sdes	}
260262566Sdes	return "unknown_sec_status_value";
261180740Sdes}
262180740Sdes
263180740Sdesvoid log_rrset_key(enum verbosity_value v, const char* str,
264255767Sdes	struct ub_packed_rrset_key* rrset)
265255767Sdes{
266255767Sdes	if(verbosity >= v)
267180740Sdes		log_nametypeclass(v, str, rrset->rk.dname,
268180740Sdes			ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
269180740Sdes}
270180740Sdes
271180740Sdesint packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i,
272180740Sdes	time_t now, char* dest, size_t dest_len)
273180740Sdes{
274180740Sdes	struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
275180740Sdes		entry.data;
276180740Sdes	uint8_t rr[65535];
277180740Sdes	size_t rlen = rrset->rk.dname_len + 2 + 2 + 4 + d->rr_len[i];
278180740Sdes	log_assert(dest_len > 0 && dest);
279255767Sdes	if(rlen > dest_len) {
280255767Sdes		dest[0] = 0;
281255767Sdes		return 0;
282180740Sdes	}
283180740Sdes	memmove(rr, rrset->rk.dname, rrset->rk.dname_len);
284180740Sdes	if(i < d->count)
285180740Sdes		memmove(rr+rrset->rk.dname_len, &rrset->rk.type, 2);
286180740Sdes	else	sldns_write_uint16(rr+rrset->rk.dname_len, LDNS_RR_TYPE_RRSIG);
287180740Sdes	memmove(rr+rrset->rk.dname_len+2, &rrset->rk.rrset_class, 2);
288180740Sdes	sldns_write_uint32(rr+rrset->rk.dname_len+4,
289180740Sdes		(uint32_t)(d->rr_ttl[i]-now));
290180740Sdes	memmove(rr+rrset->rk.dname_len+8, d->rr_data[i], d->rr_len[i]);
291180740Sdes	if(sldns_wire2str_rr_buf(rr, rlen, dest, dest_len) == -1) {
292180740Sdes		log_info("rrbuf failure %d %s", (int)d->rr_len[i], dest);
293180740Sdes		dest[0] = 0;
294180740Sdes		return 0;
295180740Sdes	}
296180740Sdes	return 1;
297180740Sdes}
298180740Sdes
299180740Sdesvoid log_packed_rrset(enum verbosity_value v, const char* str,
300180740Sdes	struct ub_packed_rrset_key* rrset)
301180740Sdes{
302248619Sdes	struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
303248619Sdes		entry.data;
304248619Sdes	char buf[65535];
305248619Sdes	size_t i;
306255767Sdes	if(verbosity < v)
307255767Sdes		return;
308255767Sdes	for(i=0; i<d->count+d->rrsig_count; i++) {
309255767Sdes		if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf))) {
310180740Sdes			log_info("%s: rr %d wire2str-error", str, (int)i);
311180740Sdes		} else {
312180740Sdes			log_info("%s: %s", str, buf);
313180740Sdes		}
314180740Sdes	}
315180740Sdes}
316180740Sdes
317180740Sdestime_t
318180740Sdesub_packed_rrset_ttl(struct ub_packed_rrset_key* key)
319180740Sdes{
320180740Sdes	struct packed_rrset_data* d = (struct packed_rrset_data*)key->
321180740Sdes		entry.data;
322180740Sdes	return d->ttl;
323180740Sdes}
324180740Sdes
325180740Sdesstruct ub_packed_rrset_key*
326180744Sdespacked_rrset_copy_region(struct ub_packed_rrset_key* key,
327180744Sdes	struct regional* region, time_t now)
328180744Sdes{
329180744Sdes	struct ub_packed_rrset_key* ck = regional_alloc(region,
330255767Sdes		sizeof(struct ub_packed_rrset_key));
331255767Sdes	struct packed_rrset_data* d;
332255767Sdes	struct packed_rrset_data* data = (struct packed_rrset_data*)
333255767Sdes		key->entry.data;
334180744Sdes	size_t dsize, i;
335180744Sdes	if(!ck)
336180744Sdes		return NULL;
337180744Sdes	ck->id = key->id;
338180740Sdes	memset(&ck->entry, 0, sizeof(ck->entry));
339180740Sdes	ck->entry.hash = key->entry.hash;
340180740Sdes	ck->entry.key = ck;
341180740Sdes	ck->rk = key->rk;
342180740Sdes	ck->rk.dname = regional_alloc_init(region, key->rk.dname,
343180740Sdes		key->rk.dname_len);
344180740Sdes	if(!ck->rk.dname)
345180740Sdes		return NULL;
346180740Sdes	dsize = packed_rrset_sizeof(data);
347180740Sdes	d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize);
348180740Sdes	if(!d)
349180740Sdes		return NULL;
350180740Sdes	ck->entry.data = d;
351180740Sdes	packed_rrset_ptr_fixup(d);
352180740Sdes	/* make TTLs relative - once per rrset */
353180740Sdes	for(i=0; i<d->count + d->rrsig_count; i++) {
354180740Sdes		if(d->rr_ttl[i] < now)
355180740Sdes			d->rr_ttl[i] = 0;
356180740Sdes		else	d->rr_ttl[i] -= now;
357180740Sdes	}
358180740Sdes	if(d->ttl < now)
359180740Sdes		d->ttl = 0;
360180740Sdes	else	d->ttl -= now;
361180740Sdes	return ck;
362180740Sdes}
363180740Sdes
364180740Sdesstruct ub_packed_rrset_key*
365180740Sdespacked_rrset_copy_alloc(struct ub_packed_rrset_key* key,
366255767Sdes	struct alloc_cache* alloc, time_t now)
367255767Sdes{
368255767Sdes	struct packed_rrset_data* fd, *dd;
369180740Sdes	struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc);
370180740Sdes	if(!dk) return NULL;
371180740Sdes	fd = (struct packed_rrset_data*)key->entry.data;
372180740Sdes	dk->entry.hash = key->entry.hash;
373180740Sdes	dk->rk = key->rk;
374180740Sdes	dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len);
375180740Sdes	if(!dk->rk.dname) {
376180740Sdes		alloc_special_release(alloc, dk);
377180740Sdes		return NULL;
378180740Sdes	}
379180740Sdes	dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd));
380180740Sdes	if(!dd) {
381180740Sdes		free(dk->rk.dname);
382180740Sdes		alloc_special_release(alloc, dk);
383180740Sdes		return NULL;
384221420Sdes	}
385221420Sdes	packed_rrset_ptr_fixup(dd);
386221420Sdes	dk->entry.data = (void*)dd;
387248619Sdes	packed_rrset_ttl_add(dd, now);
388248619Sdes	return dk;
389248619Sdes}
390255767Sdes