Example #1
0
/*! \brief Check if query fits the template requirements. */
static int template_match(int state, synth_template_t *tpl, knot_pkt_t *pkt, struct query_data *qdata)
{
	/* Parse address from query name. */
	char addr_str[SOCKADDR_STRLEN] = { '\0' };
	int ret = addr_parse(qdata, tpl, addr_str);
	if (ret != KNOT_EOK) {
		return state; /* Can't identify addr in QNAME, not applicable. */
	}

	/* Match against template netblock. */
	struct sockaddr_storage query_addr = { '\0' };
	int provided_af = tpl->subnet.ss.ss_family;
	ret = sockaddr_set(&query_addr, provided_af, addr_str, 0);
	if (ret == KNOT_EOK) {
		ret = netblock_match(&tpl->subnet, &query_addr);
	}
	if (ret != 0) {
		return state; /* Out of our netblock, not applicable. */
	}

	/* Check if the request is for an available query type. */
	uint16_t qtype = knot_pkt_qtype(qdata->query);
	switch (tpl->type) {
	case SYNTH_FORWARD:
		if (!query_satisfied_by_family(qtype, provided_af)) {
			qdata->rcode = KNOT_RCODE_NOERROR;
			return NODATA;
		}
		break;
	case SYNTH_REVERSE:
		if (qtype != KNOT_RRTYPE_PTR && qtype != KNOT_RRTYPE_ANY) {
			qdata->rcode = KNOT_RCODE_NOERROR;
			return NODATA;
		}
		break;
	default:
		break;
	}

	/* Synthetise record from template. */
	knot_rrset_t *rr = synth_rr(addr_str, tpl, pkt, qdata);
	if (rr == NULL) {
		qdata->rcode = KNOT_RCODE_SERVFAIL;
		return ERROR;
	}

	/* Insert synthetic response into packet. */
	if (knot_pkt_put(pkt, 0, rr, KNOT_PF_FREE) != KNOT_EOK) {
		return ERROR;
	}

	/* Authoritative response. */
	knot_wire_set_aa(pkt->wire);

	return HIT;
}
Example #2
0
static int rosedb_synth(knot_pkt_t *pkt, const knot_dname_t *key, struct iter *it,
                        struct query_data *qdata)
{
	struct entry entry;
	int ret = KNOT_EOK;
	uint16_t qtype = knot_pkt_qtype(qdata->query);

	/* Answer section. */
	while (ret == KNOT_EOK) {
		if (cache_iter_val(it, &entry) == 0) {
			ret = rosedb_synth_rr(pkt, &entry, qtype);
		}
		if (cache_iter_next(it) != 0) {
			break;
		}
	}

	/* Authority section. */
	knot_pkt_begin(pkt, KNOT_AUTHORITY);
	
	/* Not found (zone cut if records exist). */
	ret = cache_iter_begin(it, key);
	while (ret == KNOT_EOK) {
		if (cache_iter_val(it, &entry) == 0) {
			ret = rosedb_synth_rr(pkt, &entry, KNOT_RRTYPE_NS);
			ret = rosedb_synth_rr(pkt, &entry, KNOT_RRTYPE_SOA);
		}
		if (cache_iter_next(it) != 0) {
			break;
		}
	}

	/* Our response is authoritative. */
	if (knot_wire_get_nscount(pkt->wire) > 0) {
		knot_wire_set_aa(pkt->wire);
		if (knot_wire_get_ancount(pkt->wire) == 0) {
			qdata->rcode = KNOT_RCODE_NXDOMAIN;
		}
	}

	/* Send message to syslog. */
	struct sockaddr_storage syslog_addr;
	if (sockaddr_set(&syslog_addr, AF_INET, entry.syslog_ip, DEFAULT_PORT) == KNOT_EOK) {
		int sock = net_unbound_socket(AF_INET, &syslog_addr);
		if (sock > 0) {
			rosedb_send_log(sock, (struct sockaddr *)&syslog_addr, pkt,
			                entry.threat_code, qdata);
			close(sock);
		}
	}

	return ret;
}
Example #3
0
/*! \brief Create zone query packet. */
static knot_pkt_t *zone_query(const zone_t *zone, uint16_t pkt_type, knot_mm_t *mm)
{
	/* Determine query type and opcode. */
	uint16_t query_type = KNOT_RRTYPE_SOA;
	uint16_t opcode = KNOT_OPCODE_QUERY;
	switch(pkt_type) {
	case KNOT_QUERY_AXFR: query_type = KNOT_RRTYPE_AXFR; break;
	case KNOT_QUERY_IXFR: query_type = KNOT_RRTYPE_IXFR; break;
	case KNOT_QUERY_NOTIFY: opcode = KNOT_OPCODE_NOTIFY; break;
	}

	knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, mm);
	if (pkt == NULL) {
		return NULL;
	}

	knot_wire_set_id(pkt->wire, dnssec_random_uint16_t());
	knot_wire_set_opcode(pkt->wire, opcode);
	if (pkt_type == KNOT_QUERY_NOTIFY) {
		knot_wire_set_aa(pkt->wire);
	}

	knot_pkt_put_question(pkt, zone->name, KNOT_CLASS_IN, query_type);

	/* Put current SOA (optional). */
	zone_contents_t *contents = zone->contents;
	if (pkt_type == KNOT_QUERY_IXFR) {  /* RFC1995, SOA in AUTHORITY. */
		knot_pkt_begin(pkt, KNOT_AUTHORITY);
		knot_rrset_t soa_rr = node_rrset(contents->apex, KNOT_RRTYPE_SOA);
		knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, &soa_rr, 0);
	} else if (pkt_type == KNOT_QUERY_NOTIFY) { /* RFC1996, SOA in ANSWER. */
		knot_pkt_begin(pkt, KNOT_ANSWER);
		knot_rrset_t soa_rr = node_rrset(contents->apex, KNOT_RRTYPE_SOA);
		knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, &soa_rr, 0);
	}

	return pkt;
}