diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index ed135979d5..81c641dd84 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -352,6 +352,8 @@ struct dns_ednsopt { unsigned char *value; }; +typedef void (*dns_message_cb_t)(void *arg, isc_result_t result); + /*** *** Functions ***/ @@ -1327,6 +1329,26 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view); *\li #DNS_R_TSIGVERIFYFAILURE - The TSIG failed to verify */ +isc_result_t +dns_message_checksig_async(dns_message_t *msg, dns_view_t *view, + isc_loop_t *loop, dns_message_cb_t cb, void *cbarg); +/*%< + * Run dns_message_checksig() in an offloaded thread and return its result + * using the 'cb' callback function, running on the 'loop'. + * + * Requires: + * + *\li msg is a valid parsed message. + *\li view is a valid view or NULL. + *\li loop is a valid loop. + *\li cb is a valid callback function. + * + * Returns: + * + *\li #DNS_R_WAIT + * + */ + void dns_message_resetsig(dns_message_t *msg); /*%< diff --git a/lib/dns/message.c b/lib/dns/message.c index e99fd5edc9..bba68efe54 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -180,6 +181,18 @@ msgblock_allocate(isc_mem_t *, unsigned int, unsigned int); #define msgblock_get(block, type) \ ((type *)msgblock_internalget(block, sizeof(type))) +/* + * A context type to pass information when checking a message signature + * asynchronously. + */ +typedef struct checksig_ctx { + dns_message_t *msg; + dns_view_t *view; + dns_message_cb_t cb; + void *cbarg; + isc_result_t result; +} checksig_ctx_t; + /* * This function differs from public dns_message_puttemprdataset() that it * requires the *rdatasetp to be associated, and it will disassociate and @@ -3205,6 +3218,47 @@ dns_message_dumpsig(dns_message_t *msg, char *txt1) { } #endif /* ifdef SKAN_MSG_DEBUG */ +static void +checksig_run(void *arg) { + checksig_ctx_t *chsigctx = arg; + + chsigctx->result = dns_message_checksig(chsigctx->msg, chsigctx->view); +} + +static void +checksig_cb(void *arg) { + checksig_ctx_t *chsigctx = arg; + dns_message_t *msg = chsigctx->msg; + + chsigctx->cb(chsigctx->cbarg, chsigctx->result); + + dns_view_detach(&chsigctx->view); + isc_mem_put(msg->mctx, chsigctx, sizeof(*chsigctx)); + dns_message_detach(&msg); +} + +isc_result_t +dns_message_checksig_async(dns_message_t *msg, dns_view_t *view, + isc_loop_t *loop, dns_message_cb_t cb, void *cbarg) { + REQUIRE(DNS_MESSAGE_VALID(msg)); + REQUIRE(view != NULL); + REQUIRE(loop != NULL); + REQUIRE(cb != NULL); + + checksig_ctx_t *chsigctx = isc_mem_get(msg->mctx, sizeof(*chsigctx)); + *chsigctx = (checksig_ctx_t){ + .cb = cb, + .cbarg = cbarg, + .result = ISC_R_UNSET, + }; + dns_message_attach(msg, &chsigctx->msg); + dns_view_attach(view, &chsigctx->view); + + isc_work_enqueue(loop, checksig_run, checksig_cb, chsigctx); + + return (DNS_R_WAIT); +} + isc_result_t dns_message_checksig(dns_message_t *msg, dns_view_t *view) { isc_buffer_t b, msgb;