Esempio n. 1
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. 2
0
static rrset_type *
read_rrset(namedb_type *db,
           uint32_t domain_count, domain_type **domains,
           uint32_t zone_count, zone_type **zones)
{
    rrset_type *rrset;
    int i, j;
    domain_type *owner;
    uint16_t type;
    uint16_t klass;
    uint32_t soa_minimum;

    owner = read_domain(db, domain_count, domains);
    if (!owner)
        return NULL;

    rrset = (rrset_type *) region_alloc(db->region, sizeof(rrset_type));

    rrset->zone = read_zone(db, zone_count, zones);
    if (!rrset->zone)
        return NULL;

    if (fread(&type, sizeof(type), 1, db->fd) != 1)
        return NULL;
    type = ntohs(type);

    if (fread(&klass, sizeof(klass), 1, db->fd) != 1)
        return NULL;
    klass = ntohs(klass);

    if (fread(&rrset->rr_count, sizeof(rrset->rr_count), 1, db->fd) != 1)
        return NULL;
    rrset->rr_count = ntohs(rrset->rr_count);
    rrset->rrs = (rr_type *) region_alloc(
                     db->region, rrset->rr_count * sizeof(rr_type));

    assert(rrset->rr_count > 0);

    for (i = 0; i < rrset->rr_count; ++i) {
        rr_type *rr = &rrset->rrs[i];

        rr->owner = owner;
        rr->type = type;
        rr->klass = klass;

        if (fread(&rr->rdata_count, sizeof(rr->rdata_count), 1, db->fd) != 1)
            return NULL;
        rr->rdata_count = ntohs(rr->rdata_count);
        rr->rdatas = (rdata_atom_type *) region_alloc(
                         db->region, rr->rdata_count * sizeof(rdata_atom_type));

        if (fread(&rr->ttl, sizeof(rr->ttl), 1, db->fd) != 1)
            return NULL;
        rr->ttl = ntohl(rr->ttl);

        for (j = 0; j < rr->rdata_count; ++j) {
            if (!read_rdata_atom(db, rr->type, j, domain_count, domains, &rr->rdatas[j]))
                return NULL;
        }
    }

    domain_add_rrset(owner, rrset);

    if (rrset_rrtype(rrset) == TYPE_SOA) {
        assert(owner == rrset->zone->apex);
        rrset->zone->soa_rrset = rrset;

        /* BUG #103 add another soa with a tweaked ttl */
        rrset->zone->soa_nx_rrset = region_alloc(db->region, sizeof(rrset_type));
        rrset->zone->soa_nx_rrset->rrs =
            region_alloc(db->region, rrset->rr_count * sizeof(rr_type));

        memcpy(rrset->zone->soa_nx_rrset->rrs, rrset->rrs, sizeof(rr_type));
        rrset->zone->soa_nx_rrset->rr_count = 1;
        rrset->zone->soa_nx_rrset->next = 0;

        /* also add a link to the zone */
        rrset->zone->soa_nx_rrset->zone = rrset->zone;

        /* check the ttl and MINIMUM value and set accordinly */
        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);
        }
        owner->has_SOA = 1;

    } else if (owner == rrset->zone->apex
               && rrset_rrtype(rrset) == TYPE_NS)
    {
        rrset->zone->ns_rrset = rrset;
    }
#ifdef NSEC3
#ifndef FULL_PREHASH
    else if (type == TYPE_NSEC3) {
        if (0 != namedb_add_nsec3_domain(db, owner, rrset->zone)) {
            return NULL;
        }
    }
