Beispiel #1
0
/**
 * Add new RR. It converts ldns RR to wire format.
 * @param anchors: anchor storage.
 * @param buffer: parsing buffer.
 * @param rr: the rr (allocated by caller).
 * @return NULL on error, else the trust anchor.
 */
static struct trust_anchor*
anchor_store_new_rr(struct val_anchors* anchors, ldns_buffer* buffer, 
	ldns_rr* rr)
{
	struct trust_anchor* ta;
	ldns_rdf* owner = ldns_rr_owner(rr);
	ldns_status status;
	ldns_buffer_clear(buffer);
	ldns_buffer_skip(buffer, 2); /* skip rdatalen */
	status = ldns_rr_rdata2buffer_wire(buffer, rr);
	if(status != LDNS_STATUS_OK) {
		log_err("error converting trustanchor to wireformat: %s", 
			ldns_get_errorstr_by_id(status));
		return NULL;
	}
	ldns_buffer_flip(buffer);
	ldns_buffer_write_u16_at(buffer, 0, ldns_buffer_limit(buffer) - 2);

	if(!(ta=anchor_store_new_key(anchors, ldns_rdf_data(owner), 
		ldns_rr_get_type(rr), ldns_rr_get_class(rr),
		ldns_buffer_begin(buffer), ldns_buffer_limit(buffer)))) {
		return NULL;
	}
	log_nametypeclass(VERB_QUERY, "adding trusted key",
		ldns_rdf_data(owner), 
		ldns_rr_get_type(rr), ldns_rr_get_class(rr));
	return ta;
}
Beispiel #2
0
ldns_status
ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
{
	uint16_t i;
	uint16_t rdl_pos = 0;
	
	if (ldns_rr_owner(rr)) {
		(void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
	}
	
	if (ldns_buffer_reserve(buffer, 4)) {
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
	}

	if (section != LDNS_SECTION_QUESTION) {
		if (ldns_buffer_reserve(buffer, 6)) {
			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
			/* remember pos for later */
			rdl_pos = ldns_buffer_position(buffer);
			ldns_buffer_write_u16(buffer, 0);
		}	

		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
			(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
		}
		
		if (rdl_pos != 0) {
			ldns_buffer_write_u16_at(buffer, rdl_pos,
			                         ldns_buffer_position(buffer)
		        	                   - rdl_pos - 2);
		}
	}
	return ldns_buffer_status(buffer);
}
/**
 * Add RR to query.
 *
 */
int
query_add_rr(query_type* q, ldns_rr* rr)
{
    size_t i = 0;
    size_t tc_mark = 0;
    size_t rdlength_pos = 0;
    uint16_t rdlength = 0;

    ods_log_assert(q);
    ods_log_assert(q->buffer);
    ods_log_assert(rr);

    /* set truncation mark, in case rr does not fit */
    tc_mark = buffer_position(q->buffer);
    /* owner type class ttl */
    if (!buffer_available(q->buffer, ldns_rdf_size(ldns_rr_owner(rr)))) {
        goto query_add_rr_tc;
    }
    buffer_write_rdf(q->buffer, ldns_rr_owner(rr));
    if (!buffer_available(q->buffer, sizeof(uint16_t) + sizeof(uint16_t) +
        sizeof(uint32_t) + sizeof(rdlength))) {
        goto query_add_rr_tc;
    }
    buffer_write_u16(q->buffer, (uint16_t) ldns_rr_get_type(rr));
    buffer_write_u16(q->buffer, (uint16_t) ldns_rr_get_class(rr));
    buffer_write_u32(q->buffer, (uint32_t) ldns_rr_ttl(rr));
    /* skip rdlength */
    rdlength_pos = buffer_position(q->buffer);
    buffer_skip(q->buffer, sizeof(rdlength));
    /* write rdata */
    for (i=0; i < ldns_rr_rd_count(rr); i++) {
        if (!buffer_available(q->buffer, ldns_rdf_size(ldns_rr_rdf(rr, i)))) {
            goto query_add_rr_tc;
        }
        buffer_write_rdf(q->buffer, ldns_rr_rdf(rr, i));
    }

    if (!query_overflow(q)) {
        /* write rdlength */
        rdlength = buffer_position(q->buffer) - rdlength_pos - sizeof(rdlength);
        buffer_write_u16_at(q->buffer, rdlength_pos, rdlength);
        /* position updated by buffer_write() */
        return 1;
    }

query_add_rr_tc:
    buffer_set_position(q->buffer, tc_mark);
    ods_log_assert(!query_overflow(q));
    return 0;

}
Beispiel #4
0
static int udp_bind(int sock, int port, const char *my_address)
{
    struct sockaddr_in addr;
    in_addr_t maddr = INADDR_ANY;

    if (my_address) {
#ifdef AF_INET6
        if (inet_pton(AF_INET6, my_address, &maddr) < 1) {
#else
	if (0) {
#endif
            if (inet_pton(AF_INET, my_address, &maddr) < 1) {
                return -2;
            }
        }
    }

#ifndef S_SPLINT_S
    addr.sin_family = AF_INET;
#endif
    addr.sin_port = (in_port_t) htons((uint16_t)port);
    addr.sin_addr.s_addr = maddr;
    return bind(sock, (struct sockaddr *)&addr, (socklen_t) sizeof(addr));
}

/* this will probably be moved to a better place in the library itself */
ldns_rr_list *
get_rrset(const ldns_zone *zone, const ldns_rdf *owner_name, const ldns_rr_type qtype, const ldns_rr_class qclass)
{
	uint16_t i;
	ldns_rr_list *rrlist = ldns_rr_list_new();
	ldns_rr *cur_rr;
	if (!zone || !owner_name) {
		fprintf(stderr, "Warning: get_rrset called with NULL zone or owner name\n");
		return rrlist;
	}
	
	for (i = 0; i < ldns_zone_rr_count(zone); i++) {
		cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
		if (ldns_dname_compare(ldns_rr_owner(cur_rr), owner_name) == 0 &&
		    ldns_rr_get_class(cur_rr) == qclass &&
		    ldns_rr_get_type(cur_rr) == qtype
		   ) {
			ldns_rr_list_push_rr(rrlist, ldns_rr_clone(cur_rr));
		}
	}
	
	printf("Found rrset of %u rrs\n", (unsigned int) ldns_rr_list_rr_count(rrlist));
	
	return rrlist;
}
Beispiel #5
0
/** read qinfo from next three words */
static char*
load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf, 
	struct regional* region)
{
	/* s is part of the buf */
	char* s = str;
	ldns_rr* rr;
	ldns_status status;

	/* skip three words */
	s = strchr(str, ' ');
	if(s) s = strchr(s+1, ' ');
	if(s) s = strchr(s+1, ' ');
	if(!s) {
		log_warn("error line too short, %s", str);
		return NULL;
	}
	s[0] = 0;
	s++;

	/* parse them */
	status = ldns_rr_new_question_frm_str(&rr, str, NULL, NULL);
	if(status != LDNS_STATUS_OK) {
		log_warn("error cannot parse: %s %s",
			ldns_get_errorstr_by_id(status), str);
		return NULL;
	}
	qinfo->qtype = ldns_rr_get_type(rr);
	qinfo->qclass = ldns_rr_get_class(rr);
	ldns_buffer_clear(buf);
	status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr));
	ldns_rr_free(rr);
	if(status != LDNS_STATUS_OK) {
		log_warn("error cannot dname2wire: %s", 
			ldns_get_errorstr_by_id(status));
		return NULL;
	}
	ldns_buffer_flip(buf);
	qinfo->qname_len = ldns_buffer_limit(buf);
	qinfo->qname = (uint8_t*)regional_alloc_init(region, 
		ldns_buffer_begin(buf), ldns_buffer_limit(buf));
	if(!qinfo->qname) {
		log_warn("error out of memory");
		return NULL;
	}

	return s;
}
Beispiel #6
0
ldns_status
ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
						const ldns_rr *rr,
						int section)
{
	uint16_t i;
	uint16_t rdl_pos = 0;
	bool pre_rfc3597 = false;
	switch (ldns_rr_get_type(rr)) {
	case LDNS_RR_TYPE_NS:
	case LDNS_RR_TYPE_MD:
	case LDNS_RR_TYPE_MF:
	case LDNS_RR_TYPE_CNAME:
	case LDNS_RR_TYPE_SOA:
	case LDNS_RR_TYPE_MB:
	case LDNS_RR_TYPE_MG:
	case LDNS_RR_TYPE_MR:
	case LDNS_RR_TYPE_PTR:
	case LDNS_RR_TYPE_HINFO:
	case LDNS_RR_TYPE_MINFO:
	case LDNS_RR_TYPE_MX:
	case LDNS_RR_TYPE_RP:
	case LDNS_RR_TYPE_AFSDB:
	case LDNS_RR_TYPE_RT:
	case LDNS_RR_TYPE_SIG:
	case LDNS_RR_TYPE_PX:
	case LDNS_RR_TYPE_NXT:
	case LDNS_RR_TYPE_NAPTR:
	case LDNS_RR_TYPE_KX:
	case LDNS_RR_TYPE_SRV:
	case LDNS_RR_TYPE_DNAME:
	case LDNS_RR_TYPE_A6:
		pre_rfc3597 = true;
		break;
	default:
		break;
	}
	
	if (ldns_rr_owner(rr)) {
		(void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
	}
	
	if (ldns_buffer_reserve(buffer, 4)) {
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
	}

	if (section != LDNS_SECTION_QUESTION) {
		if (ldns_buffer_reserve(buffer, 6)) {
			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
			/* remember pos for later */
			rdl_pos = ldns_buffer_position(buffer);
			ldns_buffer_write_u16(buffer, 0);
		}	

		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
			if (pre_rfc3597) {
				(void) ldns_rdf2buffer_wire_canonical(buffer,
											   ldns_rr_rdf(rr, i));
			} else {
				(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
			}
		}
		
		if (rdl_pos != 0) {
			ldns_buffer_write_u16_at(buffer, rdl_pos,
			                         ldns_buffer_position(buffer)
		        	                   - rdl_pos - 2);
		}
	}
	return ldns_buffer_status(buffer);
}
/**
 * Process query.
 *
 */
query_state
query_process(query_type* q, void* engine)
{
    ldns_status status = LDNS_STATUS_OK;
    ldns_pkt* pkt = NULL;
    ldns_rr* rr = NULL;
    ldns_pkt_rcode rcode = LDNS_RCODE_NOERROR;
    ldns_pkt_opcode opcode = LDNS_PACKET_QUERY;
    ldns_rr_type qtype = LDNS_RR_TYPE_SOA;
    engine_type* e = (engine_type*) engine;
    ods_log_assert(e);
    ods_log_assert(q);
    ods_log_assert(q->buffer);
    if (!e || !q || !q->buffer) {
        ods_log_error("[%s] drop query: assertion error", query_str);
        return QUERY_DISCARDED; /* should not happen */
    }
    if (buffer_limit(q->buffer) < BUFFER_PKT_HEADER_SIZE) {
        ods_log_debug("[%s] drop query: packet too small", query_str);
        return QUERY_DISCARDED; /* too small */
    }
    if (buffer_pkt_qr(q->buffer)) {
        ods_log_debug("[%s] drop query: qr bit set", query_str);
        return QUERY_DISCARDED; /* not a query */
    }
    /* parse packet */
    status = ldns_wire2pkt(&pkt, buffer_current(q->buffer),
        buffer_remaining(q->buffer));
    if (status != LDNS_STATUS_OK) {
        ods_log_debug("[%s] got bad packet: %s", query_str,
            ldns_get_errorstr_by_id(status));
        return query_formerr(q);
    }
    rr = ldns_rr_list_rr(ldns_pkt_question(pkt), 0);
    lock_basic_lock(&e->zonelist->zl_lock);
    /* we can just lookup the zone, because we will only handle SOA queries,
       zone transfers, updates and notifies */
    q->zone = zonelist_lookup_zone_by_dname(e->zonelist, ldns_rr_owner(rr),
        ldns_rr_get_class(rr));
    /* don't answer for zones that are just added */
    if (q->zone && q->zone->zl_status == ZONE_ZL_ADDED) {
        ods_log_warning("[%s] zone %s just added, don't answer for now",
            query_str, q->zone->name);
        q->zone = NULL;
    }
    lock_basic_unlock(&e->zonelist->zl_lock);
    if (!q->zone) {
        ods_log_debug("[%s] zone not found", query_str);
        return query_servfail(q);
    }
    /* see if it is tsig signed */
    if (!query_find_tsig(q)) {
        return query_formerr(q);
    }
    /* else: valid tsig, or no tsig present */
    ods_log_debug("[%s] tsig %s", query_str, tsig_status2str(q->tsig_rr->status));
    rcode = query_process_tsig(q);
    if (rcode != LDNS_RCODE_NOERROR) {
        return query_error(q, rcode);
    }
    /* process edns */
    rcode = query_process_edns(q);
    if (rcode != LDNS_RCODE_NOERROR) {
        /* We should not return FORMERR, but BADVERS (=16).
         * BADVERS is created with Ext. RCODE, followed by RCODE.
         * Ext. RCODE is set to 1, RCODE must be 0 (getting 0x10 = 16).
         * Thus RCODE = NOERROR = NSD_RC_OK. */
        return query_error(q, LDNS_RCODE_NOERROR);
    }

    /* handle incoming request */
    opcode = ldns_pkt_get_opcode(pkt);
    qtype = ldns_rr_get_type(rr);
    ldns_pkt_free(pkt);

    switch (opcode) {
        case LDNS_PACKET_NOTIFY:
            return query_process_notify(q, qtype, engine);
        case LDNS_PACKET_QUERY:
            return query_process_query(q, qtype, engine);
        case LDNS_PACKET_UPDATE:
            return query_process_update(q);
        default:
            break;
    }
    return query_notimpl(q);
}
Beispiel #8
0
void print_passet(pdns_record *l, pdns_asset *p, ldns_rr *rr,
                  ldns_rdf *lname, uint16_t rcode)
{
    FILE *fd = NULL;
    static char ip_addr_s[INET6_ADDRSTRLEN];
    static char ip_addr_c[INET6_ADDRSTRLEN];
    char *d = config.log_delimiter;
    char *rr_class;
    char *rr_type;
    char *rr_rcode;
    char buffer[1000] = "";
    char *output = buffer;
    int offset = 0;
    uint8_t is_err_record = 0;

#ifdef HAVE_JSON
    json_t *jdata;
    size_t data_flags = 0;

    /* Print in the same order as inserted */
    data_flags |= JSON_PRESERVE_ORDER;

    /* No whitespace between fields */
    data_flags |= JSON_COMPACT;
#endif /* HAVE_JSON */

    /* If pdns_asset is not defined, then this is a NXD record */
    if (p == NULL) {
        is_err_record = 1;
    }

    /* Use the correct file descriptor */
    if (is_err_record && config.output_log_nxd) {
        if (config.logfile_all) {
            fd = config.logfile_fd;
        }
        else {
            fd = config.logfile_nxd_fd;
        }
        if (fd == NULL) return;
    }
    else if (!is_err_record && config.output_log) {
        fd = config.logfile_fd;
        if (fd == NULL) return;
    }


    if (is_err_record) {
        u_ntop(l->sip, l->af, ip_addr_s);
        u_ntop(l->cip, l->af, ip_addr_c);
    }
    else {
        u_ntop(p->sip, p->af, ip_addr_s);
        u_ntop(p->cip, p->af, ip_addr_c);
    }

    rr_class = malloc(10);
    rr_type  = malloc(10);
    rr_rcode = malloc(20);

    switch (ldns_rr_get_class(rr)) {
        case LDNS_RR_CLASS_IN:
            snprintf(rr_class, 10, "IN");
            break;
        case LDNS_RR_CLASS_CH:
            snprintf(rr_class, 10, "CH");
            break;
        case LDNS_RR_CLASS_HS:
            snprintf(rr_class, 10, "HS");
            break;
        case LDNS_RR_CLASS_NONE:
            snprintf(rr_class, 10, "NONE");
            break;
        case LDNS_RR_CLASS_ANY:
            snprintf(rr_class, 10, "ANY");
            break;
        default:
            snprintf(rr_class, 10, "%d", ldns_rr_get_class(rr));
            break;
    }

    switch (ldns_rr_get_type(rr)) {
        case LDNS_RR_TYPE_PTR:
            snprintf(rr_type, 10, "PTR");
            break;
        case LDNS_RR_TYPE_A:
            snprintf(rr_type, 10, "A");
            break;
        case LDNS_RR_TYPE_AAAA:
            snprintf(rr_type, 10, "AAAA");
            break;
        case LDNS_RR_TYPE_CNAME:
            snprintf(rr_type, 10, "CNAME");
            break;
        case LDNS_RR_TYPE_DNAME:
            snprintf(rr_type, 10, "DNAME");
            break;
        case LDNS_RR_TYPE_NAPTR:
            snprintf(rr_type, 10, "NAPTR");
            break;
        case LDNS_RR_TYPE_RP:
            snprintf(rr_type, 10, "RP");
            break;
        case LDNS_RR_TYPE_SRV:
            snprintf(rr_type, 10, "SRV");
            break;
        case LDNS_RR_TYPE_TXT:
            snprintf(rr_type, 10, "TXT");
            break;
        case LDNS_RR_TYPE_SOA:
            snprintf(rr_type, 10, "SOA");
            break;
        case LDNS_RR_TYPE_NS:
            snprintf(rr_type, 10, "NS");
            break;
        case LDNS_RR_TYPE_MX:
            snprintf(rr_type, 10, "MX");
            break;
        default:
            if (is_err_record) {
                snprintf(rr_type, 10, "%d", ldns_rdf_get_type(lname));
            }
            else {
                snprintf(rr_type, 10, "%d", p->rr->_rr_type);
            }
            break;
    }

    if (is_err_record) {
        switch (rcode) {
            case 1:
                snprintf(rr_rcode, 20, "FORMERR");
                break;
            case 2:
                snprintf(rr_rcode, 20, "SERVFAIL");
                break;
            case 3:
                snprintf(rr_rcode, 20, "NXDOMAIN");
                break;
            case 4:
                snprintf(rr_rcode, 20, "NOTIMPL");
                break;
            case 5:
                snprintf(rr_rcode, 20, "REFUSED");
                break;
            case 6:
                snprintf(rr_rcode, 20, "YXDOMAIN");
                break;
            case 7:
                snprintf(rr_rcode, 20, "YXRRSET");
                break;
            case 8:
                snprintf(rr_rcode, 20, "NXRRSET");
                break;
            case 9:
                snprintf(rr_rcode, 20, "NOTAUTH");
                break;
            case 10:
                snprintf(rr_rcode, 20, "NOTZONE");
                break;
            default:
                snprintf(rr_rcode, 20, "UNKNOWN-ERROR-%d", rcode);
                break;
        }
    }

#ifdef HAVE_JSON
    if ((is_err_record && config.use_json_nxd) ||
        (!is_err_record && config.use_json)) {
        jdata = json_object();
        if (config.fieldsf & FIELD_TIMESTAMP_S)
            json_object_set_new(jdata, JSON_TIMESTAMP_S,  json_integer(l->last_seen.tv_sec));
        if (config.fieldsf & FIELD_TIMESTAMP_MS)
            json_object_set_new(jdata, JSON_TIMESTAMP_MS, json_integer(l->last_seen.tv_usec));
        if (config.fieldsf & FIELD_CLIENT)
            json_object_set_new(jdata, JSON_CLIENT,       json_string(ip_addr_c));
        if (config.fieldsf & FIELD_SERVER)
            json_object_set_new(jdata, JSON_SERVER,       json_string(ip_addr_s));
        if (config.fieldsf & FIELD_CLASS)
            json_object_set_new(jdata, JSON_CLASS,        json_string(rr_class));
        if (config.fieldsf & FIELD_QUERY)
            json_object_set_new(jdata, JSON_QUERY,        json_string((const char *)l->qname));
        if (config.fieldsf & FIELD_TYPE)
            json_object_set_new(jdata, JSON_TYPE,         json_string(rr_type));

        if (is_err_record) {
            if (config.fieldsf & FIELD_ANSWER)
                json_object_set_new(jdata, JSON_ANSWER,   json_string(rr_rcode));
            if (config.fieldsf & FIELD_TTL)
                json_object_set_new(jdata, JSON_TTL,      json_integer(PASSET_ERR_TTL));
            if (config.fieldsf & FIELD_COUNT)
                json_object_set_new(jdata, JSON_COUNT,    json_integer(PASSET_ERR_COUNT));
        }
        else {
            if (config.fieldsf & FIELD_ANSWER)
                json_object_set_new(jdata, JSON_ANSWER,   json_string((const char *)p->answer));
            if (config.fieldsf & FIELD_TTL)
                json_object_set_new(jdata, JSON_TTL,      json_integer(p->rr->_ttl));
            if (config.fieldsf & FIELD_COUNT)
                json_object_set_new(jdata, JSON_COUNT,    json_integer(p->seen));
        }

        output = json_dumps(jdata, data_flags);
        if (output == NULL)
            return;
    }
    else {
#endif /* HAVE_JSON */
        /* Print timestamp */
        if ((config.fieldsf & FIELD_TIMESTAMP_S) &&
            (config.fieldsf & FIELD_TIMESTAMP_MS)) {
            if (is_err_record) {
                offset += snprintf(output, sizeof(buffer) - offset, "%lu.%06lu",
                                   l->last_seen.tv_sec, l->last_seen.tv_usec);
            }
            else {
                offset += snprintf(output, sizeof(buffer) - offset, "%lu.%06lu",
                                   p->last_seen.tv_sec, p->last_seen.tv_usec);
            }
        }
        else if (config.fieldsf & FIELD_TIMESTAMP_S) {
            if (is_err_record) {
                offset += snprintf(output, sizeof(buffer) - offset, "%lu", l->last_seen.tv_sec);
            }
            else {
                offset += snprintf(output, sizeof(buffer) - offset, "%lu", p->last_seen.tv_sec);
            }
        }
        else if (config.fieldsf & FIELD_TIMESTAMP_MS) {
            if (is_err_record) {
                offset += snprintf(output, sizeof(buffer) - offset, "%06lu", l->last_seen.tv_usec);
            }
            else {
                offset += snprintf(output, sizeof(buffer) - offset, "%06lu", p->last_seen.tv_usec);
            }
        }

        /* Print client IP */
        if (config.fieldsf & FIELD_CLIENT) {
            if (offset != 0)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", d);
            offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", ip_addr_c);
        }

        /* Print server IP */
        if (config.fieldsf & FIELD_SERVER) {
            if (offset != 0)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", d);
            offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", ip_addr_s);
        }

        /* Print class */
        if (config.fieldsf & FIELD_CLASS) {
            if (offset != 0)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", d);
            offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", rr_class);
        }

        /* Print query */
        if (config.fieldsf & FIELD_QUERY) {
            if (offset != 0)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", d);
            offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", l->qname);
        }

        /* Print type */
        if (config.fieldsf & FIELD_TYPE) {
            if (offset != 0)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", d);
            offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", rr_type);
        }

        /* Print answer */
        if (config.fieldsf & FIELD_ANSWER) {
            if (offset != 0)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", d);
            if (is_err_record)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", rr_rcode);
            else
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", p->answer);
        }

        /* Print TTL */
        if (config.fieldsf & FIELD_TTL) {
            if (offset != 0)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", d);
            if (is_err_record)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%d", PASSET_ERR_TTL);
            else
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%u", p->rr->_ttl);
        }

        /* Print count */
       if (config.fieldsf & FIELD_COUNT) {
            if (offset != 0)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%s", d);
            if (is_err_record)
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%d", PASSET_ERR_COUNT);
            else
                offset += snprintf(output+offset, sizeof(buffer) - offset, "%lu", p->seen);
        }
#ifdef HAVE_JSON
    }
#endif /* HAVE_JSON */

    /* Print to log file */
    if (fd) {
        fprintf(fd, "%s\n", output);
        fflush(fd);
    }

    /* Print to syslog */
    if ((is_err_record && config.output_syslog_nxd) ||
        (!is_err_record && config.output_syslog)) {
        openlog(PDNS_IDENT, LOG_NDELAY, LOG_LOCAL7);
        syslog(LOG_INFO, "%s", output);
        closelog();
    }

    if (is_err_record) {
        l->last_print = l->last_seen;
        l->seen = 0;
    }
    else {
        p->last_print = p->last_seen;
        p->seen = 0;
    }

    free(rr_class);
    free(rr_type);
    free(rr_rcode);

}
Beispiel #9
0
static CborError cbor_ldns_rr_list(CborEncoder *encoder, ldns_rr_list *list, size_t count, int *should_flush) {
    CborError cbor_err = CborNoError;
    size_t n;
    ldns_buffer *dname;
    char *dname_str;

    if (!encoder) {
        return CborErrorInternalError;
    }
    if (!list) {
        return CborErrorInternalError;
    }
    if (!count) {
        return CborErrorInternalError;
    }
    if (!should_flush) {
        return CborErrorInternalError;
    }

    for (n = 0; cbor_err == CborNoError && n < count; n++) {
        CborEncoder cbor_rr;
        uint8_t *rdata_bytes;
        ldns_buffer *rdata;
        ldns_rr *rr = ldns_rr_list_rr(list, n);
        size_t rd_count;

        if (!rr) {
            return CborErrorInternalError;
        }
        rd_count = ldns_rr_rd_count(rr);

        if (!(dname = ldns_buffer_new(512))) {
            return CborErrorOutOfMemory;
        }
        if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) {
            ldns_buffer_free(dname);
            return CborErrorInternalError;
        }
        ldns_buffer_write_u8(dname, 0);
        if (!(dname_str = ldns_buffer_export(dname))) {
            ldns_buffer_free(dname);
            return CborErrorOutOfMemory;
        }

        if (cbor_err == CborNoError) cbor_err = append_cbor_map(encoder, &cbor_rr, CborIndefiniteLength, should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "NAME", should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, dname_str, should_flush);
        free(dname_str);
        ldns_buffer_free(dname);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "CLASS", should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_get_class(rr), should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "TYPE", should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_get_type(rr), should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "TTL", should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_ttl(rr), should_flush);

        if (rd_count == 1) {
            if (!(rdata = ldns_buffer_new(64*1024))) {
                return CborErrorOutOfMemory;
            }
            if (ldns_rdf2buffer_wire(rdata, ldns_rr_rdf(rr, 0)) != LDNS_STATUS_OK) {
                ldns_buffer_free(rdata);
                return CborErrorInternalError;
            }
            if (!(rdata_bytes = ldns_buffer_export(rdata))) {
                ldns_buffer_free(rdata);
                return CborErrorOutOfMemory;
            }

            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "RDLENGTH", should_flush);
            if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_buffer_position(rdata), should_flush);
            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "RDATA", should_flush);
            if (cbor_err == CborNoError) cbor_err = append_cbor_bytes(&cbor_rr, rdata_bytes, ldns_buffer_position(rdata), should_flush);
            free(rdata_bytes);
            ldns_buffer_free(rdata);
        }
        else if (rd_count > 1) {
            size_t n2;
            CborEncoder rr_set;

            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "rrSet", should_flush);
            if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor_rr, &rr_set, CborIndefiniteLength, should_flush);
            for (n2 = 0; n2 < rd_count; n2++) {
                if (!(rdata = ldns_buffer_new(64*1024))) {
                    return CborErrorOutOfMemory;
                }
                if (ldns_rdf2buffer_wire(rdata, ldns_rr_rdf(rr, n2)) != LDNS_STATUS_OK) {
                    ldns_buffer_free(rdata);
                    return CborErrorInternalError;
                }
                if (!(rdata_bytes = ldns_buffer_export(rdata))) {
                    ldns_buffer_free(rdata);
                    return CborErrorOutOfMemory;
                }

                if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&rr_set, "RDLENGTH", should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&rr_set, ldns_buffer_position(rdata), should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&rr_set, "RDATA", should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_bytes(&rr_set, rdata_bytes, ldns_buffer_position(rdata), should_flush);
                free(rdata_bytes);
                ldns_buffer_free(rdata);
            }
            if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor_rr, &rr_set, should_flush);
        }

        if (cbor_err == CborNoError) cbor_err = close_cbor_container(encoder, &cbor_rr, should_flush);
    }

    return cbor_err;
}
Beispiel #10
0
/** load an RR into rrset */
static int
load_rr(SSL* ssl, ldns_buffer* buf, struct regional* region,
	struct ub_packed_rrset_key* rk, struct packed_rrset_data* d,
	unsigned int i, int is_rrsig, int* go_on, uint32_t now)
{
	ldns_rr* rr;
	ldns_status status;

	/* read the line */
	if(!ssl_read_buf(ssl, buf))
		return 0;
	if(strncmp((char*)ldns_buffer_begin(buf), "BADRR\n", 6) == 0) {
		*go_on = 0;
		return 1;
	}
	status = ldns_rr_new_frm_str(&rr, (char*)ldns_buffer_begin(buf),
		LDNS_DEFAULT_TTL, NULL, NULL);
	if(status != LDNS_STATUS_OK) {
		log_warn("error cannot parse rr: %s: %s",
			ldns_get_errorstr_by_id(status),
			(char*)ldns_buffer_begin(buf));
		return 0;
	}
	if(is_rrsig && ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
		log_warn("error expected rrsig but got %s",
			(char*)ldns_buffer_begin(buf));
		return 0;
	}

	/* convert ldns rr into packed_rr */
	d->rr_ttl[i] = ldns_rr_ttl(rr) + now;
	ldns_buffer_clear(buf);
	ldns_buffer_skip(buf, 2);
	status = ldns_rr_rdata2buffer_wire(buf, rr);
	if(status != LDNS_STATUS_OK) {
		log_warn("error cannot rr2wire: %s",
			ldns_get_errorstr_by_id(status));
		ldns_rr_free(rr);
		return 0;
	}
	ldns_buffer_flip(buf);
	ldns_buffer_write_u16_at(buf, 0, ldns_buffer_limit(buf) - 2);

	d->rr_len[i] = ldns_buffer_limit(buf);
	d->rr_data[i] = (uint8_t*)regional_alloc_init(region, 
		ldns_buffer_begin(buf), ldns_buffer_limit(buf));
	if(!d->rr_data[i]) {
		ldns_rr_free(rr);
		log_warn("error out of memory");
		return 0;
	}

	/* if first entry, fill the key structure */
	if(i==0) {
		rk->rk.type = htons(ldns_rr_get_type(rr));
		rk->rk.rrset_class = htons(ldns_rr_get_class(rr));
		ldns_buffer_clear(buf);
		status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr));
		if(status != LDNS_STATUS_OK) {
			log_warn("error cannot dname2buffer: %s",
				ldns_get_errorstr_by_id(status));
			ldns_rr_free(rr);
			return 0;
		}
		ldns_buffer_flip(buf);
		rk->rk.dname_len = ldns_buffer_limit(buf);
		rk->rk.dname = regional_alloc_init(region, 
			ldns_buffer_begin(buf), ldns_buffer_limit(buf));
		if(!rk->rk.dname) {
			log_warn("error out of memory");
			ldns_rr_free(rr);
			return 0;
		}
	}
	ldns_rr_free(rr);

	return 1;
}
Beispiel #11
0
ldns_rr *
ldns_create_empty_rrsig(ldns_rr_list *rrset,
                        ldns_key *current_key)
{
	uint32_t orig_ttl;
	ldns_rr_class orig_class;
	time_t now;
	ldns_rr *current_sig;
	uint8_t label_count;
	ldns_rdf *signame;

	label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset,
	                                                   0)));
        /* RFC4035 2.2: not counting the leftmost label if it is a wildcard */
        if(ldns_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0))))
                label_count --;

	current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);

	/* set the type on the new signature */
	orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
	orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));

	ldns_rr_set_ttl(current_sig, orig_ttl);
	ldns_rr_set_class(current_sig, orig_class);
	ldns_rr_set_owner(current_sig,
			  ldns_rdf_clone(
			       ldns_rr_owner(
				    ldns_rr_list_rr(rrset,
						    0))));

	/* fill in what we know of the signature */

	/* set the orig_ttl */
	(void)ldns_rr_rrsig_set_origttl(
		   current_sig,
		   ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
					 orig_ttl));
	/* the signers name */
	signame = ldns_rdf_clone(ldns_key_pubkey_owner(current_key));
	ldns_dname2canonical(signame);
	(void)ldns_rr_rrsig_set_signame(
			current_sig,
			signame);
	/* label count - get it from the first rr in the rr_list */
	(void)ldns_rr_rrsig_set_labels(
			current_sig,
			ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
			                     label_count));
	/* inception, expiration */
	now = time(NULL);
	if (ldns_key_inception(current_key) != 0) {
		(void)ldns_rr_rrsig_set_inception(
				current_sig,
				ldns_native2rdf_int32(
				    LDNS_RDF_TYPE_TIME,
				    ldns_key_inception(current_key)));
	} else {
		(void)ldns_rr_rrsig_set_inception(
				current_sig,
				ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
	}
	if (ldns_key_expiration(current_key) != 0) {
		(void)ldns_rr_rrsig_set_expiration(
				current_sig,
				ldns_native2rdf_int32(
				    LDNS_RDF_TYPE_TIME,
				    ldns_key_expiration(current_key)));
	} else {
		(void)ldns_rr_rrsig_set_expiration(
			     current_sig,
				ldns_native2rdf_int32(
				    LDNS_RDF_TYPE_TIME,
				    now + LDNS_DEFAULT_EXP_TIME));
	}

	(void)ldns_rr_rrsig_set_keytag(
		   current_sig,
		   ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
		                         ldns_key_keytag(current_key)));

	(void)ldns_rr_rrsig_set_algorithm(
			current_sig,
			ldns_native2rdf_int8(
			    LDNS_RDF_TYPE_ALG,
			    ldns_key_algorithm(current_key)));

	(void)ldns_rr_rrsig_set_typecovered(
			current_sig,
			ldns_native2rdf_int16(
			    LDNS_RDF_TYPE_TYPE,
			    ldns_rr_get_type(ldns_rr_list_rr(rrset,
			                                     0))));
	return current_sig;
}
int
getrrsetbyname(const char *hostname, unsigned int rdclass,
	       unsigned int rdtype, unsigned int flags,
	       struct rrsetinfo **res)
{
	int result;
	unsigned int i, j, index_ans, index_sig;
	struct rrsetinfo *rrset = NULL;
	struct rdatainfo *rdata;
	size_t len;
	ldns_resolver *ldns_res;
	ldns_rdf *domain = NULL;
	ldns_pkt *pkt = NULL;
	ldns_rr_list *rrsigs = NULL, *rrdata = NULL;
	ldns_status err;
	ldns_rr *rr;

