예제 #1
0
/**
 * QUERY.
 *
 */
static query_state
query_process_query(query_type* q, ldns_rr_type qtype, engine_type* engine)
{
    dnsout_type* dnsout = NULL;
    if (!q || !q->zone) {
        return QUERY_DISCARDED;
    }
    ods_log_assert(q->zone->name);
    ods_log_debug("[%s] incoming query qtype=%s for zone %s", query_str,
        rrset_type2str(qtype), q->zone->name);
    /* sanity checks */
    if (buffer_pkt_qdcount(q->buffer) != 1 || buffer_pkt_tc(q->buffer)) {
        buffer_pkt_set_flags(q->buffer, 0);
        return query_formerr(q);
    }
    if (buffer_pkt_ancount(q->buffer) != 0 ||
        (qtype != LDNS_RR_TYPE_IXFR && buffer_pkt_nscount(q->buffer) != 0)) {
        buffer_pkt_set_flags(q->buffer, 0);
        return query_formerr(q);
    }
    /* acl */
    if (!q->zone->adoutbound || q->zone->adoutbound->type != ADAPTER_DNS) {
        ods_log_error("[%s] zone %s is not configured to have output dns "
            "adapter", query_str, q->zone->name);
        return query_refused(q);
    }
    ods_log_assert(q->zone->adoutbound->config);
    dnsout = (dnsout_type*) q->zone->adoutbound->config;
    /* acl also in use for soa and other queries */
    if (!acl_find(dnsout->provide_xfr, &q->addr, q->tsig_rr)) {
        return query_refused(q);
    }
    /* ixfr? */
    if (qtype == LDNS_RR_TYPE_IXFR) {
        if (query_process_ixfr(q) != QUERY_PROCESSED) {
            buffer_pkt_set_flags(q->buffer, 0);
            return query_formerr(q);
        }
        query_prepare(q);
        ods_log_assert(q->zone->name);
        ods_log_debug("[%s] incoming ixfr request serial=%u for zone %s",
            query_str, q->serial, q->zone->name);
        return ixfr(q, engine);
    }

    query_prepare(q);
    /* axfr? */
    if (qtype == LDNS_RR_TYPE_AXFR) {
        ods_log_assert(q->zone->name);
        ods_log_debug("[%s] incoming axfr request for zone %s",
            query_str, q->zone->name);
        return axfr(q, engine);
    }
    /* (soa) query */
    return query_response(q, qtype);
}
예제 #2
0
/**
 * Process RR.
 *
 */
static ods_status
adapi_process_rr(zone_type* zone, ldns_rr* rr, int add, int backup)
{
    ods_status status = ODS_STATUS_OK;
    uint32_t tmp = 0;
    ods_log_assert(rr);
    ods_log_assert(zone);
    ods_log_assert(zone->name);
    ods_log_assert(zone->db);
    ods_log_assert(zone->signconf);
    /* We only support IN class */
    if (ldns_rr_get_class(rr) != LDNS_RR_CLASS_IN) {
        ods_log_warning("[%s] only class in is supported, changing class "
            "to in", adapi_str);
        ldns_rr_set_class(rr, LDNS_RR_CLASS_IN);
    }
    /* RR processing */
    if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
        if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex)) {
            ods_log_error("[%s] unable to %s rr to zone: soa record has "
                "invalid owner name", adapi_str, add?"add":"delete");
            return ODS_STATUS_ERR;
        }
        status = adapi_process_soa(zone, rr, add, backup);
        if (status != ODS_STATUS_OK) {
            ods_log_error("[%s] unable to %s rr: failed to process soa "
                "record", adapi_str, add?"add":"delete");
            return status;
        }
    } else {
        if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex) &&
            !ldns_dname_is_subdomain(ldns_rr_owner(rr), zone->apex)) {
            ods_log_warning("[%s] zone %s contains out-of-zone data, "
                "skipping", adapi_str, zone->name);
            return ODS_STATUS_UNCHANGED;
        } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY) {
            adapi_process_dnskey(zone, rr);
        } else if (util_is_dnssec_rr(rr) && !backup) {
            ods_log_warning("[%s] zone %s contains dnssec data (type=%u), "
                "skipping", adapi_str, zone->name,
                (unsigned) ldns_rr_get_type(rr));
            return ODS_STATUS_UNCHANGED;
        } else if (zone->signconf->max_zone_ttl) {
            /* Convert MaxZoneTTL */
            tmp = (uint32_t) duration2time(zone->signconf->max_zone_ttl);
        }
    }
    /* //MaxZoneTTL. Only set for RRtype != SOA && RRtype != DNSKEY */
    if (tmp && tmp < ldns_rr_ttl(rr)) {
        char* str = ldns_rdf2str(ldns_rr_owner(rr));
        if (str) {
            size_t i = 0;
            str[(strlen(str))-1] = '\0';
            /* replace tabs with white space */
            for (i=0; i < strlen(str); i++) {
                if (str[i] == '\t') {
                    str[i] = ' ';
                }
            }
            ods_log_debug("[%s] capping ttl %u to MaxZoneTTL %u for rrset "
                "<%s,%s>", adapi_str, ldns_rr_ttl(rr), tmp, str,
                rrset_type2str(ldns_rr_get_type(rr)));
        }
        ldns_rr_set_ttl(rr, tmp);
    }

    /* TODO: DNAME and CNAME checks */
    /* TODO: NS and DS checks */

    if (add) {
        return zone_add_rr(zone, rr, 1);
    } else {
        return zone_del_rr(zone, rr, 1);
    }
    /* not reached */
    return ODS_STATUS_ERR;
}