mirror of https://github.com/getdnsapi/getdns.git
Better servfail serving in getdns_query daemon
This commit is contained in:
parent
aedf4454f5
commit
2b81be8859
|
@ -2191,78 +2191,92 @@ void tcp_write_cb(void *userarg)
|
||||||
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
|
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(TRACE_DEBUG) && TRACE_DEBUG
|
||||||
|
#define SERVFAIL(error,r,msg,resp_p) do { \
|
||||||
|
if (r) DEBUG_TRACE("%s: %s\n", error, getdns_get_errorstr_by_id(r)); \
|
||||||
|
else DEBUG_TRACE("%s\n", error); \
|
||||||
|
servfail(msg, resp_p); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define SERVFAIL(error,r,msg,resp_p) servfail(msg, resp_p)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void servfail(dns_msg *msg, getdns_dict **resp_p)
|
||||||
|
{
|
||||||
|
getdns_dict *dict;
|
||||||
|
|
||||||
|
if (*resp_p)
|
||||||
|
getdns_dict_destroy(*resp_p);
|
||||||
|
if (!(*resp_p = getdns_dict_create()))
|
||||||
|
return;
|
||||||
|
if (!getdns_dict_get_dict(msg->query, "header", &dict))
|
||||||
|
getdns_dict_set_dict(*resp_p, "header", dict);
|
||||||
|
if (!getdns_dict_get_dict(msg->query, "question", &dict));
|
||||||
|
getdns_dict_set_dict(*resp_p, "question", dict);
|
||||||
|
(void) getdns_dict_set_int(
|
||||||
|
*resp_p, "/header/rcode", GETDNS_RCODE_SERVFAIL);
|
||||||
|
(void) getdns_dict_set_int(*resp_p, "/header/qr", 1);
|
||||||
|
(void) getdns_dict_set_int(*resp_p, "/header/ad", 0);
|
||||||
|
(void) getdns_dict_set_int(*resp_p, "/header/ra",
|
||||||
|
msg->rt == GETDNS_RESOLUTION_RECURSING ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
void request_cb(getdns_context *context, getdns_callback_type_t callback_type,
|
void request_cb(getdns_context *context, getdns_callback_type_t callback_type,
|
||||||
getdns_dict *response, void *userarg, getdns_transaction_t transaction_id)
|
getdns_dict *response, void *userarg, getdns_transaction_t transaction_id)
|
||||||
{
|
{
|
||||||
dns_msg *msg = (dns_msg *)userarg;
|
dns_msg *msg = (dns_msg *)userarg;
|
||||||
uint32_t qid;
|
uint32_t qid;
|
||||||
getdns_return_t r;
|
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||||
uint8_t buf[65536];
|
uint8_t buf[65536];
|
||||||
size_t len = sizeof(buf);
|
size_t len = sizeof(buf);
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
getdns_dict *dict;
|
|
||||||
|
|
||||||
DEBUG_TRACE("reply for: %p %"PRIu64" %d\n", msg, transaction_id, (int)callback_type);
|
DEBUG_TRACE("reply for: %p %"PRIu64" %d\n", msg, transaction_id, (int)callback_type);
|
||||||
if (callback_type != GETDNS_CALLBACK_COMPLETE) {
|
assert(msg);
|
||||||
if (response)
|
|
||||||
getdns_dict_destroy(response);
|
if (callback_type != GETDNS_CALLBACK_COMPLETE)
|
||||||
return;
|
SERVFAIL("Callback type not complete",
|
||||||
}
|
callback_type, msg, &response);
|
||||||
if ((r = getdns_dict_get_int(msg->query, "/header/id", &qid)))
|
|
||||||
fprintf(stderr, "Could not get qid: %s\n",
|
|
||||||
getdns_get_errorstr_by_id(r));
|
|
||||||
|
|
||||||
else if (!response)
|
else if (!response)
|
||||||
fprintf(stderr, "No response in request_cb\n");
|
SERVFAIL("Missing response", 0, msg, &response);
|
||||||
|
|
||||||
|
else if ((r = getdns_dict_get_int(msg->query, "/header/id", &qid)) ||
|
||||||
|
(r=getdns_dict_set_int(response,"/replies_tree/0/header/id",qid)))
|
||||||
|
SERVFAIL("Could not copy QID", r, msg, &response);
|
||||||
|
|
||||||
else if (getdns_dict_get_int(
|
else if (getdns_dict_get_int(
|
||||||
response, "/replies_tree/0/header/rcode", &n) && (
|
response, "/replies_tree/0/header/rcode", &n))
|
||||||
(r = getdns_dict_get_dict(msg->query, "header", &dict)) ||
|
SERVFAIL("No reply in replies tree", 0, msg, &response);
|
||||||
(r = getdns_dict_set_dict(response, "/replies_tree/0/header", dict)) ||
|
|
||||||
(r = getdns_dict_get_dict(msg->query, "question", &dict)) ||
|
|
||||||
(r = getdns_dict_set_dict(response, "/replies_tree/0/question", dict)) ||
|
|
||||||
(r = getdns_dict_set_int(response, "/replies_tree/0/header/rcode", GETDNS_RCODE_SERVFAIL)) ||
|
|
||||||
(r = getdns_dict_set_int(response, "/replies_tree/0/header/qr", 1)) ||
|
|
||||||
(r = getdns_dict_set_int(response, "/replies_tree/0/header/ra",
|
|
||||||
msg->rt == GETDNS_RESOLUTION_RECURSING ? 1 : 0)) ||
|
|
||||||
(r = getdns_dict_set_int(response, "/replies_tree/0/header/ad", 0))
|
|
||||||
))
|
|
||||||
fprintf(stderr, "Could not set answer rcode: %s\n",
|
|
||||||
getdns_get_errorstr_by_id(r));
|
|
||||||
|
|
||||||
else if (msg->rt == GETDNS_RESOLUTION_RECURSING &&
|
else if (msg->cd_bit != 1 && !getdns_dict_get_int(
|
||||||
(r = getdns_dict_set_int(response, "/replies_tree/0/header/cd", msg->cd_bit)))
|
response, "/replies_tree/0/dnssec_status", &n)
|
||||||
fprintf(stderr, "Could not set cd bit in answer: %s\n",
|
&& n == GETDNS_DNSSEC_BOGUS)
|
||||||
getdns_get_errorstr_by_id(r));
|
SERVFAIL("DNSSEC status was bogus", 0, msg, &response);
|
||||||
|
|
||||||
else if (msg->rt == GETDNS_RESOLUTION_RECURSING &&
|
else if ((r = getdns_dict_get_int(
|
||||||
( (!(r = getdns_dict_get_int(response, "/replies_tree/0/header/ra", &n)) && n == 0)
|
response, "/replies_tree/0/header/rcode", &n)))
|
||||||
|| (!(r = getdns_dict_get_int(response, "/replies_tree/0/header/rcode", &n)) && n == GETDNS_RCODE_SERVFAIL)
|
SERVFAIL("Could not get rcode from reply", r, msg, &response);
|
||||||
) &&
|
|
||||||
( (r = getdns_dict_set_int(response, "/replies_tree/0/header/rcode", GETDNS_RCODE_SERVFAIL))
|
|
||||||
|| (r = getdns_dict_set_int(response, "/replies_tree/0/header/rd", 1))
|
|
||||||
|| (r = getdns_dict_set_int(response, "/replies_tree/0/header/ra", 1))
|
|
||||||
|| (r = getdns_dict_get_dict(msg->query, "question", &dict))
|
|
||||||
|| (r = getdns_dict_set_dict(response, "/replies_tree/0/question", dict))
|
|
||||||
|| (r = getdns_dict_remove_name(response, "/replies_tree/0/answer"))
|
|
||||||
|| (r = getdns_dict_remove_name(response, "/replies_tree/0/authority"))
|
|
||||||
|| (r = getdns_dict_remove_name(response, "/replies_tree/0/additional"))
|
|
||||||
))
|
|
||||||
fprintf(stderr, "Could not create fake SERVFAIL packet: %s\n",
|
|
||||||
getdns_get_errorstr_by_id(r));
|
|
||||||
|
|
||||||
else if (!getdns_dict_get_int(
|
else if (n == GETDNS_RCODE_SERVFAIL)
|
||||||
response, "/replies_tree/0/dnssec_status", &n) &&
|
servfail(msg, &response);
|
||||||
n == GETDNS_DNSSEC_BOGUS &&
|
|
||||||
msg->cd_bit != 1 &&
|
|
||||||
(r = getdns_dict_set_int(response, "/replies_tree/0/header/rcode", GETDNS_RCODE_SERVFAIL)))
|
|
||||||
fprintf(stderr, "Could not set answer rcode: %s\n",
|
|
||||||
getdns_get_errorstr_by_id(r));
|
|
||||||
|
|
||||||
else if ((r = getdns_dict_set_int(response,
|
else if (msg->rt == GETDNS_RESOLUTION_STUB)
|
||||||
"/replies_tree/0/header/id", qid)))
|
; /* following checks are for RESOLUTION_RECURSING only */
|
||||||
fprintf(stderr, "Could not set qid: %s\n",
|
|
||||||
getdns_get_errorstr_by_id(r));
|
else if ((r = getdns_dict_set_int(
|
||||||
|
response, "/replies_tree/0/header/cd", msg->cd_bit)))
|
||||||
|
SERVFAIL("Could not copy CD bit", r, msg, &response);
|
||||||
|
|
||||||
|
else if ((r = getdns_dict_get_int(
|
||||||
|
response, "/replies_tree/0/header/ra", &n)))
|
||||||
|
SERVFAIL("Could not get RA bit from reply", r, msg, &response);
|
||||||
|
|
||||||
|
else if (n == 0)
|
||||||
|
SERVFAIL("Recursion not available", 0, msg, &response);
|
||||||
|
|
||||||
|
if (!response)
|
||||||
|
; /* No response, no reply */
|
||||||
|
|
||||||
else if ((r = getdns_msg_dict2wire_buf(response, buf, &len)))
|
else if ((r = getdns_msg_dict2wire_buf(response, buf, &len)))
|
||||||
fprintf(stderr, "Could not convert reply: %s\n",
|
fprintf(stderr, "Could not convert reply: %s\n",
|
||||||
|
|
Loading…
Reference in New Issue