Exemplo n.º 1
0
void
namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt)
{
	const char* zfile;
	int notexist = 0;
	zone_type* zone;
	/* if no zone exists, it has no contents or it has no zonefile
	 * configured, then no need to write data to disk */
	if(!zopt->pattern->zonefile)
		return;
	zone = namedb_find_zone(nsd->db, (const dname_type*)zopt->node.key);
	if(!zone || !zone->apex || !zone->soa_rrset)
		return;
	/* write if file does not exist, or if changed */
	/* so, determine filename, create directory components, check exist*/
	zfile = config_make_zonefile(zopt, nsd);
	if(!create_path_components(zfile, &notexist)) {
		log_msg(LOG_ERR, "could not write zone %s to file %s because "
			"the path could not be created", zopt->name, zfile);
		return;
	}

	/* if not changed, do not write. */
	if(notexist || zone->is_changed) {
		char logs[4096];
		char bakfile[4096];
		struct timespec mtime;
		udb_ptr zudb;
		if(nsd->db->udb) {
			if(!udb_zone_search(nsd->db->udb, &zudb,
				dname_name(domain_dname(zone->apex)),
				domain_dname(zone->apex)->name_size))
				return; /* zone does not exist in db */
		}
		/* write to zfile~ first, then rename if that works */
		snprintf(bakfile, sizeof(bakfile), "%s~", zfile);
		if(nsd->db->udb && ZONE(&zudb)->log_str.data) {
			udb_ptr s;
			udb_ptr_new(&s, nsd->db->udb, &ZONE(&zudb)->log_str);
			strlcpy(logs, (char*)udb_ptr_data(&s), sizeof(logs));
			udb_ptr_unlink(&s, nsd->db->udb);
		} else if(zone->logstr) {
			strlcpy(logs, zone->logstr, sizeof(logs));
		} else logs[0] = 0;
		VERBOSITY(1, (LOG_INFO, "writing zone %s to file %s",
			zone->opts->name, zfile));
		if(!write_to_zonefile(zone, bakfile, logs)) {
			if(nsd->db->udb)
				udb_ptr_unlink(&zudb, nsd->db->udb);
			(void)unlink(bakfile); /* delete failed file */
			return; /* error already printed */
		}
		if(rename(bakfile, zfile) == -1) {
			log_msg(LOG_ERR, "rename(%s to %s) failed: %s",
				bakfile, zfile, strerror(errno));
			if(nsd->db->udb)
				udb_ptr_unlink(&zudb, nsd->db->udb);
			(void)unlink(bakfile); /* delete failed file */
			return;
		}
		zone->is_changed = 0;
		/* fetch the mtime of the just created zonefile so we
		 * do not waste effort reading it back in */
		if(!file_get_mtime(zfile, &mtime, &notexist)) {
			get_time(&mtime);
		}
		if(nsd->db->udb) {
			ZONE(&zudb)->mtime = (uint64_t)mtime.tv_sec;
			ZONE(&zudb)->mtime_nsec = (uint64_t)mtime.tv_nsec;
			ZONE(&zudb)->is_changed = 0;
			udb_zone_set_log_str(nsd->db->udb, &zudb, NULL);
			udb_ptr_unlink(&zudb, nsd->db->udb);
		} else {
			zone->mtime = mtime;
			if(zone->filename)
				region_recycle(nsd->db->region, zone->filename,
					strlen(zone->filename)+1);
			zone->filename = region_strdup(nsd->db->region, zfile);
			if(zone->logstr)
				region_recycle(nsd->db->region, zone->logstr,
					strlen(zone->logstr)+1);
			zone->logstr = NULL;
		}
	}
}
Exemplo n.º 2
0
static zone_type*
find_zone(namedb_type* db, const dname_type* zone_name, nsd_options_t* opt,
	size_t child_count)
{
	domain_type *domain;
	zone_type* zone;
	zone_options_t* opts;
	domain = domain_table_find(db->domains, zone_name);
	if(!domain) {
		DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfr: creating domain %s",
			dname_to_string(zone_name,0)));
		/* create the zone and domain of apex (zone has config options) */
		domain = domain_table_insert(db->domains, zone_name);
	} else {
		/* O(1) if SOA exists */
		zone = domain_find_zone(domain);
		/* if domain was empty (no rrsets, empty zone) search in zonelist */
		/* check apex to make sure we don't find a parent zone */
		if(!zone || zone->apex != domain)
			zone = namedb_find_zone(db, domain);
		if(zone) {
			assert(zone->apex == domain);
			return zone;
		}
	}
	/* lookup in config */
	opts = zone_options_find(opt, domain_dname(domain));
	if(!opts) {
		log_msg(LOG_ERR, "xfr: zone %s not in config.",
			dname_to_string(zone_name,0));
		return 0;
	}
	/* create the zone */
	DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfr: creating zone_type %s",
		dname_to_string(zone_name,0)));
	zone = (zone_type *) region_alloc(db->region, sizeof(zone_type));
	if(!zone) {
		log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__);
		exit(1);
	}
	zone->next = db->zones;
	zone->opts = opts;
	db->zones = zone;
	db->zone_count++;
	zone->apex = domain;
	zone->soa_rrset = 0;
	zone->soa_nx_rrset = 0;
	zone->ns_rrset = 0;
#ifdef NSEC3
	zone->nsec3_soa_rr = NULL;
	zone->nsec3_last = NULL;
#endif
	zone->dirty = region_alloc(db->region, sizeof(uint8_t)*child_count);
	if(!zone->dirty) {
		log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__);
		exit(1);
	}
	memset(zone->dirty, 0, sizeof(uint8_t)*child_count);
#ifdef NSEC3
#ifndef FULL_PREHASH
	zone->nsec3_domains = NULL;

	if (0 != zone_nsec3_domains_create(db, zone)) {
		log_msg(LOG_ERR,
			"xfr: zone NSEC3 domains "
			"memory allocation failure");
		return 0;
	}
#endif /* !FULL_PREHASH */
#endif /* NSEC3 */
	zone->number = db->zone_count;
	zone->is_secure = 0;
	zone->updated = 1;
	zone->is_ok = 0;
	return zone;
}