1 /* 2 * dbaccess.c -- access methods for nsd(8) database 3 * 4 * Copyright (c) 2001-2011, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #include "config.h" 11 12 #include <sys/types.h> 13 #include <sys/stat.h> 14 15 #include <errno.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <unistd.h> 19 #include <fcntl.h> 20 #include <stdio.h> /* DEBUG */ 21 22 #include "dns.h" 23 #include "namedb.h" 24 #include "util.h" 25 #include "options.h" 26 27 int 28 namedb_lookup(struct namedb *db, 29 const dname_type *dname, 30 domain_type **closest_match, 31 domain_type **closest_encloser) 32 { 33 return domain_table_search( 34 db->domains, dname, closest_match, closest_encloser); 35 } 36 37 static int 38 read_magic(namedb_type *db) 39 { 40 char buf[NAMEDB_MAGIC_SIZE]; 41 42 if (fread(buf, sizeof(char), sizeof(buf), db->fd) != sizeof(buf)) 43 return 0; 44 45 return memcmp(buf, NAMEDB_MAGIC, NAMEDB_MAGIC_SIZE) == 0; 46 } 47 48 static const dname_type * 49 read_dname(FILE *fd, region_type *region) 50 { 51 uint8_t size; 52 uint8_t temp[MAXDOMAINLEN]; 53 54 if (fread(&size, sizeof(uint8_t), 1, fd) != 1) 55 return NULL; 56 if (fread(temp, sizeof(uint8_t), size, fd) != size) 57 return NULL; 58 59 return dname_make(region, temp, 1); 60 } 61 62 static int 63 read_size(namedb_type *db, uint32_t *result) 64 { 65 if (fread(result, sizeof(*result), 1, db->fd) == 1) { 66 *result = ntohl(*result); 67 return 1; 68 } else { 69 return 0; 70 } 71 } 72 73 static domain_type * 74 read_domain(namedb_type *db, uint32_t domain_count, domain_type **domains) 75 { 76 uint32_t domain_number; 77 78 if (!read_size(db, &domain_number)) 79 return NULL; 80 81 if (domain_number == 0 || domain_number > domain_count) 82 return NULL; 83 84 return domains[domain_number - 1]; 85 } 86 87 static zone_type * 88 read_zone(namedb_type *db, uint32_t zone_count, zone_type **zones) 89 { 90 uint32_t zone_number; 91 92 if (!read_size(db, &zone_number)) 93 return NULL; 94 95 if (zone_number == 0 || zone_number > zone_count) 96 return NULL; 97 98 return zones[zone_number - 1]; 99 } 100 101 static int 102 read_rdata_atom(namedb_type *db, uint16_t type, int index, uint32_t domain_count, domain_type **domains, rdata_atom_type *result) 103 { 104 uint8_t data[65536]; 105 106 if (rdata_atom_is_domain(type, index)) { 107 result->domain = read_domain(db, domain_count, domains); 108 if (!result->domain) 109 return 0; 110 } else { 111 uint16_t size; 112 113 if (fread(&size, sizeof(size), 1, db->fd) != 1) 114 return 0; 115 size = ntohs(size); 116 if (fread(data, sizeof(uint8_t), size, db->fd) != size) 117 return 0; 118 119 result->data = (uint16_t *) region_alloc( 120 db->region, sizeof(uint16_t) + size); 121 memcpy(result->data, &size, sizeof(uint16_t)); 122 memcpy((uint8_t *) result->data + sizeof(uint16_t), data, size); 123 } 124 125 return 1; 126 } 127 128 static rrset_type * 129 read_rrset(namedb_type *db, 130 uint32_t domain_count, domain_type **domains, 131 uint32_t zone_count, zone_type **zones) 132 { 133 rrset_type *rrset; 134 int i, j; 135 domain_type *owner; 136 uint16_t type; 137 uint16_t klass; 138 uint32_t soa_minimum; 139 140 owner = read_domain(db, domain_count, domains); 141 if (!owner) 142 return NULL; 143 144 rrset = (rrset_type *) region_alloc(db->region, sizeof(rrset_type)); 145 146 rrset->zone = read_zone(db, zone_count, zones); 147 if (!rrset->zone) 148 return NULL; 149 150 if (fread(&type, sizeof(type), 1, db->fd) != 1) 151 return NULL; 152 type = ntohs(type); 153 154 if (fread(&klass, sizeof(klass), 1, db->fd) != 1) 155 return NULL; 156 klass = ntohs(klass); 157 158 if (fread(&rrset->rr_count, sizeof(rrset->rr_count), 1, db->fd) != 1) 159 return NULL; 160 rrset->rr_count = ntohs(rrset->rr_count); 161 rrset->rrs = (rr_type *) region_alloc( 162 db->region, rrset->rr_count * sizeof(rr_type)); 163 164 assert(rrset->rr_count > 0); 165 166 for (i = 0; i < rrset->rr_count; ++i) { 167 rr_type *rr = &rrset->rrs[i]; 168 169 rr->owner = owner; 170 rr->type = type; 171 rr->klass = klass; 172 173 if (fread(&rr->rdata_count, sizeof(rr->rdata_count), 1, db->fd) != 1) 174 return NULL; 175 rr->rdata_count = ntohs(rr->rdata_count); 176 rr->rdatas = (rdata_atom_type *) region_alloc( 177 db->region, rr->rdata_count * sizeof(rdata_atom_type)); 178 179 if (fread(&rr->ttl, sizeof(rr->ttl), 1, db->fd) != 1) 180 return NULL; 181 rr->ttl = ntohl(rr->ttl); 182 183 for (j = 0; j < rr->rdata_count; ++j) { 184 if (!read_rdata_atom(db, rr->type, j, domain_count, domains, &rr->rdatas[j])) 185 return NULL; 186 } 187 } 188 189 domain_add_rrset(owner, rrset); 190 191 if (rrset_rrtype(rrset) == TYPE_SOA) { 192 assert(owner == rrset->zone->apex); 193 rrset->zone->soa_rrset = rrset; 194 195 /* BUG #103 add another soa with a tweaked ttl */ 196 rrset->zone->soa_nx_rrset = region_alloc(db->region, sizeof(rrset_type)); 197 rrset->zone->soa_nx_rrset->rrs = 198 region_alloc(db->region, rrset->rr_count * sizeof(rr_type)); 199 200 memcpy(rrset->zone->soa_nx_rrset->rrs, rrset->rrs, sizeof(rr_type)); 201 rrset->zone->soa_nx_rrset->rr_count = 1; 202 rrset->zone->soa_nx_rrset->next = 0; 203 204 /* also add a link to the zone */ 205 rrset->zone->soa_nx_rrset->zone = rrset->zone; 206 207 /* check the ttl and MINIMUM value and set accordinly */ 208 memcpy(&soa_minimum, rdata_atom_data(rrset->rrs->rdatas[6]), 209 rdata_atom_size(rrset->rrs->rdatas[6])); 210 if (rrset->rrs->ttl > ntohl(soa_minimum)) { 211 rrset->zone->soa_nx_rrset->rrs[0].ttl = ntohl(soa_minimum); 212 } 213 owner->has_SOA = 1; 214 215 } else if (owner == rrset->zone->apex 216 && rrset_rrtype(rrset) == TYPE_NS) 217 { 218 rrset->zone->ns_rrset = rrset; 219 } 220 #ifdef NSEC3 221 #ifndef FULL_PREHASH 222 else if (type == TYPE_NSEC3) { 223 if (0 != namedb_add_nsec3_domain(db, owner, rrset->zone)) { 224 return NULL; 225 } 226 } 227 #endif /* !FULL_PREHASH */ 228 #endif /* NSEC3 */ 229 if (rrset_rrtype(rrset) == TYPE_RRSIG && owner == rrset->zone->apex) { 230 for (i = 0; i < rrset->rr_count; ++i) { 231 if (rr_rrsig_type_covered(&rrset->rrs[i]) == TYPE_DNSKEY) { 232 rrset->zone->is_secure = 1; 233 break; 234 } 235 } 236 } 237 return rrset; 238 } 239 240 struct namedb * 241 namedb_open (const char *filename, nsd_options_t* opt, size_t num_children) 242 { 243 namedb_type *db; 244 245 /* 246 * Temporary region used while loading domain names from the 247 * database. The region is freed after each time a dname is 248 * read from the database. 249 */ 250 region_type *dname_region; 251 252 /* 253 * Temporary region used to store array of domains and zones 254 * while loading the database. The region is freed before 255 * returning. 256 */ 257 region_type *temp_region; 258 259 uint32_t dname_count; 260 domain_type **domains; /* Indexed by domain number. */ 261 262 uint32_t zone_count; 263 zone_type **zones; /* Indexed by zone number. */ 264 265 uint32_t i; 266 uint32_t rrset_count = 0; 267 uint32_t rr_count = 0; 268 269 rrset_type *rrset; 270 271 DEBUG(DEBUG_DBACCESS, 2, 272 (LOG_INFO, "sizeof(namedb_type) = %lu\n", (unsigned long) sizeof(namedb_type))); 273 DEBUG(DEBUG_DBACCESS, 2, 274 (LOG_INFO, "sizeof(zone_type) = %lu\n", (unsigned long) sizeof(zone_type))); 275 DEBUG(DEBUG_DBACCESS, 2, 276 (LOG_INFO, "sizeof(domain_type) = %lu\n", (unsigned long) sizeof(domain_type))); 277 DEBUG(DEBUG_DBACCESS, 2, 278 (LOG_INFO, "sizeof(rrset_type) = %lu\n", (unsigned long) sizeof(rrset_type))); 279 DEBUG(DEBUG_DBACCESS, 2, 280 (LOG_INFO, "sizeof(rr_type) = %lu\n", (unsigned long) sizeof(rr_type))); 281 DEBUG(DEBUG_DBACCESS, 2, 282 (LOG_INFO, "sizeof(rdata_atom_type) = %lu\n", (unsigned long) sizeof(rdata_atom_type))); 283 DEBUG(DEBUG_DBACCESS, 2, 284 (LOG_INFO, "sizeof(rbnode_t) = %lu\n", (unsigned long) sizeof(rbnode_t))); 285 286 if ((db = namedb_create()) == NULL) { 287 log_msg(LOG_ERR, 288 "insufficient memory to create database"); 289 return NULL; 290 } 291 db->filename = region_strdup(db->region, filename); 292 293 if (gettimeofday(&(db->diff_timestamp), NULL) != 0) { 294 log_msg(LOG_ERR, "unable to load %s: cannot initialize" 295 "timestamp", db->filename); 296 namedb_destroy(db); 297 return NULL; 298 } 299 300 /* Open it... */ 301 db->fd = fopen(db->filename, "r"); 302 if (db->fd == NULL) { 303 log_msg(LOG_ERR, "unable to load %s: %s", 304 db->filename, strerror(errno)); 305 namedb_destroy(db); 306 return NULL; 307 } 308 309 if (!read_magic(db)) { 310 log_msg(LOG_ERR, "corrupted database (read magic): %s", db->filename); 311 log_msg(LOG_ERR, "cannot load database, incompatible version " 312 "number. Please rebuild database and " 313 "start again."); 314 namedb_close(db); 315 return NULL; 316 } 317 318 if (!read_size(db, &zone_count)) { 319 log_msg(LOG_ERR, "corrupted database (read size): %s", db->filename); 320 namedb_close(db); 321 return NULL; 322 } 323 324 DEBUG(DEBUG_DBACCESS, 1, 325 (LOG_INFO, "Retrieving %lu zones\n", (unsigned long) zone_count)); 326 327 temp_region = region_create(xalloc, free); 328 dname_region = region_create(xalloc, free); 329 330 db->zone_count = zone_count; 331 zones = (zone_type **) region_alloc(temp_region, 332 zone_count * sizeof(zone_type *)); 333 for (i = 0; i < zone_count; ++i) { 334 const dname_type *dname = read_dname(db->fd, dname_region); 335 if (!dname) { 336 log_msg(LOG_ERR, "corrupted database (read dname): %s", db->filename); 337 region_destroy(dname_region); 338 region_destroy(temp_region); 339 namedb_close(db); 340 return NULL; 341 } 342 zones[i] = (zone_type *) region_alloc(db->region, 343 sizeof(zone_type)); 344 zones[i]->next = db->zones; 345 db->zones = zones[i]; 346 zones[i]->apex = domain_table_insert(db->domains, dname); 347 zones[i]->soa_rrset = NULL; 348 zones[i]->soa_nx_rrset = NULL; 349 zones[i]->ns_rrset = NULL; 350 #ifdef NSEC3 351 zones[i]->nsec3_soa_rr = NULL; 352 zones[i]->nsec3_last = NULL; 353 #endif 354 zones[i]->opts = zone_options_find(opt, domain_dname(zones[i]->apex)); 355 zones[i]->number = i + 1; 356 zones[i]->is_secure = 0; 357 zones[i]->updated = 1; 358 zones[i]->is_ok = 0; 359 zones[i]->dirty = region_alloc(db->region, sizeof(uint8_t)*num_children); 360 memset(zones[i]->dirty, 0, sizeof(uint8_t)*num_children); 361 if(!zones[i]->opts) { 362 log_msg(LOG_ERR, "cannot load database. Zone %s in db " 363 "%s, but not in config file (might " 364 "happen if you edited the config " 365 "file). Please rebuild database and " 366 "start again.", 367 dname_to_string(dname, NULL), db->filename); 368 region_destroy(dname_region); 369 region_destroy(temp_region); 370 namedb_close(db); 371 return NULL; 372 } 373 #ifdef NSEC3 374 #ifndef FULL_PREHASH 375 zones[i]->nsec3_domains = NULL; 376 if (0 != zone_nsec3_domains_create(db, zones[i])) { 377 log_msg(LOG_ERR, 378 "insufficient memory for NSEC3 tree, " 379 "unable to read database"); 380 region_destroy(dname_region); 381 region_destroy(temp_region); 382 namedb_close(db); 383 return NULL; 384 } 385 #endif /* !FULL_PREHASH */ 386 #endif /* NSEC3 */ 387 region_free_all(dname_region); 388 } 389 390 if (!read_size(db, &dname_count)) { 391 log_msg(LOG_ERR, "corrupted database (read size): %s", db->filename); 392 region_destroy(dname_region); 393 region_destroy(temp_region); 394 namedb_close(db); 395 return NULL; 396 } 397 398 DEBUG(DEBUG_DBACCESS, 1, 399 (LOG_INFO, "Retrieving %lu domain names\n", (unsigned long) dname_count)); 400 401 domains = (domain_type **) region_alloc( 402 temp_region, dname_count * sizeof(domain_type *)); 403 for (i = 0; i < dname_count; ++i) { 404 const dname_type *dname = read_dname(db->fd, dname_region); 405 if (!dname) { 406 log_msg(LOG_ERR, "corrupted database (read dname): %s", db->filename); 407 region_destroy(dname_region); 408 region_destroy(temp_region); 409 namedb_close(db); 410 return NULL; 411 } 412 domains[i] = domain_table_insert(db->domains, dname); 413 region_free_all(dname_region); 414 } 415 416 region_destroy(dname_region); 417 418 #ifndef NDEBUG 419 fprintf(stderr, "database region after loading domain names: "); 420 region_dump_stats(db->region, stderr); 421 fprintf(stderr, "\n"); 422 #endif 423 424 while ((rrset = read_rrset(db, dname_count, domains, zone_count, zones))) { 425 ++rrset_count; 426 rr_count += rrset->rr_count; 427 } 428 429 DEBUG(DEBUG_DBACCESS, 1, 430 (LOG_INFO, "Retrieved %lu RRs in %lu RRsets\n", 431 (unsigned long) rr_count, (unsigned long) rrset_count)); 432 433 region_destroy(temp_region); 434 435 if ((db->crc_pos = ftello(db->fd)) == -1) { 436 log_msg(LOG_ERR, "ftello %s failed: %s", 437 db->filename, strerror(errno)); 438 namedb_close(db); 439 return NULL; 440 } 441 if (!read_size(db, &db->crc)) { 442 log_msg(LOG_ERR, "corrupted database (read size): %s", db->filename); 443 namedb_close(db); 444 return NULL; 445 } 446 if (!read_magic(db)) { 447 log_msg(LOG_ERR, "corrupted database (read magic): %s", db->filename); 448 log_msg(LOG_ERR, "cannot load database, incompatible version " 449 "number. Please rebuild database and " 450 "start again."); 451 namedb_close(db); 452 return NULL; 453 } 454 455 fclose(db->fd); 456 db->fd = NULL; 457 458 #ifndef NDEBUG 459 fprintf(stderr, "database region after loading database: "); 460 region_dump_stats(db->region, stderr); 461 fprintf(stderr, "\n"); 462 #endif 463 464 return db; 465 } 466 467 void 468 namedb_close (struct namedb *db) 469 { 470 namedb_fd_close(db); 471 if (db) { 472 namedb_destroy(db); 473 } 474 } 475 476 void 477 namedb_fd_close (struct namedb *db) 478 { 479 if (db && db->fd) { 480 fclose(db->fd); 481 } 482 } 483 484