1b7579f77SDag-Erling Smørgrav /* 2b7579f77SDag-Erling Smørgrav * daemon/cachedump.c - dump the cache to text format. 3b7579f77SDag-Erling Smørgrav * 4b7579f77SDag-Erling Smørgrav * Copyright (c) 2008, 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 functions to read and write the cache(s) 40b7579f77SDag-Erling Smørgrav * to text format. 41b7579f77SDag-Erling Smørgrav */ 42b7579f77SDag-Erling Smørgrav #include "config.h" 4317d15b25SDag-Erling Smørgrav #include <openssl/ssl.h> 44b7579f77SDag-Erling Smørgrav #include "daemon/cachedump.h" 45b7579f77SDag-Erling Smørgrav #include "daemon/remote.h" 46b7579f77SDag-Erling Smørgrav #include "daemon/worker.h" 47b7579f77SDag-Erling Smørgrav #include "services/cache/rrset.h" 48b7579f77SDag-Erling Smørgrav #include "services/cache/dns.h" 49b7579f77SDag-Erling Smørgrav #include "services/cache/infra.h" 50a39a5a69SCy Schubert #include "services/outside_network.h" 51b7579f77SDag-Erling Smørgrav #include "util/data/msgreply.h" 52b7579f77SDag-Erling Smørgrav #include "util/regional.h" 53b7579f77SDag-Erling Smørgrav #include "util/net_help.h" 54b7579f77SDag-Erling Smørgrav #include "util/data/dname.h" 55a39a5a69SCy Schubert #include "util/config_file.h" 56b7579f77SDag-Erling Smørgrav #include "iterator/iterator.h" 57b7579f77SDag-Erling Smørgrav #include "iterator/iter_delegpt.h" 58b7579f77SDag-Erling Smørgrav #include "iterator/iter_utils.h" 59b7579f77SDag-Erling Smørgrav #include "iterator/iter_fwd.h" 60b7579f77SDag-Erling Smørgrav #include "iterator/iter_hints.h" 6109a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h" 6209a3aaf3SDag-Erling Smørgrav #include "sldns/wire2str.h" 6309a3aaf3SDag-Erling Smørgrav #include "sldns/str2wire.h" 64b7579f77SDag-Erling Smørgrav 65b7579f77SDag-Erling Smørgrav /** dump one rrset zonefile line */ 66b7579f77SDag-Erling Smørgrav static int 677da0adf7SDag-Erling Smørgrav dump_rrset_line(RES* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i) 68b7579f77SDag-Erling Smørgrav { 6917d15b25SDag-Erling Smørgrav char s[65535]; 7017d15b25SDag-Erling Smørgrav if(!packed_rr_to_string(k, i, now, s, sizeof(s))) { 71b7579f77SDag-Erling Smørgrav return ssl_printf(ssl, "BADRR\n"); 72b7579f77SDag-Erling Smørgrav } 7317d15b25SDag-Erling Smørgrav return ssl_printf(ssl, "%s", s); 74b7579f77SDag-Erling Smørgrav } 75b7579f77SDag-Erling Smørgrav 76b7579f77SDag-Erling Smørgrav /** dump rrset key and data info */ 77b7579f77SDag-Erling Smørgrav static int 787da0adf7SDag-Erling Smørgrav dump_rrset(RES* ssl, struct ub_packed_rrset_key* k, 7917d15b25SDag-Erling Smørgrav struct packed_rrset_data* d, time_t now) 80b7579f77SDag-Erling Smørgrav { 81b7579f77SDag-Erling Smørgrav size_t i; 82b7579f77SDag-Erling Smørgrav /* rd lock held by caller */ 83b7579f77SDag-Erling Smørgrav if(!k || !d) return 1; 8457bddd21SDag-Erling Smørgrav if(k->id == 0) return 1; /* deleted */ 85b7579f77SDag-Erling Smørgrav if(d->ttl < now) return 1; /* expired */ 86b7579f77SDag-Erling Smørgrav 87b7579f77SDag-Erling Smørgrav /* meta line */ 8817d15b25SDag-Erling Smørgrav if(!ssl_printf(ssl, ";rrset%s " ARG_LL "d %u %u %d %d\n", 89b7579f77SDag-Erling Smørgrav (k->rk.flags & PACKED_RRSET_NSEC_AT_APEX)?" nsec_apex":"", 9017d15b25SDag-Erling Smørgrav (long long)(d->ttl - now), 91b7579f77SDag-Erling Smørgrav (unsigned)d->count, (unsigned)d->rrsig_count, 92b7579f77SDag-Erling Smørgrav (int)d->trust, (int)d->security 93b7579f77SDag-Erling Smørgrav )) 94b7579f77SDag-Erling Smørgrav return 0; 9517d15b25SDag-Erling Smørgrav for(i=0; i<d->count + d->rrsig_count; i++) { 9617d15b25SDag-Erling Smørgrav if(!dump_rrset_line(ssl, k, now, i)) 97b7579f77SDag-Erling Smørgrav return 0; 98b7579f77SDag-Erling Smørgrav } 99b7579f77SDag-Erling Smørgrav return 1; 100b7579f77SDag-Erling Smørgrav } 101b7579f77SDag-Erling Smørgrav 102b7579f77SDag-Erling Smørgrav /** dump lruhash rrset cache */ 103b7579f77SDag-Erling Smørgrav static int 1047da0adf7SDag-Erling Smørgrav dump_rrset_lruhash(RES* ssl, struct lruhash* h, time_t now) 105b7579f77SDag-Erling Smørgrav { 106b7579f77SDag-Erling Smørgrav struct lruhash_entry* e; 107b7579f77SDag-Erling Smørgrav /* lruhash already locked by caller */ 108b7579f77SDag-Erling Smørgrav /* walk in order of lru; best first */ 109b7579f77SDag-Erling Smørgrav for(e=h->lru_start; e; e = e->lru_next) { 110b7579f77SDag-Erling Smørgrav lock_rw_rdlock(&e->lock); 111b7579f77SDag-Erling Smørgrav if(!dump_rrset(ssl, (struct ub_packed_rrset_key*)e->key, 112b7579f77SDag-Erling Smørgrav (struct packed_rrset_data*)e->data, now)) { 113b7579f77SDag-Erling Smørgrav lock_rw_unlock(&e->lock); 114b7579f77SDag-Erling Smørgrav return 0; 115b7579f77SDag-Erling Smørgrav } 116b7579f77SDag-Erling Smørgrav lock_rw_unlock(&e->lock); 117b7579f77SDag-Erling Smørgrav } 118b7579f77SDag-Erling Smørgrav return 1; 119b7579f77SDag-Erling Smørgrav } 120b7579f77SDag-Erling Smørgrav 121b7579f77SDag-Erling Smørgrav /** dump rrset cache */ 122b7579f77SDag-Erling Smørgrav static int 1237da0adf7SDag-Erling Smørgrav dump_rrset_cache(RES* ssl, struct worker* worker) 124b7579f77SDag-Erling Smørgrav { 125b7579f77SDag-Erling Smørgrav struct rrset_cache* r = worker->env.rrset_cache; 126b7579f77SDag-Erling Smørgrav size_t slab; 127b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "START_RRSET_CACHE\n")) return 0; 128b7579f77SDag-Erling Smørgrav for(slab=0; slab<r->table.size; slab++) { 129b7579f77SDag-Erling Smørgrav lock_quick_lock(&r->table.array[slab]->lock); 130b7579f77SDag-Erling Smørgrav if(!dump_rrset_lruhash(ssl, r->table.array[slab], 131b7579f77SDag-Erling Smørgrav *worker->env.now)) { 132b7579f77SDag-Erling Smørgrav lock_quick_unlock(&r->table.array[slab]->lock); 133b7579f77SDag-Erling Smørgrav return 0; 134b7579f77SDag-Erling Smørgrav } 135b7579f77SDag-Erling Smørgrav lock_quick_unlock(&r->table.array[slab]->lock); 136b7579f77SDag-Erling Smørgrav } 137b7579f77SDag-Erling Smørgrav return ssl_printf(ssl, "END_RRSET_CACHE\n"); 138b7579f77SDag-Erling Smørgrav } 139b7579f77SDag-Erling Smørgrav 140b7579f77SDag-Erling Smørgrav /** dump message to rrset reference */ 141b7579f77SDag-Erling Smørgrav static int 1427da0adf7SDag-Erling Smørgrav dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k) 143b7579f77SDag-Erling Smørgrav { 144b7579f77SDag-Erling Smørgrav char* nm, *tp, *cl; 14517d15b25SDag-Erling Smørgrav nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len); 14617d15b25SDag-Erling Smørgrav tp = sldns_wire2str_type(ntohs(k->rk.type)); 14717d15b25SDag-Erling Smørgrav cl = sldns_wire2str_class(ntohs(k->rk.rrset_class)); 148b7579f77SDag-Erling Smørgrav if(!nm || !cl || !tp) { 149b7579f77SDag-Erling Smørgrav free(nm); 150b7579f77SDag-Erling Smørgrav free(tp); 151b7579f77SDag-Erling Smørgrav free(cl); 152b7579f77SDag-Erling Smørgrav return ssl_printf(ssl, "BADREF\n"); 153b7579f77SDag-Erling Smørgrav } 154b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) { 155b7579f77SDag-Erling Smørgrav free(nm); 156b7579f77SDag-Erling Smørgrav free(tp); 157b7579f77SDag-Erling Smørgrav free(cl); 158b7579f77SDag-Erling Smørgrav return 0; 159b7579f77SDag-Erling Smørgrav } 160b7579f77SDag-Erling Smørgrav free(nm); 161b7579f77SDag-Erling Smørgrav free(tp); 162b7579f77SDag-Erling Smørgrav free(cl); 163b7579f77SDag-Erling Smørgrav 164b7579f77SDag-Erling Smørgrav return 1; 165b7579f77SDag-Erling Smørgrav } 166b7579f77SDag-Erling Smørgrav 167b7579f77SDag-Erling Smørgrav /** dump message entry */ 168b7579f77SDag-Erling Smørgrav static int 1698f76bb7dSCy Schubert dump_msg(RES* ssl, struct query_info* k, struct reply_info* d, time_t now) 170b7579f77SDag-Erling Smørgrav { 171b7579f77SDag-Erling Smørgrav size_t i; 172b7579f77SDag-Erling Smørgrav char* nm, *tp, *cl; 173b7579f77SDag-Erling Smørgrav if(!k || !d) return 1; 174b7579f77SDag-Erling Smørgrav if(d->ttl < now) return 1; /* expired */ 175b7579f77SDag-Erling Smørgrav 17617d15b25SDag-Erling Smørgrav nm = sldns_wire2str_dname(k->qname, k->qname_len); 17717d15b25SDag-Erling Smørgrav tp = sldns_wire2str_type(k->qtype); 17817d15b25SDag-Erling Smørgrav cl = sldns_wire2str_class(k->qclass); 179b7579f77SDag-Erling Smørgrav if(!nm || !tp || !cl) { 180b7579f77SDag-Erling Smørgrav free(nm); 181b7579f77SDag-Erling Smørgrav free(tp); 182b7579f77SDag-Erling Smørgrav free(cl); 183b7579f77SDag-Erling Smørgrav return 1; /* skip this entry */ 184b7579f77SDag-Erling Smørgrav } 185b7579f77SDag-Erling Smørgrav if(!rrset_array_lock(d->ref, d->rrset_count, now)) { 186b7579f77SDag-Erling Smørgrav /* rrsets have timed out or do not exist */ 187b7579f77SDag-Erling Smørgrav free(nm); 188b7579f77SDag-Erling Smørgrav free(tp); 189b7579f77SDag-Erling Smørgrav free(cl); 190b7579f77SDag-Erling Smørgrav return 1; /* skip this entry */ 191b7579f77SDag-Erling Smørgrav } 192b7579f77SDag-Erling Smørgrav 193b7579f77SDag-Erling Smørgrav /* meta line */ 1948f76bb7dSCy Schubert if(!ssl_printf(ssl, "msg %s %s %s %d %d " ARG_LL "d %d %u %u %u %d %s\n", 195b7579f77SDag-Erling Smørgrav nm, cl, tp, 196b7579f77SDag-Erling Smørgrav (int)d->flags, (int)d->qdcount, 19717d15b25SDag-Erling Smørgrav (long long)(d->ttl-now), (int)d->security, 198b7579f77SDag-Erling Smørgrav (unsigned)d->an_numrrsets, 199b7579f77SDag-Erling Smørgrav (unsigned)d->ns_numrrsets, 2008f76bb7dSCy Schubert (unsigned)d->ar_numrrsets, 2018f76bb7dSCy Schubert (int)d->reason_bogus, 2028f76bb7dSCy Schubert d->reason_bogus_str?d->reason_bogus_str:"")) { 203b7579f77SDag-Erling Smørgrav free(nm); 204b7579f77SDag-Erling Smørgrav free(tp); 205b7579f77SDag-Erling Smørgrav free(cl); 206b7579f77SDag-Erling Smørgrav rrset_array_unlock(d->ref, d->rrset_count); 207b7579f77SDag-Erling Smørgrav return 0; 208b7579f77SDag-Erling Smørgrav } 209b7579f77SDag-Erling Smørgrav free(nm); 210b7579f77SDag-Erling Smørgrav free(tp); 211b7579f77SDag-Erling Smørgrav free(cl); 212b7579f77SDag-Erling Smørgrav 213b7579f77SDag-Erling Smørgrav for(i=0; i<d->rrset_count; i++) { 214b7579f77SDag-Erling Smørgrav if(!dump_msg_ref(ssl, d->rrsets[i])) { 215b7579f77SDag-Erling Smørgrav rrset_array_unlock(d->ref, d->rrset_count); 216b7579f77SDag-Erling Smørgrav return 0; 217b7579f77SDag-Erling Smørgrav } 218b7579f77SDag-Erling Smørgrav } 219b7579f77SDag-Erling Smørgrav rrset_array_unlock(d->ref, d->rrset_count); 220b7579f77SDag-Erling Smørgrav 221b7579f77SDag-Erling Smørgrav return 1; 222b7579f77SDag-Erling Smørgrav } 223b7579f77SDag-Erling Smørgrav 224b7579f77SDag-Erling Smørgrav /** copy msg to worker pad */ 225b7579f77SDag-Erling Smørgrav static int 226b7579f77SDag-Erling Smørgrav copy_msg(struct regional* region, struct lruhash_entry* e, 227b7579f77SDag-Erling Smørgrav struct query_info** k, struct reply_info** d) 228b7579f77SDag-Erling Smørgrav { 229b7579f77SDag-Erling Smørgrav struct reply_info* rep = (struct reply_info*)e->data; 23009a3aaf3SDag-Erling Smørgrav if(rep->rrset_count > RR_COUNT_MAX) 23109a3aaf3SDag-Erling Smørgrav return 0; /* to protect against integer overflow */ 232b7579f77SDag-Erling Smørgrav *d = (struct reply_info*)regional_alloc_init(region, e->data, 233b7579f77SDag-Erling Smørgrav sizeof(struct reply_info) + 234b7579f77SDag-Erling Smørgrav sizeof(struct rrset_ref) * (rep->rrset_count-1) + 235b7579f77SDag-Erling Smørgrav sizeof(struct ub_packed_rrset_key*) * rep->rrset_count); 236b7579f77SDag-Erling Smørgrav if(!*d) 237b7579f77SDag-Erling Smørgrav return 0; 23804b59eacSDag-Erling Smørgrav (*d)->rrsets = (struct ub_packed_rrset_key**)(void *)( 239b7579f77SDag-Erling Smørgrav (uint8_t*)(&((*d)->ref[0])) + 240b7579f77SDag-Erling Smørgrav sizeof(struct rrset_ref) * rep->rrset_count); 241b7579f77SDag-Erling Smørgrav *k = (struct query_info*)regional_alloc_init(region, 242b7579f77SDag-Erling Smørgrav e->key, sizeof(struct query_info)); 243b7579f77SDag-Erling Smørgrav if(!*k) 244b7579f77SDag-Erling Smørgrav return 0; 245b7579f77SDag-Erling Smørgrav (*k)->qname = regional_alloc_init(region, 246b7579f77SDag-Erling Smørgrav (*k)->qname, (*k)->qname_len); 247b7579f77SDag-Erling Smørgrav return (*k)->qname != NULL; 248b7579f77SDag-Erling Smørgrav } 249b7579f77SDag-Erling Smørgrav 250b7579f77SDag-Erling Smørgrav /** dump lruhash msg cache */ 251b7579f77SDag-Erling Smørgrav static int 2527da0adf7SDag-Erling Smørgrav dump_msg_lruhash(RES* ssl, struct worker* worker, struct lruhash* h) 253b7579f77SDag-Erling Smørgrav { 254b7579f77SDag-Erling Smørgrav struct lruhash_entry* e; 255b7579f77SDag-Erling Smørgrav struct query_info* k; 256b7579f77SDag-Erling Smørgrav struct reply_info* d; 257b7579f77SDag-Erling Smørgrav 258b7579f77SDag-Erling Smørgrav /* lruhash already locked by caller */ 259b7579f77SDag-Erling Smørgrav /* walk in order of lru; best first */ 260b7579f77SDag-Erling Smørgrav for(e=h->lru_start; e; e = e->lru_next) { 261b7579f77SDag-Erling Smørgrav regional_free_all(worker->scratchpad); 262b7579f77SDag-Erling Smørgrav lock_rw_rdlock(&e->lock); 263b7579f77SDag-Erling Smørgrav /* make copy of rrset in worker buffer */ 264b7579f77SDag-Erling Smørgrav if(!copy_msg(worker->scratchpad, e, &k, &d)) { 265b7579f77SDag-Erling Smørgrav lock_rw_unlock(&e->lock); 266b7579f77SDag-Erling Smørgrav return 0; 267b7579f77SDag-Erling Smørgrav } 268b7579f77SDag-Erling Smørgrav lock_rw_unlock(&e->lock); 269b7579f77SDag-Erling Smørgrav /* release lock so we can lookup the rrset references 270b7579f77SDag-Erling Smørgrav * in the rrset cache */ 271b7579f77SDag-Erling Smørgrav if(!dump_msg(ssl, k, d, *worker->env.now)) { 272b7579f77SDag-Erling Smørgrav return 0; 273b7579f77SDag-Erling Smørgrav } 274b7579f77SDag-Erling Smørgrav } 275b7579f77SDag-Erling Smørgrav return 1; 276b7579f77SDag-Erling Smørgrav } 277b7579f77SDag-Erling Smørgrav 278b7579f77SDag-Erling Smørgrav /** dump msg cache */ 279b7579f77SDag-Erling Smørgrav static int 2807da0adf7SDag-Erling Smørgrav dump_msg_cache(RES* ssl, struct worker* worker) 281b7579f77SDag-Erling Smørgrav { 282b7579f77SDag-Erling Smørgrav struct slabhash* sh = worker->env.msg_cache; 283b7579f77SDag-Erling Smørgrav size_t slab; 284b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "START_MSG_CACHE\n")) return 0; 285b7579f77SDag-Erling Smørgrav for(slab=0; slab<sh->size; slab++) { 286b7579f77SDag-Erling Smørgrav lock_quick_lock(&sh->array[slab]->lock); 287b7579f77SDag-Erling Smørgrav if(!dump_msg_lruhash(ssl, worker, sh->array[slab])) { 288b7579f77SDag-Erling Smørgrav lock_quick_unlock(&sh->array[slab]->lock); 289b7579f77SDag-Erling Smørgrav return 0; 290b7579f77SDag-Erling Smørgrav } 291b7579f77SDag-Erling Smørgrav lock_quick_unlock(&sh->array[slab]->lock); 292b7579f77SDag-Erling Smørgrav } 293b7579f77SDag-Erling Smørgrav return ssl_printf(ssl, "END_MSG_CACHE\n"); 294b7579f77SDag-Erling Smørgrav } 295b7579f77SDag-Erling Smørgrav 296b7579f77SDag-Erling Smørgrav int 2977da0adf7SDag-Erling Smørgrav dump_cache(RES* ssl, struct worker* worker) 298b7579f77SDag-Erling Smørgrav { 299b7579f77SDag-Erling Smørgrav if(!dump_rrset_cache(ssl, worker)) 300b7579f77SDag-Erling Smørgrav return 0; 301b7579f77SDag-Erling Smørgrav if(!dump_msg_cache(ssl, worker)) 302b7579f77SDag-Erling Smørgrav return 0; 303b7579f77SDag-Erling Smørgrav return ssl_printf(ssl, "EOF\n"); 304b7579f77SDag-Erling Smørgrav } 305b7579f77SDag-Erling Smørgrav 306b7579f77SDag-Erling Smørgrav /** read a line from ssl into buffer */ 307b7579f77SDag-Erling Smørgrav static int 3087da0adf7SDag-Erling Smørgrav ssl_read_buf(RES* ssl, sldns_buffer* buf) 309b7579f77SDag-Erling Smørgrav { 31017d15b25SDag-Erling Smørgrav return ssl_read_line(ssl, (char*)sldns_buffer_begin(buf), 31117d15b25SDag-Erling Smørgrav sldns_buffer_capacity(buf)); 312b7579f77SDag-Erling Smørgrav } 313b7579f77SDag-Erling Smørgrav 314b7579f77SDag-Erling Smørgrav /** check fixed text on line */ 315b7579f77SDag-Erling Smørgrav static int 3167da0adf7SDag-Erling Smørgrav read_fixed(RES* ssl, sldns_buffer* buf, const char* str) 317b7579f77SDag-Erling Smørgrav { 318b7579f77SDag-Erling Smørgrav if(!ssl_read_buf(ssl, buf)) return 0; 31917d15b25SDag-Erling Smørgrav return (strcmp((char*)sldns_buffer_begin(buf), str) == 0); 320b7579f77SDag-Erling Smørgrav } 321b7579f77SDag-Erling Smørgrav 322b7579f77SDag-Erling Smørgrav /** load an RR into rrset */ 323b7579f77SDag-Erling Smørgrav static int 3247da0adf7SDag-Erling Smørgrav load_rr(RES* ssl, sldns_buffer* buf, struct regional* region, 325b7579f77SDag-Erling Smørgrav struct ub_packed_rrset_key* rk, struct packed_rrset_data* d, 32617d15b25SDag-Erling Smørgrav unsigned int i, int is_rrsig, int* go_on, time_t now) 327b7579f77SDag-Erling Smørgrav { 32817d15b25SDag-Erling Smørgrav uint8_t rr[LDNS_RR_BUF_SIZE]; 32917d15b25SDag-Erling Smørgrav size_t rr_len = sizeof(rr), dname_len = 0; 33017d15b25SDag-Erling Smørgrav int status; 331b7579f77SDag-Erling Smørgrav 332b7579f77SDag-Erling Smørgrav /* read the line */ 333b7579f77SDag-Erling Smørgrav if(!ssl_read_buf(ssl, buf)) 334b7579f77SDag-Erling Smørgrav return 0; 33517d15b25SDag-Erling Smørgrav if(strncmp((char*)sldns_buffer_begin(buf), "BADRR\n", 6) == 0) { 336b7579f77SDag-Erling Smørgrav *go_on = 0; 337b7579f77SDag-Erling Smørgrav return 1; 338b7579f77SDag-Erling Smørgrav } 33917d15b25SDag-Erling Smørgrav status = sldns_str2wire_rr_buf((char*)sldns_buffer_begin(buf), rr, 34017d15b25SDag-Erling Smørgrav &rr_len, &dname_len, 3600, NULL, 0, NULL, 0); 34117d15b25SDag-Erling Smørgrav if(status != 0) { 342b7579f77SDag-Erling Smørgrav log_warn("error cannot parse rr: %s: %s", 34317d15b25SDag-Erling Smørgrav sldns_get_errorstr_parse(status), 34417d15b25SDag-Erling Smørgrav (char*)sldns_buffer_begin(buf)); 345b7579f77SDag-Erling Smørgrav return 0; 346b7579f77SDag-Erling Smørgrav } 34717d15b25SDag-Erling Smørgrav if(is_rrsig && sldns_wirerr_get_type(rr, rr_len, dname_len) 34817d15b25SDag-Erling Smørgrav != LDNS_RR_TYPE_RRSIG) { 349b7579f77SDag-Erling Smørgrav log_warn("error expected rrsig but got %s", 35017d15b25SDag-Erling Smørgrav (char*)sldns_buffer_begin(buf)); 351b7579f77SDag-Erling Smørgrav return 0; 352b7579f77SDag-Erling Smørgrav } 353b7579f77SDag-Erling Smørgrav 354b7579f77SDag-Erling Smørgrav /* convert ldns rr into packed_rr */ 35517d15b25SDag-Erling Smørgrav d->rr_ttl[i] = (time_t)sldns_wirerr_get_ttl(rr, rr_len, dname_len) + now; 35617d15b25SDag-Erling Smørgrav sldns_buffer_clear(buf); 35717d15b25SDag-Erling Smørgrav d->rr_len[i] = sldns_wirerr_get_rdatalen(rr, rr_len, dname_len)+2; 358b7579f77SDag-Erling Smørgrav d->rr_data[i] = (uint8_t*)regional_alloc_init(region, 35917d15b25SDag-Erling Smørgrav sldns_wirerr_get_rdatawl(rr, rr_len, dname_len), d->rr_len[i]); 360b7579f77SDag-Erling Smørgrav if(!d->rr_data[i]) { 361b7579f77SDag-Erling Smørgrav log_warn("error out of memory"); 362b7579f77SDag-Erling Smørgrav return 0; 363b7579f77SDag-Erling Smørgrav } 364b7579f77SDag-Erling Smørgrav 365b7579f77SDag-Erling Smørgrav /* if first entry, fill the key structure */ 366b7579f77SDag-Erling Smørgrav if(i==0) { 36717d15b25SDag-Erling Smørgrav rk->rk.type = htons(sldns_wirerr_get_type(rr, rr_len, dname_len)); 36817d15b25SDag-Erling Smørgrav rk->rk.rrset_class = htons(sldns_wirerr_get_class(rr, rr_len, dname_len)); 36917d15b25SDag-Erling Smørgrav rk->rk.dname_len = dname_len; 37017d15b25SDag-Erling Smørgrav rk->rk.dname = regional_alloc_init(region, rr, dname_len); 371b7579f77SDag-Erling Smørgrav if(!rk->rk.dname) { 372b7579f77SDag-Erling Smørgrav log_warn("error out of memory"); 373b7579f77SDag-Erling Smørgrav return 0; 374b7579f77SDag-Erling Smørgrav } 375b7579f77SDag-Erling Smørgrav } 376b7579f77SDag-Erling Smørgrav 377b7579f77SDag-Erling Smørgrav return 1; 378b7579f77SDag-Erling Smørgrav } 379b7579f77SDag-Erling Smørgrav 380b7579f77SDag-Erling Smørgrav /** move entry into cache */ 381b7579f77SDag-Erling Smørgrav static int 382b7579f77SDag-Erling Smørgrav move_into_cache(struct ub_packed_rrset_key* k, 383b7579f77SDag-Erling Smørgrav struct packed_rrset_data* d, struct worker* worker) 384b7579f77SDag-Erling Smørgrav { 385b7579f77SDag-Erling Smørgrav struct ub_packed_rrset_key* ak; 386b7579f77SDag-Erling Smørgrav struct packed_rrset_data* ad; 387b7579f77SDag-Erling Smørgrav size_t s, i, num = d->count + d->rrsig_count; 388b7579f77SDag-Erling Smørgrav struct rrset_ref ref; 389b7579f77SDag-Erling Smørgrav uint8_t* p; 390b7579f77SDag-Erling Smørgrav 3911838dec3SCy Schubert ak = alloc_special_obtain(worker->alloc); 392b7579f77SDag-Erling Smørgrav if(!ak) { 393b7579f77SDag-Erling Smørgrav log_warn("error out of memory"); 394b7579f77SDag-Erling Smørgrav return 0; 395b7579f77SDag-Erling Smørgrav } 396b7579f77SDag-Erling Smørgrav ak->entry.data = NULL; 397b7579f77SDag-Erling Smørgrav ak->rk = k->rk; 398b7579f77SDag-Erling Smørgrav ak->entry.hash = rrset_key_hash(&k->rk); 399b7579f77SDag-Erling Smørgrav ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len); 400b7579f77SDag-Erling Smørgrav if(!ak->rk.dname) { 401b7579f77SDag-Erling Smørgrav log_warn("error out of memory"); 4021838dec3SCy Schubert ub_packed_rrset_parsedelete(ak, worker->alloc); 403b7579f77SDag-Erling Smørgrav return 0; 404b7579f77SDag-Erling Smørgrav } 405b7579f77SDag-Erling Smørgrav s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) + 40617d15b25SDag-Erling Smørgrav sizeof(time_t))* num; 407b7579f77SDag-Erling Smørgrav for(i=0; i<num; i++) 408b7579f77SDag-Erling Smørgrav s += d->rr_len[i]; 409b7579f77SDag-Erling Smørgrav ad = (struct packed_rrset_data*)malloc(s); 410b7579f77SDag-Erling Smørgrav if(!ad) { 411b7579f77SDag-Erling Smørgrav log_warn("error out of memory"); 4121838dec3SCy Schubert ub_packed_rrset_parsedelete(ak, worker->alloc); 413b7579f77SDag-Erling Smørgrav return 0; 414b7579f77SDag-Erling Smørgrav } 415b7579f77SDag-Erling Smørgrav p = (uint8_t*)ad; 416b7579f77SDag-Erling Smørgrav memmove(p, d, sizeof(*ad)); 417b7579f77SDag-Erling Smørgrav p += sizeof(*ad); 418b7579f77SDag-Erling Smørgrav memmove(p, &d->rr_len[0], sizeof(size_t)*num); 419b7579f77SDag-Erling Smørgrav p += sizeof(size_t)*num; 420b7579f77SDag-Erling Smørgrav memmove(p, &d->rr_data[0], sizeof(uint8_t*)*num); 421b7579f77SDag-Erling Smørgrav p += sizeof(uint8_t*)*num; 42217d15b25SDag-Erling Smørgrav memmove(p, &d->rr_ttl[0], sizeof(time_t)*num); 42317d15b25SDag-Erling Smørgrav p += sizeof(time_t)*num; 424b7579f77SDag-Erling Smørgrav for(i=0; i<num; i++) { 425b7579f77SDag-Erling Smørgrav memmove(p, d->rr_data[i], d->rr_len[i]); 426b7579f77SDag-Erling Smørgrav p += d->rr_len[i]; 427b7579f77SDag-Erling Smørgrav } 428b7579f77SDag-Erling Smørgrav packed_rrset_ptr_fixup(ad); 429b7579f77SDag-Erling Smørgrav 430b7579f77SDag-Erling Smørgrav ak->entry.data = ad; 431b7579f77SDag-Erling Smørgrav 432b7579f77SDag-Erling Smørgrav ref.key = ak; 433b7579f77SDag-Erling Smørgrav ref.id = ak->id; 434b7579f77SDag-Erling Smørgrav (void)rrset_cache_update(worker->env.rrset_cache, &ref, 4351838dec3SCy Schubert worker->alloc, *worker->env.now); 4361838dec3SCy Schubert 437b7579f77SDag-Erling Smørgrav return 1; 438b7579f77SDag-Erling Smørgrav } 439b7579f77SDag-Erling Smørgrav 440b7579f77SDag-Erling Smørgrav /** load an rrset entry */ 441b7579f77SDag-Erling Smørgrav static int 4427da0adf7SDag-Erling Smørgrav load_rrset(RES* ssl, sldns_buffer* buf, struct worker* worker) 443b7579f77SDag-Erling Smørgrav { 44417d15b25SDag-Erling Smørgrav char* s = (char*)sldns_buffer_begin(buf); 445b7579f77SDag-Erling Smørgrav struct regional* region = worker->scratchpad; 446b7579f77SDag-Erling Smørgrav struct ub_packed_rrset_key* rk; 447b7579f77SDag-Erling Smørgrav struct packed_rrset_data* d; 44817d15b25SDag-Erling Smørgrav unsigned int rr_count, rrsig_count, trust, security; 44917d15b25SDag-Erling Smørgrav long long ttl; 450b7579f77SDag-Erling Smørgrav unsigned int i; 451b7579f77SDag-Erling Smørgrav int go_on = 1; 452b7579f77SDag-Erling Smørgrav regional_free_all(region); 453b7579f77SDag-Erling Smørgrav 454b7579f77SDag-Erling Smørgrav rk = (struct ub_packed_rrset_key*)regional_alloc_zero(region, 455b7579f77SDag-Erling Smørgrav sizeof(*rk)); 456b7579f77SDag-Erling Smørgrav d = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*d)); 457b7579f77SDag-Erling Smørgrav if(!rk || !d) { 458b7579f77SDag-Erling Smørgrav log_warn("error out of memory"); 459b7579f77SDag-Erling Smørgrav return 0; 460b7579f77SDag-Erling Smørgrav } 461b7579f77SDag-Erling Smørgrav 462b7579f77SDag-Erling Smørgrav if(strncmp(s, ";rrset", 6) != 0) { 463b7579f77SDag-Erling Smørgrav log_warn("error expected ';rrset' but got %s", s); 464b7579f77SDag-Erling Smørgrav return 0; 465b7579f77SDag-Erling Smørgrav } 466b7579f77SDag-Erling Smørgrav s += 6; 467b7579f77SDag-Erling Smørgrav if(strncmp(s, " nsec_apex", 10) == 0) { 468b7579f77SDag-Erling Smørgrav s += 10; 469b7579f77SDag-Erling Smørgrav rk->rk.flags |= PACKED_RRSET_NSEC_AT_APEX; 470b7579f77SDag-Erling Smørgrav } 47117d15b25SDag-Erling Smørgrav if(sscanf(s, " " ARG_LL "d %u %u %u %u", &ttl, &rr_count, &rrsig_count, 472b7579f77SDag-Erling Smørgrav &trust, &security) != 5) { 473b7579f77SDag-Erling Smørgrav log_warn("error bad rrset spec %s", s); 474b7579f77SDag-Erling Smørgrav return 0; 475b7579f77SDag-Erling Smørgrav } 476b7579f77SDag-Erling Smørgrav if(rr_count == 0 && rrsig_count == 0) { 477b7579f77SDag-Erling Smørgrav log_warn("bad rrset without contents"); 478b7579f77SDag-Erling Smørgrav return 0; 479b7579f77SDag-Erling Smørgrav } 48009a3aaf3SDag-Erling Smørgrav if(rr_count > RR_COUNT_MAX || rrsig_count > RR_COUNT_MAX) { 48109a3aaf3SDag-Erling Smørgrav log_warn("bad rrset with too many rrs"); 48209a3aaf3SDag-Erling Smørgrav return 0; 48309a3aaf3SDag-Erling Smørgrav } 484b7579f77SDag-Erling Smørgrav d->count = (size_t)rr_count; 485b7579f77SDag-Erling Smørgrav d->rrsig_count = (size_t)rrsig_count; 486b7579f77SDag-Erling Smørgrav d->security = (enum sec_status)security; 487b7579f77SDag-Erling Smørgrav d->trust = (enum rrset_trust)trust; 48817d15b25SDag-Erling Smørgrav d->ttl = (time_t)ttl + *worker->env.now; 489b7579f77SDag-Erling Smørgrav 490b7579f77SDag-Erling Smørgrav d->rr_len = regional_alloc_zero(region, 491b7579f77SDag-Erling Smørgrav sizeof(size_t)*(d->count+d->rrsig_count)); 492b7579f77SDag-Erling Smørgrav d->rr_ttl = regional_alloc_zero(region, 49317d15b25SDag-Erling Smørgrav sizeof(time_t)*(d->count+d->rrsig_count)); 494b7579f77SDag-Erling Smørgrav d->rr_data = regional_alloc_zero(region, 495b7579f77SDag-Erling Smørgrav sizeof(uint8_t*)*(d->count+d->rrsig_count)); 496b7579f77SDag-Erling Smørgrav if(!d->rr_len || !d->rr_ttl || !d->rr_data) { 497b7579f77SDag-Erling Smørgrav log_warn("error out of memory"); 498b7579f77SDag-Erling Smørgrav return 0; 499b7579f77SDag-Erling Smørgrav } 500b7579f77SDag-Erling Smørgrav 501b7579f77SDag-Erling Smørgrav /* read the rr's themselves */ 502b7579f77SDag-Erling Smørgrav for(i=0; i<rr_count; i++) { 503b7579f77SDag-Erling Smørgrav if(!load_rr(ssl, buf, region, rk, d, i, 0, 504b7579f77SDag-Erling Smørgrav &go_on, *worker->env.now)) { 505b7579f77SDag-Erling Smørgrav log_warn("could not read rr %u", i); 506b7579f77SDag-Erling Smørgrav return 0; 507b7579f77SDag-Erling Smørgrav } 508b7579f77SDag-Erling Smørgrav } 509b7579f77SDag-Erling Smørgrav for(i=0; i<rrsig_count; i++) { 510b7579f77SDag-Erling Smørgrav if(!load_rr(ssl, buf, region, rk, d, i+rr_count, 1, 511b7579f77SDag-Erling Smørgrav &go_on, *worker->env.now)) { 512b7579f77SDag-Erling Smørgrav log_warn("could not read rrsig %u", i); 513b7579f77SDag-Erling Smørgrav return 0; 514b7579f77SDag-Erling Smørgrav } 515b7579f77SDag-Erling Smørgrav } 516b7579f77SDag-Erling Smørgrav if(!go_on) { 517b7579f77SDag-Erling Smørgrav /* skip this entry */ 518b7579f77SDag-Erling Smørgrav return 1; 519b7579f77SDag-Erling Smørgrav } 520b7579f77SDag-Erling Smørgrav 521b7579f77SDag-Erling Smørgrav return move_into_cache(rk, d, worker); 522b7579f77SDag-Erling Smørgrav } 523b7579f77SDag-Erling Smørgrav 524b7579f77SDag-Erling Smørgrav /** load rrset cache */ 525b7579f77SDag-Erling Smørgrav static int 5267da0adf7SDag-Erling Smørgrav load_rrset_cache(RES* ssl, struct worker* worker) 527b7579f77SDag-Erling Smørgrav { 52817d15b25SDag-Erling Smørgrav sldns_buffer* buf = worker->env.scratch_buffer; 529b7579f77SDag-Erling Smørgrav if(!read_fixed(ssl, buf, "START_RRSET_CACHE")) return 0; 530b7579f77SDag-Erling Smørgrav while(ssl_read_buf(ssl, buf) && 53117d15b25SDag-Erling Smørgrav strcmp((char*)sldns_buffer_begin(buf), "END_RRSET_CACHE")!=0) { 532b7579f77SDag-Erling Smørgrav if(!load_rrset(ssl, buf, worker)) 533b7579f77SDag-Erling Smørgrav return 0; 534b7579f77SDag-Erling Smørgrav } 535b7579f77SDag-Erling Smørgrav return 1; 536b7579f77SDag-Erling Smørgrav } 537b7579f77SDag-Erling Smørgrav 538b7579f77SDag-Erling Smørgrav /** read qinfo from next three words */ 539b7579f77SDag-Erling Smørgrav static char* 54017d15b25SDag-Erling Smørgrav load_qinfo(char* str, struct query_info* qinfo, struct regional* region) 541b7579f77SDag-Erling Smørgrav { 542b7579f77SDag-Erling Smørgrav /* s is part of the buf */ 543b7579f77SDag-Erling Smørgrav char* s = str; 54417d15b25SDag-Erling Smørgrav uint8_t rr[LDNS_RR_BUF_SIZE]; 54517d15b25SDag-Erling Smørgrav size_t rr_len = sizeof(rr), dname_len = 0; 54617d15b25SDag-Erling Smørgrav int status; 547b7579f77SDag-Erling Smørgrav 548b7579f77SDag-Erling Smørgrav /* skip three words */ 549b7579f77SDag-Erling Smørgrav s = strchr(str, ' '); 550b7579f77SDag-Erling Smørgrav if(s) s = strchr(s+1, ' '); 551b7579f77SDag-Erling Smørgrav if(s) s = strchr(s+1, ' '); 552b7579f77SDag-Erling Smørgrav if(!s) { 553b7579f77SDag-Erling Smørgrav log_warn("error line too short, %s", str); 554b7579f77SDag-Erling Smørgrav return NULL; 555b7579f77SDag-Erling Smørgrav } 556b7579f77SDag-Erling Smørgrav s[0] = 0; 557b7579f77SDag-Erling Smørgrav s++; 558b7579f77SDag-Erling Smørgrav 559b7579f77SDag-Erling Smørgrav /* parse them */ 56017d15b25SDag-Erling Smørgrav status = sldns_str2wire_rr_question_buf(str, rr, &rr_len, &dname_len, 56117d15b25SDag-Erling Smørgrav NULL, 0, NULL, 0); 56217d15b25SDag-Erling Smørgrav if(status != 0) { 563b7579f77SDag-Erling Smørgrav log_warn("error cannot parse: %s %s", 56417d15b25SDag-Erling Smørgrav sldns_get_errorstr_parse(status), str); 565b7579f77SDag-Erling Smørgrav return NULL; 566b7579f77SDag-Erling Smørgrav } 56717d15b25SDag-Erling Smørgrav qinfo->qtype = sldns_wirerr_get_type(rr, rr_len, dname_len); 56817d15b25SDag-Erling Smørgrav qinfo->qclass = sldns_wirerr_get_class(rr, rr_len, dname_len); 56917d15b25SDag-Erling Smørgrav qinfo->qname_len = dname_len; 57017d15b25SDag-Erling Smørgrav qinfo->qname = (uint8_t*)regional_alloc_init(region, rr, dname_len); 571bc892140SDag-Erling Smørgrav qinfo->local_alias = NULL; 572b7579f77SDag-Erling Smørgrav if(!qinfo->qname) { 573b7579f77SDag-Erling Smørgrav log_warn("error out of memory"); 574b7579f77SDag-Erling Smørgrav return NULL; 575b7579f77SDag-Erling Smørgrav } 576b7579f77SDag-Erling Smørgrav 577b7579f77SDag-Erling Smørgrav return s; 578b7579f77SDag-Erling Smørgrav } 579b7579f77SDag-Erling Smørgrav 580b7579f77SDag-Erling Smørgrav /** load a msg rrset reference */ 581b7579f77SDag-Erling Smørgrav static int 5827da0adf7SDag-Erling Smørgrav load_ref(RES* ssl, sldns_buffer* buf, struct worker* worker, 583b7579f77SDag-Erling Smørgrav struct regional *region, struct ub_packed_rrset_key** rrset, 584b7579f77SDag-Erling Smørgrav int* go_on) 585b7579f77SDag-Erling Smørgrav { 58617d15b25SDag-Erling Smørgrav char* s = (char*)sldns_buffer_begin(buf); 587b7579f77SDag-Erling Smørgrav struct query_info qinfo; 588b7579f77SDag-Erling Smørgrav unsigned int flags; 589b7579f77SDag-Erling Smørgrav struct ub_packed_rrset_key* k; 590b7579f77SDag-Erling Smørgrav 591b7579f77SDag-Erling Smørgrav /* read line */ 592b7579f77SDag-Erling Smørgrav if(!ssl_read_buf(ssl, buf)) 593b7579f77SDag-Erling Smørgrav return 0; 594b7579f77SDag-Erling Smørgrav if(strncmp(s, "BADREF", 6) == 0) { 595b7579f77SDag-Erling Smørgrav *go_on = 0; /* its bad, skip it and skip message */ 596b7579f77SDag-Erling Smørgrav return 1; 597b7579f77SDag-Erling Smørgrav } 598b7579f77SDag-Erling Smørgrav 59917d15b25SDag-Erling Smørgrav s = load_qinfo(s, &qinfo, region); 600b7579f77SDag-Erling Smørgrav if(!s) { 601b7579f77SDag-Erling Smørgrav return 0; 602b7579f77SDag-Erling Smørgrav } 603b7579f77SDag-Erling Smørgrav if(sscanf(s, " %u", &flags) != 1) { 604b7579f77SDag-Erling Smørgrav log_warn("error cannot parse flags: %s", s); 605b7579f77SDag-Erling Smørgrav return 0; 606b7579f77SDag-Erling Smørgrav } 607b7579f77SDag-Erling Smørgrav 608b7579f77SDag-Erling Smørgrav /* lookup in cache */ 609b7579f77SDag-Erling Smørgrav k = rrset_cache_lookup(worker->env.rrset_cache, qinfo.qname, 610b7579f77SDag-Erling Smørgrav qinfo.qname_len, qinfo.qtype, qinfo.qclass, 611b7579f77SDag-Erling Smørgrav (uint32_t)flags, *worker->env.now, 0); 612b7579f77SDag-Erling Smørgrav if(!k) { 613b7579f77SDag-Erling Smørgrav /* not found or expired */ 614b7579f77SDag-Erling Smørgrav *go_on = 0; 615b7579f77SDag-Erling Smørgrav return 1; 616b7579f77SDag-Erling Smørgrav } 617b7579f77SDag-Erling Smørgrav 618b7579f77SDag-Erling Smørgrav /* store in result */ 619b7579f77SDag-Erling Smørgrav *rrset = packed_rrset_copy_region(k, region, *worker->env.now); 620b7579f77SDag-Erling Smørgrav lock_rw_unlock(&k->entry.lock); 621b7579f77SDag-Erling Smørgrav 622b7579f77SDag-Erling Smørgrav return (*rrset != NULL); 623b7579f77SDag-Erling Smørgrav } 624b7579f77SDag-Erling Smørgrav 625b7579f77SDag-Erling Smørgrav /** load a msg entry */ 626b7579f77SDag-Erling Smørgrav static int 6277da0adf7SDag-Erling Smørgrav load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker) 628b7579f77SDag-Erling Smørgrav { 629b7579f77SDag-Erling Smørgrav struct regional* region = worker->scratchpad; 630b7579f77SDag-Erling Smørgrav struct query_info qinf; 631b7579f77SDag-Erling Smørgrav struct reply_info rep; 63217d15b25SDag-Erling Smørgrav char* s = (char*)sldns_buffer_begin(buf); 63317d15b25SDag-Erling Smørgrav unsigned int flags, qdcount, security, an, ns, ar; 63417d15b25SDag-Erling Smørgrav long long ttl; 635b7579f77SDag-Erling Smørgrav size_t i; 636b7579f77SDag-Erling Smørgrav int go_on = 1; 6378f76bb7dSCy Schubert int ede; 6388f76bb7dSCy Schubert int consumed = 0; 6398f76bb7dSCy Schubert char* ede_str = NULL; 640b7579f77SDag-Erling Smørgrav 641b7579f77SDag-Erling Smørgrav regional_free_all(region); 642b7579f77SDag-Erling Smørgrav 643b7579f77SDag-Erling Smørgrav if(strncmp(s, "msg ", 4) != 0) { 644b7579f77SDag-Erling Smørgrav log_warn("error expected msg but got %s", s); 645b7579f77SDag-Erling Smørgrav return 0; 646b7579f77SDag-Erling Smørgrav } 647b7579f77SDag-Erling Smørgrav s += 4; 64817d15b25SDag-Erling Smørgrav s = load_qinfo(s, &qinf, region); 649b7579f77SDag-Erling Smørgrav if(!s) { 650b7579f77SDag-Erling Smørgrav return 0; 651b7579f77SDag-Erling Smørgrav } 652b7579f77SDag-Erling Smørgrav 653b7579f77SDag-Erling Smørgrav /* read remainder of line */ 6548f76bb7dSCy Schubert /* note the last space before any possible EDE text */ 6558f76bb7dSCy Schubert if(sscanf(s, " %u %u " ARG_LL "d %u %u %u %u %d %n", &flags, &qdcount, &ttl, 6568f76bb7dSCy Schubert &security, &an, &ns, &ar, &ede, &consumed) != 8) { 657b7579f77SDag-Erling Smørgrav log_warn("error cannot parse numbers: %s", s); 658b7579f77SDag-Erling Smørgrav return 0; 659b7579f77SDag-Erling Smørgrav } 6608f76bb7dSCy Schubert /* there may be EDE text after the numbers */ 6618f76bb7dSCy Schubert if(consumed > 0 && (size_t)consumed < strlen(s)) 6628f76bb7dSCy Schubert ede_str = s + consumed; 6638f76bb7dSCy Schubert memset(&rep, 0, sizeof(rep)); 664b7579f77SDag-Erling Smørgrav rep.flags = (uint16_t)flags; 665b7579f77SDag-Erling Smørgrav rep.qdcount = (uint16_t)qdcount; 66617d15b25SDag-Erling Smørgrav rep.ttl = (time_t)ttl; 667b7579f77SDag-Erling Smørgrav rep.prefetch_ttl = PREFETCH_TTL_CALC(rep.ttl); 6684c75e3aaSDag-Erling Smørgrav rep.serve_expired_ttl = rep.ttl + SERVE_EXPIRED_TTL; 669b7579f77SDag-Erling Smørgrav rep.security = (enum sec_status)security; 67009a3aaf3SDag-Erling Smørgrav if(an > RR_COUNT_MAX || ns > RR_COUNT_MAX || ar > RR_COUNT_MAX) { 67109a3aaf3SDag-Erling Smørgrav log_warn("error too many rrsets"); 67209a3aaf3SDag-Erling Smørgrav return 0; /* protect against integer overflow in alloc */ 67309a3aaf3SDag-Erling Smørgrav } 674b7579f77SDag-Erling Smørgrav rep.an_numrrsets = (size_t)an; 675b7579f77SDag-Erling Smørgrav rep.ns_numrrsets = (size_t)ns; 676b7579f77SDag-Erling Smørgrav rep.ar_numrrsets = (size_t)ar; 677b7579f77SDag-Erling Smørgrav rep.rrset_count = (size_t)an+(size_t)ns+(size_t)ar; 6788f76bb7dSCy Schubert rep.reason_bogus = (sldns_ede_code)ede; 6798f76bb7dSCy Schubert rep.reason_bogus_str = ede_str?(char*)regional_strdup(region, ede_str):NULL; 680b7579f77SDag-Erling Smørgrav rep.rrsets = (struct ub_packed_rrset_key**)regional_alloc_zero( 681b7579f77SDag-Erling Smørgrav region, sizeof(struct ub_packed_rrset_key*)*rep.rrset_count); 682b7579f77SDag-Erling Smørgrav 683b7579f77SDag-Erling Smørgrav /* fill repinfo with references */ 684b7579f77SDag-Erling Smørgrav for(i=0; i<rep.rrset_count; i++) { 685b7579f77SDag-Erling Smørgrav if(!load_ref(ssl, buf, worker, region, &rep.rrsets[i], 686b7579f77SDag-Erling Smørgrav &go_on)) { 687b7579f77SDag-Erling Smørgrav return 0; 688b7579f77SDag-Erling Smørgrav } 689b7579f77SDag-Erling Smørgrav } 690b7579f77SDag-Erling Smørgrav 691b7579f77SDag-Erling Smørgrav if(!go_on) 692b7579f77SDag-Erling Smørgrav return 1; /* skip this one, not all references satisfied */ 693b7579f77SDag-Erling Smørgrav 694790c6b24SCy Schubert if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags, 695*be771a7bSCy Schubert *worker->env.now, 1)) { 696b7579f77SDag-Erling Smørgrav log_warn("error out of memory"); 697b7579f77SDag-Erling Smørgrav return 0; 698b7579f77SDag-Erling Smørgrav } 699b7579f77SDag-Erling Smørgrav return 1; 700b7579f77SDag-Erling Smørgrav } 701b7579f77SDag-Erling Smørgrav 702b7579f77SDag-Erling Smørgrav /** load msg cache */ 703b7579f77SDag-Erling Smørgrav static int 7047da0adf7SDag-Erling Smørgrav load_msg_cache(RES* ssl, struct worker* worker) 705b7579f77SDag-Erling Smørgrav { 70617d15b25SDag-Erling Smørgrav sldns_buffer* buf = worker->env.scratch_buffer; 707b7579f77SDag-Erling Smørgrav if(!read_fixed(ssl, buf, "START_MSG_CACHE")) return 0; 708b7579f77SDag-Erling Smørgrav while(ssl_read_buf(ssl, buf) && 70917d15b25SDag-Erling Smørgrav strcmp((char*)sldns_buffer_begin(buf), "END_MSG_CACHE")!=0) { 710b7579f77SDag-Erling Smørgrav if(!load_msg(ssl, buf, worker)) 711b7579f77SDag-Erling Smørgrav return 0; 712b7579f77SDag-Erling Smørgrav } 713b7579f77SDag-Erling Smørgrav return 1; 714b7579f77SDag-Erling Smørgrav } 715b7579f77SDag-Erling Smørgrav 716b7579f77SDag-Erling Smørgrav int 7177da0adf7SDag-Erling Smørgrav load_cache(RES* ssl, struct worker* worker) 718b7579f77SDag-Erling Smørgrav { 719b7579f77SDag-Erling Smørgrav if(!load_rrset_cache(ssl, worker)) 720b7579f77SDag-Erling Smørgrav return 0; 721b7579f77SDag-Erling Smørgrav if(!load_msg_cache(ssl, worker)) 722b7579f77SDag-Erling Smørgrav return 0; 723b7579f77SDag-Erling Smørgrav return read_fixed(ssl, worker->env.scratch_buffer, "EOF"); 724b7579f77SDag-Erling Smørgrav } 725b7579f77SDag-Erling Smørgrav 726b7579f77SDag-Erling Smørgrav /** print details on a delegation point */ 727b7579f77SDag-Erling Smørgrav static void 7287da0adf7SDag-Erling Smørgrav print_dp_details(RES* ssl, struct worker* worker, struct delegpt* dp) 729b7579f77SDag-Erling Smørgrav { 730b7579f77SDag-Erling Smørgrav char buf[257]; 731b7579f77SDag-Erling Smørgrav struct delegpt_addr* a; 73217d15b25SDag-Erling Smørgrav int lame, dlame, rlame, rto, edns_vs, to, delay, 733b7579f77SDag-Erling Smørgrav tA = 0, tAAAA = 0, tother = 0; 73417d15b25SDag-Erling Smørgrav long long entry_ttl; 735b7579f77SDag-Erling Smørgrav struct rtt_info ri; 736b7579f77SDag-Erling Smørgrav uint8_t edns_lame_known; 737b7579f77SDag-Erling Smørgrav for(a = dp->target_list; a; a = a->next_target) { 738b7579f77SDag-Erling Smørgrav addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf)); 739b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "%-16s\t", buf)) 740b7579f77SDag-Erling Smørgrav return; 741b7579f77SDag-Erling Smørgrav if(a->bogus) { 742b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "Address is BOGUS. ")) 743b7579f77SDag-Erling Smørgrav return; 744b7579f77SDag-Erling Smørgrav } 745b7579f77SDag-Erling Smørgrav /* lookup in infra cache */ 746b7579f77SDag-Erling Smørgrav delay=0; 747b7579f77SDag-Erling Smørgrav entry_ttl = infra_get_host_rto(worker->env.infra_cache, 748b7579f77SDag-Erling Smørgrav &a->addr, a->addrlen, dp->name, dp->namelen, 749b7579f77SDag-Erling Smørgrav &ri, &delay, *worker->env.now, &tA, &tAAAA, &tother); 750b7579f77SDag-Erling Smørgrav if(entry_ttl == -2 && ri.rto >= USEFUL_SERVER_TOP_TIMEOUT) { 751b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "expired, rto %d msec, tA %d " 752b7579f77SDag-Erling Smørgrav "tAAAA %d tother %d.\n", ri.rto, tA, tAAAA, 753b7579f77SDag-Erling Smørgrav tother)) 754b7579f77SDag-Erling Smørgrav return; 755b7579f77SDag-Erling Smørgrav continue; 756b7579f77SDag-Erling Smørgrav } 757b7579f77SDag-Erling Smørgrav if(entry_ttl == -1 || entry_ttl == -2) { 758b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "not in infra cache.\n")) 759b7579f77SDag-Erling Smørgrav return; 760b7579f77SDag-Erling Smørgrav continue; /* skip stuff not in infra cache */ 761b7579f77SDag-Erling Smørgrav } 762b7579f77SDag-Erling Smørgrav 763b7579f77SDag-Erling Smørgrav /* uses type_A because most often looked up, but other 764b7579f77SDag-Erling Smørgrav * lameness won't be reported then */ 765b7579f77SDag-Erling Smørgrav if(!infra_get_lame_rtt(worker->env.infra_cache, 766b7579f77SDag-Erling Smørgrav &a->addr, a->addrlen, dp->name, dp->namelen, 767b7579f77SDag-Erling Smørgrav LDNS_RR_TYPE_A, &lame, &dlame, &rlame, &rto, 768b7579f77SDag-Erling Smørgrav *worker->env.now)) { 769b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "not in infra cache.\n")) 770b7579f77SDag-Erling Smørgrav return; 771b7579f77SDag-Erling Smørgrav continue; /* skip stuff not in infra cache */ 772b7579f77SDag-Erling Smørgrav } 77317d15b25SDag-Erling Smørgrav if(!ssl_printf(ssl, "%s%s%s%srto %d msec, ttl " ARG_LL "d, " 77417d15b25SDag-Erling Smørgrav "ping %d var %d rtt %d, tA %d, tAAAA %d, tother %d", 775b7579f77SDag-Erling Smørgrav lame?"LAME ":"", dlame?"NoDNSSEC ":"", 776b7579f77SDag-Erling Smørgrav a->lame?"AddrWasParentSide ":"", 777b7579f77SDag-Erling Smørgrav rlame?"NoAuthButRecursive ":"", rto, entry_ttl, 778b7579f77SDag-Erling Smørgrav ri.srtt, ri.rttvar, rtt_notimeout(&ri), 779b7579f77SDag-Erling Smørgrav tA, tAAAA, tother)) 780b7579f77SDag-Erling Smørgrav return; 781b7579f77SDag-Erling Smørgrav if(delay) 782b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, ", probedelay %d", delay)) 783b7579f77SDag-Erling Smørgrav return; 784b7579f77SDag-Erling Smørgrav if(infra_host(worker->env.infra_cache, &a->addr, a->addrlen, 785b7579f77SDag-Erling Smørgrav dp->name, dp->namelen, *worker->env.now, &edns_vs, 786b7579f77SDag-Erling Smørgrav &edns_lame_known, &to)) { 787b7579f77SDag-Erling Smørgrav if(edns_vs == -1) { 788b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, ", noEDNS%s.", 789b7579f77SDag-Erling Smørgrav edns_lame_known?" probed":" assumed")) 790b7579f77SDag-Erling Smørgrav return; 791b7579f77SDag-Erling Smørgrav } else { 792b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, ", EDNS %d%s.", edns_vs, 793b7579f77SDag-Erling Smørgrav edns_lame_known?" probed":" assumed")) 794b7579f77SDag-Erling Smørgrav return; 795b7579f77SDag-Erling Smørgrav } 796b7579f77SDag-Erling Smørgrav } 797b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "\n")) 798b7579f77SDag-Erling Smørgrav return; 799b7579f77SDag-Erling Smørgrav } 800b7579f77SDag-Erling Smørgrav } 801b7579f77SDag-Erling Smørgrav 802b7579f77SDag-Erling Smørgrav /** print main dp info */ 803b7579f77SDag-Erling Smørgrav static void 8047da0adf7SDag-Erling Smørgrav print_dp_main(RES* ssl, struct delegpt* dp, struct dns_msg* msg) 805b7579f77SDag-Erling Smørgrav { 806b7579f77SDag-Erling Smørgrav size_t i, n_ns, n_miss, n_addr, n_res, n_avail; 807b7579f77SDag-Erling Smørgrav 808b7579f77SDag-Erling Smørgrav /* print the dp */ 809b7579f77SDag-Erling Smørgrav if(msg) 810b7579f77SDag-Erling Smørgrav for(i=0; i<msg->rep->rrset_count; i++) { 811b7579f77SDag-Erling Smørgrav struct ub_packed_rrset_key* k = msg->rep->rrsets[i]; 812b7579f77SDag-Erling Smørgrav struct packed_rrset_data* d = 813b7579f77SDag-Erling Smørgrav (struct packed_rrset_data*)k->entry.data; 814b7579f77SDag-Erling Smørgrav if(d->security == sec_status_bogus) { 815b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "Address is BOGUS:\n")) 816b7579f77SDag-Erling Smørgrav return; 817b7579f77SDag-Erling Smørgrav } 818b7579f77SDag-Erling Smørgrav if(!dump_rrset(ssl, k, d, 0)) 819b7579f77SDag-Erling Smørgrav return; 820b7579f77SDag-Erling Smørgrav } 821b7579f77SDag-Erling Smørgrav delegpt_count_ns(dp, &n_ns, &n_miss); 822b7579f77SDag-Erling Smørgrav delegpt_count_addr(dp, &n_addr, &n_res, &n_avail); 823b7579f77SDag-Erling Smørgrav /* since dp has not been used by iterator, all are available*/ 824b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "Delegation with %d names, of which %d " 825b7579f77SDag-Erling Smørgrav "can be examined to query further addresses.\n" 826b7579f77SDag-Erling Smørgrav "%sIt provides %d IP addresses.\n", 827b7579f77SDag-Erling Smørgrav (int)n_ns, (int)n_miss, (dp->bogus?"It is BOGUS. ":""), 828b7579f77SDag-Erling Smørgrav (int)n_addr)) 829b7579f77SDag-Erling Smørgrav return; 830b7579f77SDag-Erling Smørgrav } 831b7579f77SDag-Erling Smørgrav 8327da0adf7SDag-Erling Smørgrav int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm, 833b7579f77SDag-Erling Smørgrav size_t nmlen, int ATTR_UNUSED(nmlabs)) 834b7579f77SDag-Erling Smørgrav { 835b7579f77SDag-Erling Smørgrav /* deep links into the iterator module */ 836b7579f77SDag-Erling Smørgrav struct delegpt* dp; 837b7579f77SDag-Erling Smørgrav struct dns_msg* msg; 838b7579f77SDag-Erling Smørgrav struct regional* region = worker->scratchpad; 839*be771a7bSCy Schubert char b[LDNS_MAX_DOMAINLEN]; 840b7579f77SDag-Erling Smørgrav struct query_info qinfo; 841b7579f77SDag-Erling Smørgrav struct iter_hints_stub* stub; 842335c7cdaSCy Schubert int nolock = 0; 843b7579f77SDag-Erling Smørgrav regional_free_all(region); 844b7579f77SDag-Erling Smørgrav qinfo.qname = nm; 845b7579f77SDag-Erling Smørgrav qinfo.qname_len = nmlen; 846b7579f77SDag-Erling Smørgrav qinfo.qtype = LDNS_RR_TYPE_A; 847b7579f77SDag-Erling Smørgrav qinfo.qclass = LDNS_RR_CLASS_IN; 848bc892140SDag-Erling Smørgrav qinfo.local_alias = NULL; 849b7579f77SDag-Erling Smørgrav 850b7579f77SDag-Erling Smørgrav dname_str(nm, b); 851b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "The following name servers are used for lookup " 852b7579f77SDag-Erling Smørgrav "of %s\n", b)) 853b7579f77SDag-Erling Smørgrav return 0; 854b7579f77SDag-Erling Smørgrav 855335c7cdaSCy Schubert dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass, nolock); 856b7579f77SDag-Erling Smørgrav if(dp) { 857335c7cdaSCy Schubert if(!ssl_printf(ssl, "forwarding request:\n")) { 858335c7cdaSCy Schubert lock_rw_unlock(&worker->env.fwds->lock); 859b7579f77SDag-Erling Smørgrav return 0; 860335c7cdaSCy Schubert } 861b7579f77SDag-Erling Smørgrav print_dp_main(ssl, dp, NULL); 862b7579f77SDag-Erling Smørgrav print_dp_details(ssl, worker, dp); 863335c7cdaSCy Schubert lock_rw_unlock(&worker->env.fwds->lock); 864b7579f77SDag-Erling Smørgrav return 1; 865b7579f77SDag-Erling Smørgrav } 866b7579f77SDag-Erling Smørgrav 867b7579f77SDag-Erling Smørgrav while(1) { 868b7579f77SDag-Erling Smørgrav dp = dns_cache_find_delegation(&worker->env, nm, nmlen, 869b7579f77SDag-Erling Smørgrav qinfo.qtype, qinfo.qclass, region, &msg, 870790c6b24SCy Schubert *worker->env.now, 0, NULL, 0); 871b7579f77SDag-Erling Smørgrav if(!dp) { 872b7579f77SDag-Erling Smørgrav return ssl_printf(ssl, "no delegation from " 873b7579f77SDag-Erling Smørgrav "cache; goes to configured roots\n"); 874b7579f77SDag-Erling Smørgrav } 875b7579f77SDag-Erling Smørgrav /* go up? */ 876a39a5a69SCy Schubert if(iter_dp_is_useless(&qinfo, BIT_RD, dp, 877a39a5a69SCy Schubert (worker->env.cfg->do_ip4 && worker->back->num_ip4 != 0), 8788f76bb7dSCy Schubert (worker->env.cfg->do_ip6 && worker->back->num_ip6 != 0), 8798f76bb7dSCy Schubert worker->env.cfg->do_nat64)) { 880b7579f77SDag-Erling Smørgrav print_dp_main(ssl, dp, msg); 881b7579f77SDag-Erling Smørgrav print_dp_details(ssl, worker, dp); 882b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "cache delegation was " 883b7579f77SDag-Erling Smørgrav "useless (no IP addresses)\n")) 884b7579f77SDag-Erling Smørgrav return 0; 885b7579f77SDag-Erling Smørgrav if(dname_is_root(nm)) { 886b7579f77SDag-Erling Smørgrav /* goes to root config */ 887b7579f77SDag-Erling Smørgrav return ssl_printf(ssl, "no delegation from " 888b7579f77SDag-Erling Smørgrav "cache; goes to configured roots\n"); 889b7579f77SDag-Erling Smørgrav } else { 890b7579f77SDag-Erling Smørgrav /* useless, goes up */ 891b7579f77SDag-Erling Smørgrav nm = dp->name; 892b7579f77SDag-Erling Smørgrav nmlen = dp->namelen; 893b7579f77SDag-Erling Smørgrav dname_remove_label(&nm, &nmlen); 894b7579f77SDag-Erling Smørgrav dname_str(nm, b); 895b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "going up, lookup %s\n", b)) 896b7579f77SDag-Erling Smørgrav return 0; 897b7579f77SDag-Erling Smørgrav continue; 898b7579f77SDag-Erling Smørgrav } 899b7579f77SDag-Erling Smørgrav } 900b7579f77SDag-Erling Smørgrav stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass, 901335c7cdaSCy Schubert dp, nolock); 902b7579f77SDag-Erling Smørgrav if(stub) { 903b7579f77SDag-Erling Smørgrav if(stub->noprime) { 904b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "The noprime stub servers " 905335c7cdaSCy Schubert "are used:\n")) { 906335c7cdaSCy Schubert lock_rw_unlock(&worker->env.hints->lock); 907b7579f77SDag-Erling Smørgrav return 0; 908335c7cdaSCy Schubert } 909b7579f77SDag-Erling Smørgrav } else { 910b7579f77SDag-Erling Smørgrav if(!ssl_printf(ssl, "The stub is primed " 911335c7cdaSCy Schubert "with servers:\n")) { 912335c7cdaSCy Schubert lock_rw_unlock(&worker->env.hints->lock); 913b7579f77SDag-Erling Smørgrav return 0; 914b7579f77SDag-Erling Smørgrav } 915335c7cdaSCy Schubert } 916b7579f77SDag-Erling Smørgrav print_dp_main(ssl, stub->dp, NULL); 917b7579f77SDag-Erling Smørgrav print_dp_details(ssl, worker, stub->dp); 918335c7cdaSCy Schubert lock_rw_unlock(&worker->env.hints->lock); 919b7579f77SDag-Erling Smørgrav } else { 920b7579f77SDag-Erling Smørgrav print_dp_main(ssl, dp, msg); 921b7579f77SDag-Erling Smørgrav print_dp_details(ssl, worker, dp); 922b7579f77SDag-Erling Smørgrav } 923b7579f77SDag-Erling Smørgrav break; 924b7579f77SDag-Erling Smørgrav } 925b7579f77SDag-Erling Smørgrav 926b7579f77SDag-Erling Smørgrav return 1; 927b7579f77SDag-Erling Smørgrav } 928