#endif /* !FULL_PREHASH */
#endif /* NSEC3 */
    if (rrset_rrtype(rrset) == TYPE_RRSIG && owner == rrset->zone->apex) {
        for (i = 0; i < rrset->rr_count; ++i) {
            if (rr_rrsig_type_covered(&rrset->rrs[i]) == TYPE_DNSKEY) {
                rrset->zone->is_secure = 1;
                break;
            }
        }
    }
    return rrset;
}
Esempio n. 3
0
int
process_rr(void)
{
	zone_type *zone = parser->current_zone;
	rr_type *rr = &parser->current_rr;
	rrset_type *rrset;
	size_t max_rdlength;
	int i;
	rrtype_descriptor_type *descriptor
		= rrtype_descriptor_by_type(rr->type);

	/* We only support IN class */
	if (rr->klass != CLASS_IN) {
		if(zone_is_slave(zone->opts))
			zc_warning_prev_line("only class IN is supported");
		else
			zc_error_prev_line("only class IN is supported");
		return 0;
	}

	/* Make sure the maximum RDLENGTH does not exceed 65535 bytes.	*/
	max_rdlength = rdata_maximum_wireformat_size(
		descriptor, rr->rdata_count, rr->rdatas);

	if (max_rdlength > MAX_RDLENGTH) {
		zc_error_prev_line("maximum rdata length exceeds %d octets", MAX_RDLENGTH);
		return 0;
	}
	/* we have the zone already */
	assert(zone);
	if (rr->type == TYPE_SOA) {
		if (rr->owner != zone->apex) {
			zc_error_prev_line(
				"SOA record with invalid domain name");
			return 0;
		}
		if(has_soa(rr->owner)) {
			if(zone_is_slave(zone->opts))
				zc_warning_prev_line("this SOA record was already encountered");
			else
				zc_error_prev_line("this SOA record was already encountered");
			return 0;
		}
		rr->owner->is_apex = 1;
	}

	if (!domain_is_subdomain(rr->owner, zone->apex))
	{
		if(zone_is_slave(zone->opts))
			zc_warning_prev_line("out of zone data");
		else
			zc_error_prev_line("out of zone data");
		return 0;
	}

	/* Do we have this type of rrset already? */
	rrset = domain_find_rrset(rr->owner, zone, rr->type);
	if (!rrset) {
		rrset = (rrset_type *) region_alloc(parser->region,
						    sizeof(rrset_type));
		rrset->zone = zone;
		rrset->rr_count = 1;
		rrset->rrs = (rr_type *) region_alloc(parser->region,
						      sizeof(rr_type));
		rrset->rrs[0] = *rr;

		/* Add it */
		domain_add_rrset(rr->owner, rrset);
	} else {
		rr_type* o;
		if (rr->type != TYPE_RRSIG && rrset->rrs[0].ttl != rr->ttl) {
			zc_warning_prev_line(
				"%s TTL %u does not match the TTL %u of the %s RRset",
				domain_to_string(rr->owner), (unsigned)rr->ttl,
				(unsigned)rrset->rrs[0].ttl,
				rrtype_to_string(rr->type));
		}

		/* Search for possible duplicates... */
		for (i = 0; i < rrset->rr_count; i++) {
			if (!zrdatacmp(rr->type, rr, &rrset->rrs[i])) {
				break;
			}
		}

		/* Discard the duplicates... */
		if (i < rrset->rr_count) {
			return 0;
		}
		if(rrset->rr_count == 65535) {
			zc_error_prev_line("too many RRs for domain RRset");
			return 0;
		}

		/* Add it... */
		o = rrset->rrs;
		rrset->rrs = (rr_type *) region_alloc_array(parser->region,
			(rrset->rr_count + 1), sizeof(rr_type));
		memcpy(rrset->rrs, o, (rrset->rr_count) * sizeof(rr_type));
		region_recycle(parser->region, o,
			(rrset->rr_count) * sizeof(rr_type));
		rrset->rrs[rrset->rr_count] = *rr;
		++rrset->rr_count;
	}

	if(rr->type == TYPE_DNAME && rrset->rr_count > 1) {
		if(zone_is_slave(zone->opts))
			zc_warning_prev_line("multiple DNAMEs at the same name");
		else
			zc_error_prev_line("multiple DNAMEs at the same name");
	}
	if(rr->type == TYPE_CNAME && rrset->rr_count > 1) {
		if(zone_is_slave(zone->opts))
			zc_warning_prev_line("multiple CNAMEs at the same name");
		else
			zc_error_prev_line("multiple CNAMEs at the same name");
	}
	if((rr->type == TYPE_DNAME && domain_find_rrset(rr->owner, zone, TYPE_CNAME))
	 ||(rr->type == TYPE_CNAME && domain_find_rrset(rr->owner, zone, TYPE_DNAME))) {
		if(zone_is_slave(zone->opts))
			zc_warning_prev_line("DNAME and CNAME at the same name");
		else
			zc_error_prev_line("DNAME and CNAME at the same name");
	}
	if(domain_find_rrset(rr->owner, zone, TYPE_CNAME) &&
		domain_find_non_cname_rrset(rr->owner, zone)) {
		if(zone_is_slave(zone->opts))
			zc_warning_prev_line("CNAME and other data at the same name");
		else
			zc_error_prev_line("CNAME and other data at the same name");
	}

	/* Check we have SOA */
	if(rr->owner == zone->apex)
		apex_rrset_checks(parser->db, rrset, rr->owner);

	if(parser->line % ZONEC_PCT_COUNT == 0 && time(NULL) > startzonec + ZONEC_PCT_TIME) {
		struct stat buf;
		startzonec = time(NULL);
		buf.st_size = 0;
		fstat(fileno(yyin), &buf);
		if(buf.st_size == 0) buf.st_size = 1;
		VERBOSITY(1, (LOG_INFO, "parse %s %d %%",
			parser->current_zone->opts->name,
			(int)((uint64_t)ftell(yyin)*(uint64_t)100/(uint64_t)buf.st_size)));
	}
	++totalrrs;
	return 1;
}
Esempio n. 4
0
/**
 * Add RR.
 *
 */
