Esempio n. 1
0
/** print one line with udb RR */
static void
print_udb_rr(uint8_t* name, udb_ptr* urr)
{
	buffer_type buffer;
	region_type* region = region_create(xalloc, free);
	region_type* tmpregion = region_create(xalloc, free);
	buffer_type* tmpbuffer = buffer_create(region, MAX_RDLENGTH);
	rr_type rr;
	ssize_t c;
	domain_table_type* owners;

	owners = domain_table_create(region);
	rr.owner = domain_table_insert(owners, dname_make(region, name, 0));

	/* to RR */
	rr.type = RR(urr)->type;
	rr.klass = RR(urr)->klass;
	rr.ttl = RR(urr)->ttl;
	buffer_create_from(&buffer, RR(urr)->wire, RR(urr)->len);
	c = rdata_wireformat_to_rdata_atoms(region, owners, RR(urr)->type,
		RR(urr)->len, &buffer, &rr.rdatas);
	if(c == -1) {
		printf("cannot parse wireformat\n");
		region_destroy(region);
		return;
	}
	rr.rdata_count = c;

	print_rr(stdout, NULL, &rr, tmpregion, tmpbuffer);

	region_destroy(region);
	region_destroy(tmpregion);
}
Esempio n. 2
0
rr_type *
packet_read_rr(region_type *region, domain_table_type *owners,
	       buffer_type *packet, int question_section)
{
	const dname_type *owner;
	uint16_t rdlength;
	ssize_t rdata_count;
	rdata_atom_type *rdatas;
	rr_type *result = (rr_type *) region_alloc(region, sizeof(rr_type));

	owner = dname_make_from_packet(region, packet, 1, 1);
	if (!owner || !buffer_available(packet, 2*sizeof(uint16_t))) {
		return NULL;
	}

	result->owner = domain_table_insert(owners, owner);
	result->type = buffer_read_u16(packet);
	result->klass = buffer_read_u16(packet);

	if (question_section) {
		result->ttl = 0;
		result->rdata_count = 0;
		result->rdatas = NULL;
		return result;
	} else if (!buffer_available(packet, sizeof(uint32_t) + sizeof(uint16_t))) {
		return NULL;
	}

	result->ttl = buffer_read_u32(packet);
	rdlength = buffer_read_u16(packet);

	if (!buffer_available(packet, rdlength)) {
		return NULL;
	}

	rdata_count = rdata_wireformat_to_rdata_atoms(
		region, owners, result->type, rdlength, packet, &rdatas);
	if (rdata_count == -1) {
		return NULL;
	}
	result->rdata_count = rdata_count;
	result->rdatas = rdatas;

	return result;
}
Esempio n. 3
0
void
parse_unknown_rdata(uint16_t type, uint16_t *wireformat)
{
	buffer_type packet;
	uint16_t size;
	ssize_t rdata_count;
	ssize_t i;
	rdata_atom_type *rdatas;

	if (wireformat) {
		size = *wireformat;
	} else {
		return;
	}

	buffer_create_from(&packet, wireformat + 1, *wireformat);
	rdata_count = rdata_wireformat_to_rdata_atoms(parser->region,
						      parser->db->domains,
						      type,
						      size,
						      &packet,
						      &rdatas);
	if (rdata_count == -1) {
		zc_error_prev_line("bad unknown RDATA");
		return;
	}

	for (i = 0; i < rdata_count; ++i) {
		if (rdata_atom_is_domain(type, i)) {
			zadd_rdata_domain(rdatas[i].domain);
		} else {
			zadd_rdata_wireformat(rdatas[i].data);
		}
	}
	region_recycle(parser->region, rdatas,
		rdata_count*sizeof(rdata_atom_type));
}
Esempio n. 4
0
static int
add_RR(namedb_type* db, const dname_type* dname,
	uint16_t type, uint16_t klass, uint32_t ttl,
	buffer_type* packet, size_t rdatalen, zone_type *zone,
	int is_axfr)
{
	domain_type* domain;
	rrset_type* rrset;
	rdata_atom_type *rdatas;
	rr_type *rrs_old;
	ssize_t rdata_num;
	int rrnum;
	domain = domain_table_find(db->domains, dname);
	if(!domain) {
		/* create the domain */
		domain = domain_table_insert(db->domains, dname);
	}
	rrset = domain_find_rrset(domain, zone, type);
	if(!rrset) {
		/* create the rrset */
		rrset = region_alloc(db->region, sizeof(rrset_type));
		if(!rrset) {
			log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__);
			exit(1);
		}
		rrset->zone = zone;
		rrset->rrs = 0;
		rrset->rr_count = 0;
		domain_add_rrset(domain, rrset);
	}

	/* dnames in rdata are normalized, conform RFC 4035,
	 * Section 6.2
	 */
	rdata_num = rdata_wireformat_to_rdata_atoms(
		db->region, db->domains, type, rdatalen, packet, &rdatas);
	if(rdata_num == -1) {
		log_msg(LOG_ERR, "diff: bad rdata for %s",
			dname_to_string(dname,0));
		return 0;
	}
	rrnum = find_rr_num(rrset, type, klass, rdatas, rdata_num);
	if(rrnum != -1) {
		DEBUG(DEBUG_XFRD, 2, (LOG_ERR, "diff: RR <%s, %s> already exists",
			dname_to_string(dname,0), rrtype_to_string(type)));
		/* ignore already existing RR: lenient accepting of messages */
		return 1;
	}

	/* re-alloc the rrs and add the new */
	rrs_old = rrset->rrs;
	rrset->rrs = region_alloc(db->region,
		(rrset->rr_count+1) * sizeof(rr_type));
	if(!rrset->rrs) {
		log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__);
		exit(1);
	}
	if(rrs_old)
		memcpy(rrset->rrs, rrs_old, rrset->rr_count * sizeof(rr_type));
	region_recycle(db->region, rrs_old, sizeof(rr_type) * rrset->rr_count);
	rrset->rr_count ++;

	rrset->rrs[rrset->rr_count - 1].owner = domain;
	rrset->rrs[rrset->rr_count - 1].rdatas = rdatas;
	rrset->rrs[rrset->rr_count - 1].ttl = ttl;
	rrset->rrs[rrset->rr_count - 1].type = type;
	rrset->rrs[rrset->rr_count - 1].klass = klass;
	rrset->rrs[rrset->rr_count - 1].rdata_count = rdata_num;

	/* see if it is a SOA */
	if(domain == zone->apex) {
		if(type == TYPE_SOA) {
			uint32_t soa_minimum;
			zone->soa_rrset = rrset;
			zone->updated = 1;
			/* BUG #103 tweaked SOA ttl value */
			if(zone->soa_nx_rrset == 0) {
				zone->soa_nx_rrset = region_alloc(db->region,
					sizeof(rrset_type));
				if(!zone->soa_nx_rrset) {
					log_msg(LOG_ERR, "out of memory, %s:%d",
						__FILE__, __LINE__);
					exit(1);
				}
				zone->soa_nx_rrset->rr_count = 1;
				zone->soa_nx_rrset->next = 0;
				zone->soa_nx_rrset->zone = zone;
				zone->soa_nx_rrset->rrs = region_alloc(db->region,
					sizeof(rr_type));
				if(!zone->soa_nx_rrset->rrs) {
					log_msg(LOG_ERR, "out of memory, %s:%d",
						__FILE__, __LINE__);
					exit(1);
				}
			}
			memcpy(zone->soa_nx_rrset->rrs, rrset->rrs, sizeof(rr_type));
			memcpy(&soa_minimum, rdata_atom_data(rrset->rrs->rdatas[6]),
				rdata_atom_size(rrset->rrs->rdatas[6]));
			if (rrset->rrs->ttl > ntohl(soa_minimum)) {
				rrset->zone->soa_nx_rrset->rrs[0].ttl = ntohl(soa_minimum);
			}
			domain->has_SOA = 1;
		}
		if(type == TYPE_NS) {
			zone->ns_rrset = rrset;
		}
		if(type == TYPE_RRSIG) {
			int i;
			for (i = 0; i < rrset->rr_count; ++i) {
				if (rr_rrsig_type_covered(&rrset->rrs[i]) == TYPE_DNSKEY) {
					zone->is_secure = 1;
					break;
				}
			}
		}
	}