	/* check for invalid class and type */
	if (rdclass > 0xffff || rdtype > 0xffff) {
		result = ERRSET_INVAL;
		goto fail;
	}

	/* don't allow queries of class or type ANY */
	if (rdclass == 0xff || rdtype == 0xff) {
		result = ERRSET_INVAL;
		goto fail;
	}

	/* don't allow flags yet, unimplemented */
	if (flags) {
		result = ERRSET_INVAL;
		goto fail;
	}

	/* Initialize resolver from resolv.conf */
	domain = ldns_dname_new_frm_str(hostname);
	if ((err = ldns_resolver_new_frm_file(&ldns_res, NULL)) != \
	    LDNS_STATUS_OK) {
		result = ERRSET_FAIL;
		goto fail;
	}

#ifdef LDNS_DEBUG
	ldns_resolver_set_debug(ldns_res, true);
#endif /* LDNS_DEBUG */

	ldns_resolver_set_dnssec(ldns_res, true); /* Use DNSSEC */

	/* make query */
	pkt = ldns_resolver_query(ldns_res, domain, rdtype, rdclass, LDNS_RD);

	/*** TODO: finer errcodes -- see original **/
	if (!pkt || ldns_pkt_ancount(pkt) < 1) {
		result = ERRSET_FAIL;
		goto fail;
	}

