return result;
}
-static int put_answer(knot_pkt_t *pkt, struct kr_query *qry, knot_rrset_t *rr, bool use_nodata)
-{
- int ret = 0;
- if (!knot_rrset_empty(rr) || use_nodata) {
- /* Update packet question */
- if (!knot_dname_is_equal(knot_pkt_qname(pkt), rr->owner)) {
- kr_pkt_recycle(pkt);
- knot_pkt_put_question(pkt, qry->sname, qry->sclass, qry->stype);
- }
- if (!knot_rrset_empty(rr)) {
- /* Append to packet */
- ret = knot_pkt_put_rotate(pkt, KNOT_COMPR_HINT_QNAME, rr,
- qry->reorder, KNOT_PF_FREE);
- } else {
- /* Return empty answer if name exists, but type doesn't match */
- knot_wire_set_aa(pkt->wire);
- }
- } else {
- ret = kr_error(ENOENT);
- }
- /* Clear RR if failed */
- if (ret != 0) {
- knot_rrset_clear(rr, &pkt->mm);
- }
- return ret;
-}
-
-static int satisfy_reverse(/*const*/ struct hints_data *data,
- knot_pkt_t *pkt, struct kr_query *qry)
-{
- /* Find a matching name */
- pack_t *addr_set = kr_zonecut_find(&data->reverse_hints, qry->sname);
- if (!addr_set || addr_set->len == 0) {
- return kr_error(ENOENT);
- }
- knot_dname_t *qname = knot_dname_copy(qry->sname, &pkt->mm);
- knot_rrset_t rr;
- knot_rrset_init(&rr, qname, KNOT_RRTYPE_PTR, KNOT_CLASS_IN, data->ttl);
-
- /* Append address records from hints */
- uint8_t *addr = pack_last(*addr_set);
- if (addr != NULL) {
- size_t len = pack_obj_len(addr);
- void *addr_val = pack_obj_val(addr);
- knot_rrset_add_rdata(&rr, addr_val, len, &pkt->mm);
- }
-
- return put_answer(pkt, qry, &rr, data->use_nodata);
-}
-
-static int satisfy_forward(/*const*/ struct hints_data *data,
- knot_pkt_t *pkt, struct kr_query *qry)
-{
- /* Find a matching name */
- pack_t *addr_set = kr_zonecut_find(&data->hints, qry->sname);
- if (!addr_set || addr_set->len == 0) {
- return kr_error(ENOENT);
- }
- knot_dname_t *qname = knot_dname_copy(qry->sname, &pkt->mm);
- knot_rrset_t rr;
- knot_rrset_init(&rr, qname, qry->stype, qry->sclass, data->ttl);
-
- size_t family_len;
- switch (rr.type) {
- case KNOT_RRTYPE_A:
- family_len = sizeof(struct in_addr);
- break;
- case KNOT_RRTYPE_AAAA:
- family_len = sizeof(struct in6_addr);
- break;
- default:
- goto finish;
- };
-
- /* Append address records from hints */
- uint8_t *addr = pack_head(*addr_set);
- while (addr != pack_tail(*addr_set)) {
- size_t len = pack_obj_len(addr);
- void *addr_val = pack_obj_val(addr);
- if (len == family_len) {
- knot_rrset_add_rdata(&rr, addr_val, len, &pkt->mm);
- }
- addr = pack_obj_next(addr);
- }
-finish:
- return put_answer(pkt, qry, &rr, data->use_nodata);
-}
-
-static int query(kr_layer_t *ctx, knot_pkt_t *pkt)
-{
- struct kr_query *qry = ctx->req->current_query;
- if (!qry || (ctx->state & KR_STATE_FAIL)) {
- return ctx->state;
- }
-
- struct kr_module *module = ctx->api->data;
- struct hints_data *data = module->data;
- if (!data) { /* No valid file. */
- return ctx->state;
- }
- /* We can optimize for early return like this: */
- if (!data->use_nodata && qry->stype != KNOT_RRTYPE_A
- && qry->stype != KNOT_RRTYPE_AAAA && qry->stype != KNOT_RRTYPE_PTR) {
- return ctx->state;
- }
- /* FIXME: putting directly into packet breaks ordering in case the hint
- * is applied after a CNAME jump. */
- const bool is_rev =
+ knot_dname_in_bailiwick(qry->sname, (const uint8_t *)"\4arpa\0") > 0 &&
+ (knot_dname_in_bailiwick(qry->sname, (const uint8_t *)"\7in-addr\4arpa\0") > 0
+ || knot_dname_in_bailiwick(qry->sname, (const uint8_t *)"\3ip6\4arpa\0") > 0);
+ if (is_rev) {
- if (satisfy_reverse(data, pkt, qry) != 0)
- return ctx->state;
- } else {
- if (satisfy_forward(data, pkt, qry) != 0)
- return ctx->state;
- }
-
- VERBOSE_MSG(qry, "<= answered from hints\n");
- qry->flags.DNSSEC_WANT = false; /* Never authenticated */
- qry->flags.CACHED = true;
- qry->flags.NO_MINIMIZE = true;
- pkt->parsed = pkt->size;
- knot_wire_set_qr(pkt->wire);
- return KR_STATE_DONE;
-}
-
static int parse_addr_str(union kr_sockaddr *sa, const char *addr)
{
int family = strchr(addr, ':') ? AF_INET6 : AF_INET;