#ifdef NSEC3
#ifndef FULL_PREHASH
	if ((type == TYPE_NSEC3) &&
	    (rrset->rr_count == 1)) {
		/* NSEC3 RRset just added */
		if (0 != namedb_add_nsec3_domain(db, domain, zone))
			return 0;
	}
	if (is_axfr == 0) {
		struct domain *parent = domain;
		do {
			if (0 != namedb_add_nsec3_mod_domain(db, parent))
				return 0;
			parent = parent->parent;
		} while (parent != zone->apex->parent);
	}
#else
	(void)is_axfr;
#endif /* !FULL_PREHASH */
#endif /* NSEC3 */

	return 1;
}
Esempio n. 5
0
static int
delete_RR(namedb_type* db, const dname_type* dname,
	uint16_t type, uint16_t klass,
	domain_type* prevdomain,
	buffer_type* packet, size_t rdatalen, zone_type *zone,
	region_type* temp_region, int is_axfr)
{
	domain_type *domain;
	rrset_type *rrset;
	domain = domain_table_find(db->domains, dname);
	if(!domain) {
		log_msg(LOG_WARNING, "diff: domain %s does not exist",
			dname_to_string(dname,0));
		buffer_skip(packet, rdatalen);
		return 1; /* not fatal error */
	}
	rrset = domain_find_rrset(domain, zone, type);
	if(!rrset) {
		log_msg(LOG_WARNING, "diff: rrset %s does not exist",
			dname_to_string(dname,0));
		buffer_skip(packet, rdatalen);
		return 1; /* not fatal error */
	} else {
		/* find the RR in the rrset */
		domain_table_type *temptable;
		rdata_atom_type *rdatas;
		ssize_t rdata_num;
		int rrnum;
		temptable = domain_table_create(temp_region);
		/* This will ensure that the dnames in rdata are
		 * normalized, conform RFC 4035, section 6.2
		 */
		rdata_num = rdata_wireformat_to_rdata_atoms(
			temp_region, temptable, type, rdatalen, packet, &rdatas);
		if(rdata_num == -1) {
			log_msg(LOG_ERR, "diff: bad rdata for %s",
				dname_to_string(dname,0));
			return 0;
		}
		rrnum = find_rr_num(rrset, type, klass, rdatas, rdata_num);
		if(rrnum == -1) {
			log_msg(LOG_WARNING, "diff: RR <%s, %s> does not exist",
				dname_to_string(dname,0), rrtype_to_string(type));
			return 1; /* not fatal error */
		}
#ifdef NSEC3
#ifndef FULL_PREHASH
		if (is_axfr == 0) {
			struct domain *parent = domain;
			do {
				if (0 != namedb_add_nsec3_mod_domain(db,
								    parent)) {
					return 0;
				}
				parent = parent->parent;
			} while (parent != zone->apex->parent);
		}
#else
		(void)is_axfr;
#endif /* !FULL_PREHASH */
#endif /* NSEC3 */

		if(rrset->rr_count == 1) {
			/* delete entire rrset */
			domain = rrset_delete(db, domain, rrset);
			if (domain && domain != prevdomain && !domain->nextdiff) {
				/* this domain is not yet in the diff chain */
				prevdomain->nextdiff = domain;
			}
		} else {
			/* swap out the bad RR and decrease the count */
			rr_type* rrs_orig = rrset->rrs;
			add_rdata_to_recyclebin(db, &rrset->rrs[rrnum]);
			if(rrnum < rrset->rr_count-1)
				rrset->rrs[rrnum] = rrset->rrs[rrset->rr_count-1];
			memset(&rrset->rrs[rrset->rr_count-1], 0, sizeof(rr_type));
			/* realloc the rrs array one smaller */
			rrset->rrs = region_alloc_init(db->region, rrs_orig,
				sizeof(rr_type) * (rrset->rr_count-1));
			if(!rrset->rrs) {
				log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__);
				exit(1);
			}
			region_recycle(db->region, rrs_orig,
				sizeof(rr_type) * rrset->rr_count);
			rrset->rr_count --;
		}
	}
	return 1;
}