	/* initialize rrset */
	rrset = calloc(1, sizeof(struct rrsetinfo));
	if (rrset == NULL) {
		result = ERRSET_NOMEMORY;
		goto fail;
	}

	rrdata = ldns_pkt_rr_list_by_type(pkt, rdtype, LDNS_SECTION_ANSWER);
	rrset->rri_nrdatas = ldns_rr_list_rr_count(rrdata);
	if (!rrset->rri_nrdatas) {
		result = ERRSET_NODATA;
		goto fail;
	}

	/* copy name from answer section */
	len = ldns_rdf_size(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0)));
	if ((rrset->rri_name = malloc(len)) == NULL) {
		result = ERRSET_NOMEMORY;
		goto fail;
	}
	memcpy(rrset->rri_name,
	    ldns_rdf_data(ldns_rr_owner(ldns_rr_list_rr(rrdata, 0))), len);

	rrset->rri_rdclass = ldns_rr_get_class(ldns_rr_list_rr(rrdata, 0));
	rrset->rri_rdtype = ldns_rr_get_type(ldns_rr_list_rr(rrdata, 0));
	rrset->rri_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrdata, 0));

	debug2("ldns: got %u answers from DNS", rrset->rri_nrdatas);

	/* Check for authenticated data */
	if (ldns_pkt_ad(pkt)) {
		rrset->rri_flags |= RRSET_VALIDATED;
	} else { /* AD is not set, try autonomous validation */
		ldns_rr_list * trusted_keys = ldns_rr_list_new();

		debug2("ldns: trying to validate RRset");
		/* Get eventual sigs */
		rrsigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG,
		    LDNS_SECTION_ANSWER);

		rrset->rri_nsigs = ldns_rr_list_rr_count(rrsigs);
		debug2("ldns: got %u signature(s) (RRTYPE %u) from DNS",
		       rrset->rri_nsigs, LDNS_RR_TYPE_RRSIG);

		if ((err = ldns_verify_trusted(ldns_res, rrdata, rrsigs,
		     trusted_keys)) == LDNS_STATUS_OK) {
			rrset->rri_flags |= RRSET_VALIDATED;
			debug2("ldns: RRset is signed with a valid key");
		} else {
			debug2("ldns: RRset validation failed: %s",
			    ldns_get_errorstr_by_id(err));
		}

		ldns_rr_list_deep_free(trusted_keys);
	}

	/* allocate memory for answers */
	rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
	   sizeof(struct rdatainfo));

	if (rrset->rri_rdatas == NULL) {
		result = ERRSET_NOMEMORY;
		goto fail;
	}

	/* allocate memory for signatures */
	if (rrset->rri_nsigs > 0) {
		rrset->rri_sigs = calloc(rrset->rri_nsigs,
		    sizeof(struct rdatainfo));

		if (rrset->rri_sigs == NULL) {
			result = ERRSET_NOMEMORY;
			goto fail;
		}
	}

	/* copy answers & signatures */
	for (i=0, index_ans=0, index_sig=0; i< pkt->_header->_ancount; i++) {
		rdata = NULL;
		rr = ldns_rr_list_rr(ldns_pkt_answer(pkt), i);

		if (ldns_rr_get_class(rr) == rrset->rri_rdclass &&
		    ldns_rr_get_type(rr) == rrset->rri_rdtype) {
			rdata = &rrset->rri_rdatas[index_ans++];
		}

		if (rr->_rr_class == rrset->rri_rdclass &&
		    rr->_rr_type == LDNS_RR_TYPE_RRSIG &&
		    rrset->rri_sigs) {
			rdata = &rrset->rri_sigs[index_sig++];
		}

		if (rdata) {
			size_t rdata_offset = 0;

			rdata->rdi_length = 0;
			for (j=0; j< rr->_rd_count; j++) {
				rdata->rdi_length +=
				    ldns_rdf_size(ldns_rr_rdf(rr, j));
			}

			rdata->rdi_data = malloc(rdata->rdi_length);
			if (rdata->rdi_data == NULL) {
				result = ERRSET_NOMEMORY;
				goto fail;
			}

			/* Re-create the raw DNS RDATA */
			for (j=0; j< rr->_rd_count; j++) {
				len = ldns_rdf_size(ldns_rr_rdf(rr, j));
				memcpy(rdata->rdi_data + rdata_offset,
				       ldns_rdf_data(ldns_rr_rdf(rr, j)), len);
				rdata_offset += len;
			}
		}
	}

	*res = rrset;
	result = ERRSET_SUCCESS;

