2 * util/data/packed_rrset.c - data storage for a set of resource records.
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * This file contains the data storage for RRsets.
43 #include "util/data/packed_rrset.h"
44 #include "util/data/dname.h"
45 #include "util/storage/lookup3.h"
47 #include "util/alloc.h"
48 #include "util/regional.h"
49 #include "util/net_help.h"
50 #include "ldns/rrdef.h"
51 #include "ldns/sbuffer.h"
52 #include "ldns/wire2str.h"
55 ub_packed_rrset_parsedelete(struct ub_packed_rrset_key
* pkey
,
56 struct alloc_cache
* alloc
)
61 free(pkey
->entry
.data
);
62 pkey
->entry
.data
= NULL
;
65 pkey
->rk
.dname
= NULL
;
67 alloc_special_release(alloc
, pkey
);
71 ub_rrset_sizefunc(void* key
, void* data
)
73 struct ub_packed_rrset_key
* k
= (struct ub_packed_rrset_key
*)key
;
74 struct packed_rrset_data
* d
= (struct packed_rrset_data
*)data
;
75 size_t s
= sizeof(struct ub_packed_rrset_key
) + k
->rk
.dname_len
;
76 s
+= packed_rrset_sizeof(d
) + lock_get_mem(&k
->entry
.lock
);
81 packed_rrset_sizeof(struct packed_rrset_data
* d
)
84 if(d
->rrsig_count
> 0) {
85 s
= ((uint8_t*)d
->rr_data
[d
->count
+d
->rrsig_count
-1] -
86 (uint8_t*)d
) + d
->rr_len
[d
->count
+d
->rrsig_count
-1];
88 log_assert(d
->count
> 0);
89 s
= ((uint8_t*)d
->rr_data
[d
->count
-1] - (uint8_t*)d
) +
90 d
->rr_len
[d
->count
-1];
96 ub_rrset_compare(void* k1
, void* k2
)
98 struct ub_packed_rrset_key
* key1
= (struct ub_packed_rrset_key
*)k1
;
99 struct ub_packed_rrset_key
* key2
= (struct ub_packed_rrset_key
*)k2
;
103 if(key1
->rk
.type
!= key2
->rk
.type
) {
104 if(key1
->rk
.type
< key2
->rk
.type
)
108 if(key1
->rk
.dname_len
!= key2
->rk
.dname_len
) {
109 if(key1
->rk
.dname_len
< key2
->rk
.dname_len
)
113 if((c
=query_dname_compare(key1
->rk
.dname
, key2
->rk
.dname
)) != 0)
115 if(key1
->rk
.rrset_class
!= key2
->rk
.rrset_class
) {
116 if(key1
->rk
.rrset_class
< key2
->rk
.rrset_class
)
120 if(key1
->rk
.flags
!= key2
->rk
.flags
) {
121 if(key1
->rk
.flags
< key2
->rk
.flags
)
129 ub_rrset_key_delete(void* key
, void* userdata
)
131 struct ub_packed_rrset_key
* k
= (struct ub_packed_rrset_key
*)key
;
132 struct alloc_cache
* a
= (struct alloc_cache
*)userdata
;
136 alloc_special_release(a
, k
);
140 rrset_data_delete(void* data
, void* ATTR_UNUSED(userdata
))
142 struct packed_rrset_data
* d
= (struct packed_rrset_data
*)data
;
147 rrsetdata_equal(struct packed_rrset_data
* d1
, struct packed_rrset_data
* d2
)
151 if(d1
->count
!= d2
->count
|| d1
->rrsig_count
!= d2
->rrsig_count
)
153 total
= d1
->count
+ d1
->rrsig_count
;
154 for(i
=0; i
<total
; i
++) {
155 if(d1
->rr_len
[i
] != d2
->rr_len
[i
])
157 if(memcmp(d1
->rr_data
[i
], d2
->rr_data
[i
], d1
->rr_len
[i
]) != 0)
164 rrset_key_hash(struct packed_rrset_key
* key
)
166 /* type is hashed in host order */
167 uint16_t t
= ntohs(key
->type
);
168 /* Note this MUST be identical to pkt_hash_rrset in msgparse.c */
169 /* this routine does not have a compressed name */
170 hashvalue_t h
= 0xab;
171 h
= dname_query_hash(key
->dname
, h
);
172 h
= hashlittle(&t
, sizeof(t
), h
);
173 h
= hashlittle(&key
->rrset_class
, sizeof(uint16_t), h
);
174 h
= hashlittle(&key
->flags
, sizeof(uint32_t), h
);
179 packed_rrset_ptr_fixup(struct packed_rrset_data
* data
)
182 size_t total
= data
->count
+ data
->rrsig_count
;
184 /* fixup pointers in packed rrset data */
185 data
->rr_len
= (size_t*)((uint8_t*)data
+
186 sizeof(struct packed_rrset_data
));
187 data
->rr_data
= (uint8_t**)&(data
->rr_len
[total
]);
188 data
->rr_ttl
= (time_t*)&(data
->rr_data
[total
]);
189 nextrdata
= (uint8_t*)&(data
->rr_ttl
[total
]);
190 for(i
=0; i
<total
; i
++) {
191 data
->rr_data
[i
] = nextrdata
;
192 nextrdata
+= data
->rr_len
[i
];
197 get_cname_target(struct ub_packed_rrset_key
* rrset
, uint8_t** dname
,
200 struct packed_rrset_data
* d
;
202 if(ntohs(rrset
->rk
.type
) != LDNS_RR_TYPE_CNAME
&&
203 ntohs(rrset
->rk
.type
) != LDNS_RR_TYPE_DNAME
)
205 d
= (struct packed_rrset_data
*)rrset
->entry
.data
;
208 if(d
->rr_len
[0] < 3) /* at least rdatalen + 0byte root label */
210 len
= sldns_read_uint16(d
->rr_data
[0]);
211 if(len
!= d
->rr_len
[0] - sizeof(uint16_t))
213 if(dname_valid(d
->rr_data
[0]+sizeof(uint16_t), len
) != len
)
215 *dname
= d
->rr_data
[0]+sizeof(uint16_t);
220 packed_rrset_ttl_add(struct packed_rrset_data
* data
, time_t add
)
223 size_t total
= data
->count
+ data
->rrsig_count
;
225 for(i
=0; i
<total
; i
++)
226 data
->rr_ttl
[i
] += add
;
230 rrset_trust_to_string(enum rrset_trust s
)
233 case rrset_trust_none
: return "rrset_trust_none";
234 case rrset_trust_add_noAA
: return "rrset_trust_add_noAA";
235 case rrset_trust_auth_noAA
: return "rrset_trust_auth_noAA";
236 case rrset_trust_add_AA
: return "rrset_trust_add_AA";
237 case rrset_trust_nonauth_ans_AA
:return "rrset_trust_nonauth_ans_AA";
238 case rrset_trust_ans_noAA
: return "rrset_trust_ans_noAA";
239 case rrset_trust_glue
: return "rrset_trust_glue";
240 case rrset_trust_auth_AA
: return "rrset_trust_auth_AA";
241 case rrset_trust_ans_AA
: return "rrset_trust_ans_AA";
242 case rrset_trust_sec_noglue
: return "rrset_trust_sec_noglue";
243 case rrset_trust_prim_noglue
: return "rrset_trust_prim_noglue";
244 case rrset_trust_validated
: return "rrset_trust_validated";
245 case rrset_trust_ultimate
: return "rrset_trust_ultimate";
247 return "unknown_rrset_trust_value";
251 sec_status_to_string(enum sec_status s
)
254 case sec_status_unchecked
: return "sec_status_unchecked";
255 case sec_status_bogus
: return "sec_status_bogus";
256 case sec_status_indeterminate
: return "sec_status_indeterminate";
257 case sec_status_insecure
: return "sec_status_insecure";
258 case sec_status_secure
: return "sec_status_secure";
260 return "unknown_sec_status_value";
263 void log_rrset_key(enum verbosity_value v
, const char* str
,
264 struct ub_packed_rrset_key
* rrset
)
267 log_nametypeclass(v
, str
, rrset
->rk
.dname
,
268 ntohs(rrset
->rk
.type
), ntohs(rrset
->rk
.rrset_class
));
271 int packed_rr_to_string(struct ub_packed_rrset_key
* rrset
, size_t i
,
272 time_t now
, char* dest
, size_t dest_len
)
274 struct packed_rrset_data
* d
= (struct packed_rrset_data
*)rrset
->
277 size_t rlen
= rrset
->rk
.dname_len
+ 2 + 2 + 4 + d
->rr_len
[i
];
278 log_assert(dest_len
> 0 && dest
);
279 if(rlen
> dest_len
) {
283 memmove(rr
, rrset
->rk
.dname
, rrset
->rk
.dname_len
);
285 memmove(rr
+rrset
->rk
.dname_len
, &rrset
->rk
.type
, 2);
286 else sldns_write_uint16(rr
+rrset
->rk
.dname_len
, LDNS_RR_TYPE_RRSIG
);
287 memmove(rr
+rrset
->rk
.dname_len
+2, &rrset
->rk
.rrset_class
, 2);
288 sldns_write_uint32(rr
+rrset
->rk
.dname_len
+4,
289 (uint32_t)(d
->rr_ttl
[i
]-now
));
290 memmove(rr
+rrset
->rk
.dname_len
+8, d
->rr_data
[i
], d
->rr_len
[i
]);
291 if(sldns_wire2str_rr_buf(rr
, rlen
, dest
, dest_len
) == -1) {
292 log_info("rrbuf failure %d %s", (int)d
->rr_len
[i
], dest
);
299 void log_packed_rrset(enum verbosity_value v
, const char* str
,
300 struct ub_packed_rrset_key
* rrset
)
302 struct packed_rrset_data
* d
= (struct packed_rrset_data
*)rrset
->
308 for(i
=0; i
<d
->count
+d
->rrsig_count
; i
++) {
309 if(!packed_rr_to_string(rrset
, i
, 0, buf
, sizeof(buf
))) {
310 log_info("%s: rr %d wire2str-error", str
, (int)i
);
312 log_info("%s: %s", str
, buf
);
318 ub_packed_rrset_ttl(struct ub_packed_rrset_key
* key
)
320 struct packed_rrset_data
* d
= (struct packed_rrset_data
*)key
->
325 struct ub_packed_rrset_key
*
326 packed_rrset_copy_region(struct ub_packed_rrset_key
* key
,
327 struct regional
* region
, time_t now
)
329 struct ub_packed_rrset_key
* ck
= regional_alloc(region
,
330 sizeof(struct ub_packed_rrset_key
));
331 struct packed_rrset_data
* d
;
332 struct packed_rrset_data
* data
= (struct packed_rrset_data
*)
338 memset(&ck
->entry
, 0, sizeof(ck
->entry
));
339 ck
->entry
.hash
= key
->entry
.hash
;
342 ck
->rk
.dname
= regional_alloc_init(region
, key
->rk
.dname
,
346 dsize
= packed_rrset_sizeof(data
);
347 d
= (struct packed_rrset_data
*)regional_alloc_init(region
, data
, dsize
);
351 packed_rrset_ptr_fixup(d
);
352 /* make TTLs relative - once per rrset */
353 for(i
=0; i
<d
->count
+ d
->rrsig_count
; i
++) {
354 if(d
->rr_ttl
[i
] < now
)
356 else d
->rr_ttl
[i
] -= now
;
364 struct ub_packed_rrset_key
*
365 packed_rrset_copy_alloc(struct ub_packed_rrset_key
* key
,
366 struct alloc_cache
* alloc
, time_t now
)
368 struct packed_rrset_data
* fd
, *dd
;
369 struct ub_packed_rrset_key
* dk
= alloc_special_obtain(alloc
);
371 fd
= (struct packed_rrset_data
*)key
->entry
.data
;
372 dk
->entry
.hash
= key
->entry
.hash
;
374 dk
->rk
.dname
= (uint8_t*)memdup(key
->rk
.dname
, key
->rk
.dname_len
);
376 alloc_special_release(alloc
, dk
);
379 dd
= (struct packed_rrset_data
*)memdup(fd
, packed_rrset_sizeof(fd
));
382 alloc_special_release(alloc
, dk
);
385 packed_rrset_ptr_fixup(dd
);
386 dk
->entry
.data
= (void*)dd
;
387 packed_rrset_ttl_add(dd
, now
);