ods_status
zone_add_rr(zone_type* zone, ldns_rr* rr, int do_stats)
{
    domain_type* domain = NULL;
    rrset_type* rrset = NULL;
    rr_type* record = NULL;
    ods_status status = ODS_STATUS_OK;

    ods_log_assert(rr);
    ods_log_assert(zone);
    ods_log_assert(zone->name);
    ods_log_assert(zone->db);
    ods_log_assert(zone->signconf);
    /* If we already have this RR, return ODS_STATUS_UNCHANGED */
    domain = namedb_lookup_domain(zone->db, ldns_rr_owner(rr));
    if (!domain) {
        domain = namedb_add_domain(zone->db, ldns_rr_owner(rr));
        if (!domain) {
            ods_log_error("[%s] unable to add RR to zone %s: "
                "failed to add domain", zone_str, zone->name);
            return ODS_STATUS_ERR;
        }
        if (ldns_dname_compare(domain->dname, zone->apex) == 0) {
            domain->is_apex = 1;
        } else {
            status = namedb_domain_entize(zone->db, domain, zone->apex);
            if (status != ODS_STATUS_OK) {
                ods_log_error("[%s] unable to add RR to zone %s: "
                    "failed to entize domain", zone_str, zone->name);
                return ODS_STATUS_ERR;
            }
        }
    }
    rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr));
    if (!rrset) {
        rrset = rrset_create(domain->zone, ldns_rr_get_type(rr));
        if (!rrset) {
            ods_log_error("[%s] unable to add RR to zone %s: "
                "failed to add RRset", zone_str, zone->name);
            return ODS_STATUS_ERR;
        }
        domain_add_rrset(domain, rrset);
    }
    record = rrset_lookup_rr(rrset, rr);
    if (record) {
        record->is_added = 1; /* already exists, just mark added */
        record->is_removed = 0; /* unset is_removed */
        if (ldns_rr_ttl(rr) != ldns_rr_ttl(record->rr)) {
            ldns_rr_set_ttl(record->rr, ldns_rr_ttl(rr));
            rrset->needs_signing = 1;
        }
        return ODS_STATUS_UNCHANGED;
    } else {
        record = rrset_add_rr(rrset, rr);
        ods_log_assert(record);
        ods_log_assert(record->rr);
        ods_log_assert(record->is_added);
    }
    /* update stats */
    if (do_stats && zone->stats) {
        zone->stats->sort_count += 1;
    }
    return ODS_STATUS_OK;
}