int axfr_query_process(knot_pkt_t *pkt, struct query_data *qdata) { if (pkt == NULL || qdata == NULL) { return KNOT_NS_PROC_FAIL; } int ret = KNOT_EOK; struct timeval now = {0}; /* If AXFR is disabled, respond with NOTIMPL. */ if (qdata->param->proc_flags & NS_QUERY_NO_AXFR) { qdata->rcode = KNOT_RCODE_NOTIMPL; return KNOT_NS_PROC_FAIL; } /* Initialize on first call. */ if (qdata->ext == NULL) { ret = axfr_query_init(qdata); if (ret != KNOT_EOK) { AXFROUT_LOG(LOG_ERR, "failed to start (%s)", knot_strerror(ret)); return KNOT_NS_PROC_FAIL; } else { AXFROUT_LOG(LOG_INFO, "started, serial %u", zone_contents_serial(qdata->zone->contents)); } } /* Reserve space for TSIG. */ knot_pkt_reserve(pkt, knot_tsig_wire_maxsize(qdata->sign.tsig_key)); /* Answer current packet (or continue). */ struct axfr_proc *axfr = (struct axfr_proc *)qdata->ext; ret = xfr_process_list(pkt, &axfr_process_node_tree, qdata); switch(ret) { case KNOT_ESPACE: /* Couldn't write more, send packet and continue. */ return KNOT_NS_PROC_FULL; /* Check for more. */ case KNOT_EOK: /* Last response. */ gettimeofday(&now, NULL); AXFROUT_LOG(LOG_INFO, "finished, %.02f seconds, %u messages, %u bytes", time_diff(&axfr->proc.tstamp, &now) / 1000.0, axfr->proc.npkts, axfr->proc.nbytes); return KNOT_NS_PROC_DONE; break; default: /* Generic error. */ AXFROUT_LOG(LOG_ERR, "failed (%s)", knot_strerror(ret)); return KNOT_NS_PROC_FAIL; } }
int notify_process_query(knot_pkt_t *pkt, struct query_data *qdata) { if (pkt == NULL || qdata == NULL) { return KNOT_STATE_FAIL; } /* Validate notification query. */ int state = notify_check_query(qdata); if (state == KNOT_STATE_FAIL) { switch (qdata->rcode) { case KNOT_RCODE_NOTAUTH: /* Not authoritative or ACL check failed. */ NOTIFY_QLOG(LOG_NOTICE, "unauthorized request"); break; case KNOT_RCODE_FORMERR: /* Silently ignore bad queries. */ default: break; } return state; } /* Reserve space for TSIG. */ knot_pkt_reserve(pkt, knot_tsig_wire_maxsize(&qdata->sign.tsig_key)); /* SOA RR in answer may be included, recover serial. */ const knot_pktsection_t *answer = knot_pkt_section(qdata->query, KNOT_ANSWER); if (answer->count > 0) { const knot_rrset_t *soa = knot_pkt_rr(answer, 0); if (soa->type == KNOT_RRTYPE_SOA) { uint32_t serial = knot_soa_serial(&soa->rrs); NOTIFY_QLOG(LOG_INFO, "received serial %u", serial); } else { /* Complain, but accept N/A record. */ NOTIFY_QLOG(LOG_NOTICE, "received, bad record in answer section"); } } else { NOTIFY_QLOG(LOG_INFO, "received, doesn't have SOA"); } /* Incoming NOTIFY expires REFRESH timer and renews EXPIRE timer. */ zone_t *zone = (zone_t *)qdata->zone; zone_set_preferred_master(zone, qdata->param->remote); zone_events_schedule(zone, ZONE_EVENT_REFRESH, ZONE_EVENT_NOW); int ret = zone_events_write_persistent(zone); if (ret != KNOT_EOK) { return KNOT_STATE_FAIL; } return KNOT_STATE_DONE; }
int sign_packet(knot_pkt_t *pkt, sign_context_t *sign_ctx) { if (pkt == NULL || sign_ctx == NULL || sign_ctx->digest == NULL) { return KNOT_EINVAL; } uint8_t *wire = pkt->wire; size_t *wire_size = &pkt->size; size_t max_size = pkt->max_size; knot_pkt_reserve(pkt, knot_tsig_wire_maxsize(sign_ctx->tsig_key)); return knot_tsig_sign(wire, wire_size, max_size, NULL, 0, sign_ctx->digest, &sign_ctx->digest_size, sign_ctx->tsig_key, 0, 0); }
int main(int argc, char *argv[]) { plan(25); /* Create memory pool context. */ int ret = 0; knot_mm_t mm; mm_ctx_mempool(&mm, MM_DEFAULT_BLKSIZE); /* Create names and data. */ knot_dname_t* dnames[NAMECOUNT] = {0}; knot_rrset_t* rrsets[NAMECOUNT] = {0}; for (unsigned i = 0; i < NAMECOUNT; ++i) { dnames[i] = knot_dname_from_str_alloc(g_names[i]); } uint8_t *edns_str = (uint8_t *)"ab"; /* Create OPT RR. */ knot_rrset_t opt_rr; ret = knot_edns_init(&opt_rr, 1024, 0, 0, &mm); if (ret != KNOT_EOK) { skip_block(25, "Failed to initialize OPT RR."); return 0; } /* Add NSID */ ret = knot_edns_add_option(&opt_rr, KNOT_EDNS_OPTION_NSID, strlen((char *)edns_str), edns_str, &mm); if (ret != KNOT_EOK) { knot_rrset_clear(&opt_rr, &mm); skip_block(25, "Failed to add NSID to OPT RR."); return 0; } /* * Packet writer tests. */ /* Create packet. */ knot_pkt_t *out = knot_pkt_new(NULL, MM_DEFAULT_BLKSIZE, &mm); ok(out != NULL, "pkt: new"); /* Mark as response (not part of the test). */ knot_wire_set_qr(out->wire); /* Secure packet. */ const char *tsig_secret = "abcd"; knot_tsig_key_t tsig_key; tsig_key.algorithm = DNSSEC_TSIG_HMAC_MD5; tsig_key.name = dnames[0]; tsig_key.secret.data = (uint8_t *)strdup(tsig_secret); tsig_key.secret.size = strlen(tsig_secret); ret = knot_pkt_reserve(out, knot_tsig_wire_maxsize(&tsig_key)); ok(ret == KNOT_EOK, "pkt: set TSIG key"); /* Write question. */ ret = knot_pkt_put_question(out, dnames[0], KNOT_CLASS_IN, KNOT_RRTYPE_A); ok(ret == KNOT_EOK, "pkt: put question"); /* Add OPT to packet (empty NSID). */ ret = knot_pkt_reserve(out, knot_edns_wire_size(&opt_rr)); ok(ret == KNOT_EOK, "pkt: reserve OPT RR"); /* Begin ANSWER section. */ ret = knot_pkt_begin(out, KNOT_ANSWER); ok(ret == KNOT_EOK, "pkt: begin ANSWER"); /* Write ANSWER section. */ rrsets[0] = knot_rrset_new(dnames[0], KNOT_RRTYPE_A, KNOT_CLASS_IN, NULL); knot_dname_free(&dnames[0], NULL); knot_rrset_add_rdata(rrsets[0], RDVAL(0), RDLEN(0), TTL, NULL); ret = knot_pkt_put(out, KNOT_COMPR_HINT_QNAME, rrsets[0], 0); ok(ret == KNOT_EOK, "pkt: write ANSWER"); /* Begin AUTHORITY. */ ret = knot_pkt_begin(out, KNOT_AUTHORITY); ok(ret == KNOT_EOK, "pkt: begin AUTHORITY"); /* Write rest to AUTHORITY. */ ret = KNOT_EOK; for (unsigned i = 1; i < NAMECOUNT; ++i) { rrsets[i] = knot_rrset_new(dnames[i], KNOT_RRTYPE_NS, KNOT_CLASS_IN, NULL); knot_dname_free(&dnames[i], NULL); knot_rrset_add_rdata(rrsets[i], RDVAL(i), RDLEN(i), TTL, NULL); ret |= knot_pkt_put(out, KNOT_COMPR_HINT_NONE, rrsets[i], 0); } ok(ret == KNOT_EOK, "pkt: write AUTHORITY(%u)", NAMECOUNT - 1); /* Begin ADDITIONALS */ ret = knot_pkt_begin(out, KNOT_ADDITIONAL); ok(ret == KNOT_EOK, "pkt: begin ADDITIONALS"); /* Encode OPT RR. */ ret = knot_pkt_put(out, KNOT_COMPR_HINT_NONE, &opt_rr, 0); ok(ret == KNOT_EOK, "pkt: write OPT RR"); /* * Packet reader tests. */ /* Create new packet from query packet. */ knot_pkt_t *in = knot_pkt_new(out->wire, out->size, &out->mm); ok(in != NULL, "pkt: create packet for parsing"); /* Read packet header. */ ret = knot_pkt_parse_question(in); ok(ret == KNOT_EOK, "pkt: read header"); /* Read packet payload. */ ret = knot_pkt_parse_payload(in, 0); ok(ret == KNOT_EOK, "pkt: read payload"); /* Compare parsed packet to written packet. */ packet_match(in, out); /* * Copied packet tests. */ knot_pkt_t *copy = knot_pkt_new(NULL, in->max_size, &in->mm); ret = knot_pkt_copy(copy, in); ok(ret == KNOT_EOK, "pkt: create packet copy"); /* Compare copied packet to original. */ packet_match(in, copy); /* Free packets. */ knot_pkt_free(©); knot_pkt_free(&out); knot_pkt_free(&in); ok(in == NULL && out == NULL && copy == NULL, "pkt: free"); /* Free extra data. */ for (unsigned i = 0; i < NAMECOUNT; ++i) { knot_rrset_free(&rrsets[i], NULL); } free(tsig_key.secret.data); mp_delete((struct mempool *)mm.ctx); return 0; }