fail:
	/* freerrset(rrset); */
	ldns_rdf_deep_free(domain);
	ldns_pkt_free(pkt);
	ldns_rr_list_deep_free(rrsigs);
	ldns_rr_list_deep_free(rrdata);
	ldns_resolver_deep_free(ldns_res);

	return result;
}
Beispiel #13
0
/*
 * Parses data buffer to a query, finds the correct answer 
 * and calls the given function for every packet to send.
 */
void
handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
	enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*),
	void* userdata, FILE* verbose_out)
{
	ldns_status status;
	ldns_pkt *query_pkt = NULL;
	ldns_pkt *answer_pkt = NULL;
	struct reply_packet *p;
	ldns_rr *query_rr = NULL;
	uint8_t *outbuf = NULL;
	size_t answer_size = 0;
	struct entry* entry = NULL;
	ldns_rdf *stop_command = ldns_dname_new_frm_str("server.stop.");

	status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen);
	if (status != LDNS_STATUS_OK) {
		verbose(1, "Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
		ldns_rdf_free(stop_command);
		return;
	}
	
	query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
	verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count), (int)ldns_pkt_id(query_pkt), 
		(transport==transport_tcp)?"TCP":"UDP", (int)inlen);
	if(verbose_out) ldns_rr_print(verbose_out, query_rr);
	if(verbose_out) ldns_pkt_print(verbose_out, query_pkt);

	if (ldns_rr_get_type(query_rr) == LDNS_RR_TYPE_TXT &&
	    ldns_rr_get_class(query_rr) == LDNS_RR_CLASS_CH &&
	    ldns_dname_compare(ldns_rr_owner(query_rr), stop_command) == 0) {
		exit(0);
        }
	
	/* fill up answer packet */
	entry = find_match(entries, query_pkt, transport);
	if(!entry || !entry->reply_list) {
		verbose(1, "no answer packet for this query, no reply.\n");
		ldns_pkt_free(query_pkt);
		ldns_rdf_free(stop_command);
		return;
	}
	for(p = entry->reply_list; p; p = p->next)
	{
		verbose(3, "Answer pkt:\n");
		if (p->reply_from_hex) {
			/* try to parse the hex packet, if it can be
			 * parsed, we can use adjust rules. if not,
			 * send packet literally */
			status = ldns_buffer2pkt_wire(&answer_pkt, p->reply_from_hex);
			if (status == LDNS_STATUS_OK) {
				adjust_packet(entry, answer_pkt, query_pkt);
				if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt);
				status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
				verbose(2, "Answer packet size: %u bytes.\n", (unsigned int)answer_size);
				if (status != LDNS_STATUS_OK) {
					verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
					ldns_pkt_free(query_pkt);
					ldns_rdf_free(stop_command);
					return;
				}
				ldns_pkt_free(answer_pkt);
				answer_pkt = NULL;
			} else {
				verbose(3, "Could not parse hex data (%s), sending hex data directly.\n", ldns_get_errorstr_by_id(status));
				/* still try to adjust ID */
				answer_size = ldns_buffer_capacity(p->reply_from_hex);
				outbuf = LDNS_XMALLOC(uint8_t, answer_size);
				memcpy(outbuf, ldns_buffer_export(p->reply_from_hex), answer_size);
				if(entry->copy_id) {
					ldns_write_uint16(outbuf, 
						ldns_pkt_id(query_pkt));
				}
			}
		} else {
			answer_pkt = ldns_pkt_clone(p->reply);
			adjust_packet(entry, answer_pkt, query_pkt);
			if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt);
			status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
			verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)answer_size);
			if (status != LDNS_STATUS_OK) {
				verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
				ldns_pkt_free(query_pkt);
				ldns_rdf_free(stop_command);
				return;
			}
			ldns_pkt_free(answer_pkt);
			answer_pkt = NULL;
		}
		if(p->packet_sleep) {
			verbose(3, "sleeping for next packet %d secs\n", 
				p->packet_sleep);
#ifdef HAVE_SLEEP
			sleep(p->packet_sleep);
#else
			Sleep(p->packet_sleep * 1000);
#endif
			verbose(3, "wakeup for next packet "
				"(slept %d secs)\n", p->packet_sleep);
		}
		sendfunc(outbuf, answer_size, userdata);
		LDNS_FREE(outbuf);
		outbuf = NULL;
		answer_size = 0;
	}
	ldns_pkt_free(query_pkt);
	ldns_rdf_free(stop_command);
}
Beispiel #14
0
int output_cbor(iaddr from, iaddr to, uint8_t proto, unsigned flags, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char *payload, size_t payloadlen) {
    ldns_pkt *pkt = 0;
    ldns_status ldns_rc;

    if (!payload) {
        return DUMP_CBOR_EINVAL;
    }
    if (!payloadlen) {
        return DUMP_CBOR_EINVAL;
    }

/*    if (!cbor_stringrefs) {*/
/*        cbor_stringrefs = calloc(1, cbor_stringref_size);*/
/*    }*/
    if (!cbor_buf) {
        if (!(cbor_buf = calloc(1, cbor_size + cbor_reserve))) {
            return DUMP_CBOR_ENOMEM;
        }
    }
    if (cbor_flushed) {
        CborError cbor_err;

        cbor_encoder_init(&cbor_root, cbor_buf, cbor_size, 0);
/*        cbor_err = cbor_encode_tag(&cbor_root, 256);*/
/*        if (cbor_err == CborNoError)*/
        cbor_err = cbor_encoder_create_array(&cbor_root, &cbor_pkts, CborIndefiniteLength);
        if (cbor_err != CborNoError) {
            fprintf(stderr, "cbor init error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err));
            return DUMP_CBOR_ECBOR;
        }
        cbor_flushed = 0;
    }

    ldns_rc = ldns_wire2pkt(&pkt, payload, payloadlen);

    if (ldns_rc != LDNS_STATUS_OK) {
        fprintf(stderr, "ldns error [%d]: %s\n", ldns_rc, ldns_get_errorstr_by_id(ldns_rc));
        return DUMP_CBOR_ELDNS;
    }
    if (!pkt) {
        return DUMP_CBOR_ELDNS;
    }

    CborEncoder cbor, ip;
    CborError cbor_err = CborNoError;
    int should_flush = 0;

    cbor_err = append_cbor_map(&cbor_pkts, &cbor, CborIndefiniteLength, &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "dateSeconds", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_double(&cbor, (double)ts.tv_sec + ( (double)ts.tv_usec / 1000000 ), &should_flush);
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "dateNanoFractions", &should_flush);*/
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ts.tv_usec * 1000, &should_flush);*/

    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ip", &should_flush);
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, proto, &should_flush);*/
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "sourceIpAddress", &should_flush);*/
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, ia_str(from), &should_flush);*/
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "sourcePort", &should_flush);*/
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, sport, &should_flush);*/
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "destinationIpAddress", &should_flush);*/
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, ia_str(to), &should_flush);*/
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "destinationPort", &should_flush);*/
/*            if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, dport, &should_flush);*/

    if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &ip, CborIndefiniteLength, &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, proto, &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&ip, ia_str(from), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, sport, &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&ip, ia_str(to), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, dport, &should_flush);
    if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &ip, &should_flush);

    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ID", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_id(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QR", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_qr(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "Opcode", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_get_opcode(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "AA", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_aa(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "TC", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_tc(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RD", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_rd(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RA", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_ra(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "AD", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_ad(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "CD", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_cd(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RCODE", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_get_rcode(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QDCOUNT", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_qdcount(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ANCOUNT", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_ancount(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "NSCOUNT", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_nscount(pkt), &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ARCOUNT", &should_flush);
    if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_arcount(pkt), &should_flush);

    /* questionRRs */

    if (ldns_pkt_qdcount(pkt) > 0) {
        ldns_rr_list *list = ldns_pkt_question(pkt);
        ldns_rr *rr;
        size_t n, qdcount = ldns_pkt_qdcount(pkt);
        ldns_buffer *dname;
        char *dname_str;

        if (!list) {
            ldns_pkt_free(pkt);
            return DUMP_CBOR_ELDNS;
        }
        rr = ldns_rr_list_rr(list, 0);
        if (!rr) {
            ldns_pkt_free(pkt);
            return DUMP_CBOR_ELDNS;
        }

        if (!(dname = ldns_buffer_new(512))) {
            ldns_pkt_free(pkt);
            return DUMP_CBOR_ENOMEM;
        }
        if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) {
            ldns_buffer_free(dname);
            ldns_pkt_free(pkt);
            return DUMP_CBOR_ELDNS;
        }
        ldns_buffer_write_u8(dname, 0);
        if (!(dname_str = ldns_buffer_export(dname))) {
            ldns_buffer_free(dname);
            ldns_pkt_free(pkt);
            return DUMP_CBOR_ENOMEM;
        }

        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QNAME", &should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, dname_str, &should_flush);
        free(dname_str);
        ldns_buffer_free(dname);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QCLASS", &should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_rr_get_class(rr), &should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QTYPE", &should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_rr_get_type(rr), &should_flush);

        if (qdcount > 1) {
            CborEncoder queries;

            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "questionRRs", &should_flush);
            if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &queries, CborIndefiniteLength, &should_flush);
            for (n = 1; cbor_err == CborNoError && n < qdcount; n++) {
                CborEncoder query;

                rr = ldns_rr_list_rr(list, n);
                if (!rr) {
                    ldns_pkt_free(pkt);
                    return DUMP_CBOR_ELDNS;
                }

                if (!(dname = ldns_buffer_new(512))) {
                    ldns_pkt_free(pkt);
                    return DUMP_CBOR_ENOMEM;
                }
                if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) {
                    ldns_buffer_free(dname);
                    ldns_pkt_free(pkt);
                    return DUMP_CBOR_ELDNS;
                }
                ldns_buffer_write_u8(dname, 0);
                if (!(dname_str = ldns_buffer_export(dname))) {
                    ldns_buffer_free(dname);
                    ldns_pkt_free(pkt);
                    return DUMP_CBOR_ENOMEM;
                }

                if (cbor_err == CborNoError) cbor_err = append_cbor_map(&queries, &query, CborIndefiniteLength, &should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "NAME", &should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, dname_str, &should_flush);
                free(dname_str);
                ldns_buffer_free(dname);
                if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "CLASS", &should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&query, ldns_rr_get_class(rr), &should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "TYPE", &should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&query, ldns_rr_get_type(rr), &should_flush);
                if (cbor_err == CborNoError) cbor_err = close_cbor_container(&queries, &query, &should_flush);
            }
            if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &queries, &should_flush);
        }
    }

    /* answerRRs */

    if (ldns_pkt_ancount(pkt) > 0) {
        CborEncoder cbor_rrs;

        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "answerRRs", &should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush);
        cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_answer(pkt), ldns_pkt_ancount(pkt), &should_flush);
        if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush);
    }

    /* authorityRRs */

    if (ldns_pkt_nscount(pkt) > 0) {
        CborEncoder cbor_rrs;

        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "authorityRRs", &should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush);
        cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_authority(pkt), ldns_pkt_nscount(pkt), &should_flush);
        if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush);
    }

    /* additionalRRs */

    if (ldns_pkt_arcount(pkt) > 0) {
        CborEncoder cbor_rrs;

        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "additionalRRs", &should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush);
        cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_additional(pkt), ldns_pkt_arcount(pkt), &should_flush);
        if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush);
    }

    ldns_pkt_free(pkt);

    if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor_pkts, &cbor, &should_flush);

    if (cbor_err != CborNoError) {
        fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err));
        return DUMP_CBOR_ECBOR;
    }

    if (should_flush) {
        if ((cbor_err = cbor_encoder_close_container_checked(&cbor_root, &cbor_pkts)) != CborNoError) {
            fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err));
            return DUMP_CBOR_ECBOR;
        }

        fprintf(stderr, "cbor output: %lu bytes\n", cbor_encoder_get_buffer_size(&cbor_root, cbor_buf));

        cbor_flushed = 1;
        return DUMP_CBOR_FLUSH;
    }

    return DUMP_CBOR_OK;
}
Beispiel #15
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;
}
Beispiel #16
0
int
main(int argc, char **argv)
{
	/* arguments */
	int port;
	const char *zone_file;

	/* network */
	int sock;
	ssize_t nb;
	struct sockaddr addr_me;
	struct sockaddr addr_him;
	socklen_t hislen = (socklen_t) sizeof(addr_him);
	uint8_t inbuf[INBUF_SIZE];
	uint8_t *outbuf;

	/* dns */
	ldns_status status;
	ldns_pkt *query_pkt;
	ldns_pkt *answer_pkt;
	size_t answer_size;
	ldns_rr *query_rr;
	ldns_rr_list *answer_qr;
	ldns_rr_list *answer_an;
	ldns_rr_list *answer_ns;
	ldns_rr_list *answer_ad;
	ldns_rdf *origin = NULL;
	
	/* zone */
	ldns_zone *zone;
	int line_nr;
	FILE *zone_fp;
	
	/* use this to listen on specified interfaces later? */
	char *my_address = NULL;
		
	if (argc < 5) {
		usage(stderr);
		exit(EXIT_FAILURE);
	} else {
	    my_address = argv[1];
		port = atoi(argv[2]);
		if (port < 1) {
			usage(stderr);
			exit(EXIT_FAILURE);
		}
		if (ldns_str2rdf_dname(&origin, argv[3]) != LDNS_STATUS_OK) {
			fprintf(stderr, "Bad origin, not a correct domain name\n");
			usage(stderr);
			exit(EXIT_FAILURE);
		}
		zone_file = argv[4];
	}
	
	printf("Reading zone file %s\n", zone_file);
	zone_fp = fopen(zone_file, "r");
	if (!zone_fp) {
		fprintf(stderr, "Unable to open %s: %s\n", zone_file, strerror(errno));
		exit(EXIT_FAILURE);
	}
	
	line_nr = 0;
	status = ldns_zone_new_frm_fp_l(&zone, zone_fp, origin, 0, LDNS_RR_CLASS_IN, &line_nr);

	if (status != LDNS_STATUS_OK) {
		printf("Zone reader failed, aborting\n");
		exit(EXIT_FAILURE);
	} else {
		printf("Read %u resource records in zone file\n", (unsigned int) ldns_zone_rr_count(zone));
	}
	fclose(zone_fp);

	printf("Listening on port %d\n", port);
	sock =  socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) {
		fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno));
		exit(1);
	}
	memset(&addr_me, 0, sizeof(addr_me));

	/* bind: try all ports in that range */
	if (udp_bind(sock, port, my_address)) {
		fprintf(stderr, "%s: cannot bind(): %s\n", argv[0], strerror(errno));
		exit(errno);
	}

	/* Done. Now receive */
	while (1) {
		nb = recvfrom(sock, (void*)inbuf, INBUF_SIZE, 0, 
			&addr_him, &hislen);
		if (nb < 1) {
			fprintf(stderr, "%s: recvfrom(): %s\n",
			argv[0], strerror(errno));
			exit(1);
		}

		/*
		show(inbuf, nb, nn, hp, sp, ip, bp);
		*/
		printf("Got query of %u bytes\n", (unsigned int) nb);
		status = ldns_wire2pkt(&query_pkt, inbuf, (size_t) nb);
		if (status != LDNS_STATUS_OK) {
			printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
		} else {
			ldns_pkt_print(stdout, query_pkt);
		}

		query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
		printf("QUERY RR: \n");
		ldns_rr_print(stdout, query_rr);
		
		answer_qr = ldns_rr_list_new();
		ldns_rr_list_push_rr(answer_qr, ldns_rr_clone(query_rr));

		answer_an = get_rrset(zone, ldns_rr_owner(query_rr), ldns_rr_get_type(query_rr), ldns_rr_get_class(query_rr));
		answer_pkt = ldns_pkt_new();
		answer_ns = ldns_rr_list_new();
		answer_ad = ldns_rr_list_new();
		
		ldns_pkt_set_qr(answer_pkt, 1);
		ldns_pkt_set_aa(answer_pkt, 1);
		ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));

		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_QUESTION, answer_qr);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ANSWER, answer_an);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_AUTHORITY, answer_ns);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ADDITIONAL, answer_ad);

		status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
		
		printf("Answer packet size: %u bytes.\n", (unsigned int) answer_size);
		if (status != LDNS_STATUS_OK) {
			printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
		} else {
			nb = sendto(sock, (void*)outbuf, answer_size, 0, 
				&addr_him, hislen);
		}
		
		ldns_pkt_free(query_pkt);
		ldns_pkt_free(answer_pkt);
		LDNS_FREE(outbuf);
		ldns_rr_list_free(answer_qr);
		ldns_rr_list_free(answer_an);
		ldns_rr_list_free(answer_ns);
		ldns_rr_list_free(answer_ad);
	}
	
	/* No cleanup because of the infinite loop
	 *
	 * ldns_rdf_deep_free(origin);
	 * ldns_zone_deep_free(zone);
	 * return 0;
	 */
}
Beispiel #17
0
ldns_status
ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c, 
		int *line_nr)
{
	ldns_zone *newzone;
	ldns_rr *rr;
	uint32_t my_ttl = ttl;
	ldns_rr_class my_class = c;
	ldns_rr *last_rr = NULL;
	ldns_rdf *my_origin;
	ldns_rdf *my_prev;
	bool soa_seen = false; 	/* 2 soa are an error */
	ldns_status s;

	newzone = ldns_zone_new();
	my_origin = origin;
	my_ttl    = ttl;
	my_class  = c;
	
	if (origin) {
		my_origin = ldns_rdf_clone(origin);
		/* also set the prev */
		my_prev   = ldns_rdf_clone(origin);
	} else {
		my_origin = NULL;
		my_prev = NULL;
	}

	while(!feof(fp)) {
		s = ldns_rr_new_frm_fp_l(&rr, fp, &my_ttl, &my_origin, &my_prev, line_nr);
		switch (s) {
		case LDNS_STATUS_OK:
			if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
				if (soa_seen) {
					/* second SOA 
					 * just skip, maybe we want to say
					 * something??? */
					ldns_rr_free(rr);
					continue;
				}
				soa_seen = true;
				ldns_zone_set_soa(newzone, rr);
				/* set origin to soa if not specified */
				if (!my_origin) {
					my_origin = ldns_rdf_clone(ldns_rr_owner(rr));
				}
				continue;
			}
			
			/* a normal RR - as sofar the DNS is normal */
			last_rr = rr;
			if (!ldns_zone_push_rr(newzone, rr)) {
				if (my_origin) {
					ldns_rdf_deep_free(my_origin);
				}
				ldns_zone_free(newzone);
				return LDNS_STATUS_MEM_ERR;
			}

			/*my_origin = ldns_rr_owner(rr);*/
			my_ttl    = ldns_rr_ttl(rr);
			my_class  = ldns_rr_get_class(rr);
		case LDNS_STATUS_SYNTAX_EMPTY:
			/* empty line was seen */
		case LDNS_STATUS_SYNTAX_TTL:
			/* the function set the ttl */
			break;
		case LDNS_STATUS_SYNTAX_ORIGIN:
			/* the function set the origin */
			break;
		default:
			ldns_zone_free(newzone);
			return s;
		}
	}

	if (my_origin) {
		ldns_rdf_deep_free(my_origin);
	}
	if (my_prev) {
		ldns_rdf_deep_free(my_prev);
	}
	if (z) {
		*z = newzone;
	}

	return LDNS_STATUS_OK;
}
Beispiel #18
0
Datei: clib.c Projekt: crnt/zkdns
void zkdns_start(const char* my_address, int port, const char* my_zone)
{
	rp_handle = rp_initialize(my_zone);
	/* network */
	int sock;
	ssize_t nb;
	struct sockaddr addr_me;
	struct sockaddr addr_him;
	socklen_t hislen = (socklen_t) sizeof(addr_him);
	uint8_t inbuf[INBUF_SIZE];
	uint8_t *outbuf;

	/* dns */
	ldns_status status;
	ldns_pkt *query_pkt;
	ldns_pkt *answer_pkt;
	size_t answer_size;
	ldns_rr *query_rr;
	ldns_rr_list *answer_qr;
	ldns_rr_list *answer_an;
	ldns_rr_list *answer_ns;
	ldns_rr_list *answer_ad;
	ldns_rdf *origin = NULL;
	
	/* zone */
	ldns_zone *zone;
	int line_nr;
	FILE *zone_fp;
	
	if (ldns_str2rdf_dname(&origin, my_zone) != LDNS_STATUS_OK) {
		fprintf(stderr, "Bad origin, not a correct domain name\n");
		exit(EXIT_FAILURE);
	}

	printf("Listening on port %d\n", port);
	sock =  socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) {
		fprintf(stderr, "socket(): %s\n", strerror(errno));
		exit(1);
	}
	memset(&addr_me, 0, sizeof(addr_me));

	/* bind: try all ports in that range */
	if (udp_bind(sock, port, my_address)) {
		fprintf(stderr, "cannot bind(): %s\n", strerror(errno));
		exit(errno);
	}

	/* Done. Now receive */
	while (1) {
		nb = recvfrom(sock, (void*)inbuf, INBUF_SIZE, 0, 
			&addr_him, &hislen);
		if (nb < 1) {
			fprintf(stderr, "recvfrom(): %s\n",
			strerror(errno));
			exit(1);
		}

		/*
		show(inbuf, nb, nn, hp, sp, ip, bp);
		*/
		status = ldns_wire2pkt(&query_pkt, inbuf, (size_t) nb);
		if (status != LDNS_STATUS_OK) {
			printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
		}

		query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
		
		answer_qr = ldns_rr_list_new();
		ldns_rr_list_push_rr(answer_qr, ldns_rr_clone(query_rr));

		answer_an = get_rrset(zone, ldns_rr_owner(query_rr), ldns_rr_get_type(query_rr), ldns_rr_get_class(query_rr));
		answer_pkt = ldns_pkt_new();
		answer_ns = ldns_rr_list_new();
		answer_ad = ldns_rr_list_new();
		
		ldns_pkt_set_qr(answer_pkt, 1);
		ldns_pkt_set_aa(answer_pkt, 1);
		ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));

		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_QUESTION, answer_qr);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ANSWER, answer_an);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_AUTHORITY, answer_ns);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ADDITIONAL, answer_ad);

		status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
		
		if (status != LDNS_STATUS_OK) {
			printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
		} else {
			nb = sendto(sock, (void*)outbuf, answer_size, 0, 
				&addr_him, hislen);
		}
		
		ldns_pkt_free(query_pkt);
		ldns_pkt_free(answer_pkt);
		LDNS_FREE(outbuf);
		ldns_rr_list_free(answer_qr);
		ldns_rr_list_free(answer_an);
		ldns_rr_list_free(answer_ns);
		ldns_rr_list_free(answer_ad);
	}
	
	ldns_rdf_deep_free(origin);
	ldns_zone_deep_free(zone);
	rp_shutdown(rp_handle);
}
Beispiel #19
0
/** read root hints from file */
static int 
read_root_hints(struct iter_hints* hints, char* fname)
{
	int lineno = 0;
	uint32_t default_ttl = 0;
	ldns_rdf* origin = NULL;
	ldns_rdf* prev_rr = NULL;
	struct delegpt* dp;
	ldns_rr* rr = NULL;
	ldns_status status;
	uint16_t c = LDNS_RR_CLASS_IN;
	FILE* f = fopen(fname, "r");
	if(!f) {
		log_err("could not read root hints %s: %s",
			fname, strerror(errno));
		return 0;
	}
	dp = delegpt_create_mlc(NULL);
	if(!dp) {
		log_err("out of memory reading root hints");
		fclose(f);
		return 0;
	}
	verbose(VERB_QUERY, "Reading root hints from %s", fname);
	dp->has_parent_side_NS = 1;
	while(!feof(f)) {
		status = ldns_rr_new_frm_fp_l(&rr, f, 
			&default_ttl, &origin, &prev_rr, &lineno);
		if(status == LDNS_STATUS_SYNTAX_EMPTY ||
			status == LDNS_STATUS_SYNTAX_TTL ||
			status == LDNS_STATUS_SYNTAX_ORIGIN)
			continue;
		if(status != LDNS_STATUS_OK) {
			log_err("reading root hints %s %d: %s", fname,
				lineno, ldns_get_errorstr_by_id(status));
			goto stop_read;
		}
		if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) {
			if(!delegpt_add_ns_mlc(dp,
				ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0)) {
				log_err("out of memory reading root hints");
				goto stop_read;
			}
			c = ldns_rr_get_class(rr);
			if(!dp->name) {
				if(!delegpt_set_name_mlc(dp,
					ldns_rdf_data(ldns_rr_owner(rr)))){
					log_err("out of memory.");
					goto stop_read;
				}
			}
		} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_A) {
			struct sockaddr_in sa;
			socklen_t len = (socklen_t)sizeof(sa);
			memset(&sa, 0, len);
			sa.sin_family = AF_INET;
			sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
			memmove(&sa.sin_addr, 
				ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET_SIZE);
			if(!delegpt_add_target_mlc(dp,
					ldns_rdf_data(ldns_rr_owner(rr)),
					ldns_rdf_size(ldns_rr_owner(rr)),
					(struct sockaddr_storage*)&sa, len, 
					0, 0)) {
				log_err("out of memory reading root hints");
				goto stop_read;
			}
		} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) {
			struct sockaddr_in6 sa;
			socklen_t len = (socklen_t)sizeof(sa);
			memset(&sa, 0, len);
			sa.sin6_family = AF_INET6;
			sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
			memmove(&sa.sin6_addr, 
				ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET6_SIZE);
			if(!delegpt_add_target_mlc(dp,
					ldns_rdf_data(ldns_rr_owner(rr)),
					ldns_rdf_size(ldns_rr_owner(rr)),
					(struct sockaddr_storage*)&sa, len,
					0, 0)) {
				log_err("out of memory reading root hints");
				goto stop_read;
			}
		} else {
			log_warn("root hints %s:%d skipping type %d",
				fname, lineno, ldns_rr_get_type(rr));
		}

		ldns_rr_free(rr);
	}

	if (origin)
		ldns_rdf_deep_free(origin);
	if (prev_rr)
		ldns_rdf_deep_free(prev_rr);
	fclose(f);
	if(!dp->name) {
		log_warn("root hints %s: no NS content", fname);
		delegpt_free_mlc(dp);
		return 1;
	}
	if(!hints_insert(hints, c, dp, 0)) {
		return 0;
	}
	delegpt_log(VERB_QUERY, dp);
	return 1;

stop_read:
	if (origin)
		ldns_rdf_deep_free(origin);
	if (prev_rr)
		ldns_rdf_deep_free(prev_rr);
	delegpt_free_mlc(dp);
	fclose(f);
	return 0;
}