diff --git a/src/Makefile.in b/src/Makefile.in index 381ab6bd..d6d90054 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -117,7 +117,7 @@ install: libgetdns.la $(INSTALL) -m 755 -d $(DESTDIR)$(includedir) $(INSTALL) -m 755 -d $(DESTDIR)$(includedir)/getdns $(INSTALL) -m 644 getdns/getdns.h $(DESTDIR)$(includedir)/getdns/getdns.h - $(INSTALL) -m 644 $(srcdir)/getdns/getdns_extra.h $(DESTDIR)$(includedir)/getdns/getdns_extra.h + $(INSTALL) -m 644 getdns/getdns_extra.h $(DESTDIR)$(includedir)/getdns/getdns_extra.h $(INSTALL) -m 755 -d $(DESTDIR)$(libdir) $(LIBTOOL) --mode=install cp libgetdns.la $(DESTDIR)$(libdir) if test $(have_libevent) = 1 ; then $(INSTALL) -m 644 $(srcdir)/getdns/getdns_ext_libevent.h $(DESTDIR)$(includedir)/getdns/ ; $(LIBTOOL) --mode=install cp $(EXTENSION_LIBEVENT_LIB) $(DESTDIR)$(libdir) ; fi diff --git a/src/request-internal.c b/src/request-internal.c index 30156724..3e87195d 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -114,6 +114,12 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, net_req->write_queue_tail = NULL; net_req->response_len = 0; + /* Some fields to record info for return_call_debugging */ + net_req->debug_start_time = 0; + net_req->debug_end_time = 0; + net_req->debug_tls_auth_status = 0; + net_req->debug_upstream = NULL; + net_req->wire_data_sz = wire_data_sz; if (max_query_sz) { /* first two bytes will contain query length (for tcp) */ @@ -372,7 +378,9 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, result->dnssec_return_only_secure = dnssec_return_only_secure; result->dnssec_return_validation_chain = dnssec_return_validation_chain; result->edns_cookies = edns_cookies; - + result->return_call_debugging + = is_extension_set(extensions, "return_call_debugging"); + /* will be set by caller */ result->user_pointer = NULL; result->user_callback = NULL; diff --git a/src/stub.c b/src/stub.c index 7bc30c2d..cafd1f85 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1276,6 +1276,8 @@ stub_udp_write_cb(void *userarg) dnsreq->loop, netreq->fd, dnsreq->context->timeout, getdns_eventloop_event_init(&netreq->event, netreq, stub_udp_read_cb, NULL, stub_timeout_cb)); + + netreq->debug_upstream = netreq->upstream; } /**************************/ @@ -1343,6 +1345,7 @@ stub_tcp_write_cb(void *userarg) dnsreq->loop, netreq->fd, dnsreq->context->timeout, getdns_eventloop_event_init(&netreq->event, netreq, stub_tcp_read_cb, NULL, stub_timeout_cb)); + netreq->debug_upstream = netreq->upstream; return; } } @@ -1477,6 +1480,9 @@ upstream_write_cb(void *userarg) return; default: + netreq->debug_upstream = netreq->upstream; + /* Need this because auth status is reset on connection clode */ + netreq->debug_tls_auth_status = netreq->upstream->tls_auth_failed; upstream->writes_done++; netreq->query_id = (uint16_t) q; /* Unqueue the netreq from the write_queue */ diff --git a/src/types-internal.h b/src/types-internal.h index 93b97973..0dbe7028 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -226,6 +226,12 @@ typedef struct getdns_network_req /* Network requests scheduled to write after me */ struct getdns_network_req *write_queue_tail; + /* Some fields to record info for return_call_debugging */ + uint64_t debug_start_time; + uint64_t debug_end_time; + size_t debug_tls_auth_status; + struct getdns_upstream *debug_upstream; + /* When more space is needed for the wire_data response than is * available in wire_data[], it will be allocated seperately. * response will then not point to wire_data anymore. @@ -237,6 +243,8 @@ typedef struct getdns_network_req size_t wire_data_sz; uint8_t wire_data[]; + + } getdns_network_req; /** @@ -262,6 +270,7 @@ typedef struct getdns_dns_req { int dnssec_return_only_secure; int dnssec_return_validation_chain; int edns_cookies; + int return_call_debugging; /* Internally used by return_validation_chain */ int dnssec_ok_checking_disabled; diff --git a/src/util-internal.c b/src/util-internal.c index d6e9299e..67a8c982 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -671,6 +671,33 @@ success: return result; } +getdns_dict * +_getdns_create_call_debugging_dict(getdns_context *context, + getdns_network_req *netreq, + getdns_dict *reply) { + getdns_dict *netreq_debug = getdns_dict_create_with_context(context); + getdns_bindata *qname = NULL; + uint32_t qtype; + getdns_dict *question = NULL; + getdns_dict_get_dict(reply, "question", &question); + getdns_dict_get_bindata(question, "qname", &qname); + getdns_dict_set_bindata(netreq_debug, "qname", qname); + getdns_dict_get_int(question, "qtype", &qtype); + getdns_dict_set_int(netreq_debug, "qtype", qtype); + getdns_dict *address_debug = getdns_dict_create_with_context(context); + _getdns_sockaddr_to_dict(context, &netreq->upstream->addr, &address_debug); + getdns_dict_set_dict(netreq_debug, "upstream", address_debug); + getdns_dict_set_int(netreq_debug, "transport", netreq->upstream->transport); + /* Only include the auth status if TLS was used */ + if (netreq->upstream->transport == GETDNS_TRANSPORT_TLS) { + getdns_dict_util_set_string(netreq_debug, "tls_auth", + netreq->debug_tls_auth_status == 0 ? "OK" : "FAILED"); + } + return netreq_debug; + +} + + getdns_dict * _getdns_create_getdns_response(getdns_dns_req *completed_request) { @@ -678,6 +705,7 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) getdns_list *just_addrs = NULL; getdns_list *replies_full; getdns_list *replies_tree; + getdns_list *call_debugging; getdns_network_req *netreq, **netreq_p; int rrsigs_in_answer = 0; getdns_dict *reply; @@ -713,6 +741,11 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) if (!(replies_tree = getdns_list_create_with_context(context))) goto error_free_replies_full; + if (completed_request->return_call_debugging) { + if (!(call_debugging = getdns_list_create_with_context(context))) + goto error_free_result; + } + for ( netreq_p = completed_request->netreqs ; (netreq = *netreq_p) ; netreq_p++) { @@ -769,6 +802,17 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) getdns_dict_destroy(reply); goto error; } + + if (completed_request->return_call_debugging) { + getdns_dict *netreq_debug; + if (!(netreq_debug = _getdns_create_call_debugging_dict(context, + netreq, reply))) { + goto error; + } + _getdns_list_append_dict(call_debugging, netreq_debug); + getdns_dict_destroy(netreq_debug); + } + getdns_dict_destroy(reply); /* buffer */ @@ -785,6 +829,11 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) goto error_free_replies_full; getdns_list_destroy(replies_full); + if (completed_request->return_call_debugging) { + if (getdns_dict_set_list(result, "return_call_debugging", call_debugging)) + goto error_free_call_debugging; + } + if (just_addrs && getdns_dict_set_list( result, GETDNS_STR_KEY_JUST_ADDRS, just_addrs)) goto error_free_result; @@ -806,6 +855,9 @@ error: getdns_list_destroy(replies_tree); error_free_replies_full: getdns_list_destroy(replies_full); +error_free_call_debugging: + if (completed_request->return_call_debugging) + getdns_list_destroy(call_debugging); error_free_result: getdns_list_destroy(just_addrs); getdns_dict_destroy(result);