unsigned int is_dc; /* dns cache */
unsigned int is_rblc; /* cleared dnsbl caches */
unsigned int is_rblh; /* dnsbl cache hit */
+
+ /* dns counters */
+ uint64_t is_dnssucc; /* successful dns response */
+ uint64_t is_dnsfail; /* failure dns response */
+ uint64_t is_dnsretry; /* number of retries sent */
+ uint64_t is_dnstimeout; /* number of timed out queries */
+
+ /* dns rcode counters */
+ uint64_t is_dnsnoerr;
+ uint64_t is_dnsfmterr;
+ uint64_t is_dnsservfail;
+ uint64_t is_dnsnameerr;
+ uint64_t is_dnsnierr;
+ uint64_t is_dnsreferr;
};
struct Counter
return ret;
}
+static int
+http_stats_dns(struct MHD_Connection *connection, const char *url,
+ const char *method, const char *version, const char *upload_data,
+ size_t *upload_data_size)
+{
+ json_t *root = json_object();
+
+ json_object_set_new(root, "succ", json_integer(ServerStats.is_dnssucc));
+ json_object_set_new(root, "fail", json_integer(ServerStats.is_dnsfail));
+ json_object_set_new(root, "retry", json_integer(ServerStats.is_dnsretry));
+ json_object_set_new(root, "timeout", json_integer(ServerStats.is_dnstimeout));
+
+ json_object_set_new(root, "rcnoerror", json_integer(ServerStats.is_dnsnoerr));
+ json_object_set_new(root, "rcfmterr", json_integer(ServerStats.is_dnsfmterr));
+ json_object_set_new(root, "rcservfail", json_integer(ServerStats.is_dnsservfail));
+ json_object_set_new(root, "rcnameerr", json_integer(ServerStats.is_dnsnameerr));
+ json_object_set_new(root, "rcni", json_integer(ServerStats.is_dnsnierr));
+ json_object_set_new(root, "rcrefused", json_integer(ServerStats.is_dnsreferr));
+
+ const char *dump = json_dumps(root, JSON_INDENT(2));
+
+ json_decref(root);
+ root = NULL;
+
+ if (dump == NULL)
+ return MHD_NO;
+
+ struct MHD_Response *response = MHD_create_response_from_buffer(strlen(dump), (void *) dump, MHD_RESPMEM_MUST_FREE);
+ int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
+ MHD_destroy_response(response);
+
+ return ret;
+}
+
static struct HttpResource stats_http_memory =
{
.method = MHD_HTTP_METHOD_GET,
.handler = http_stats_ltrace
};
+static struct HttpResource stats_http_dns =
+{
+ .method = MHD_HTTP_METHOD_GET,
+ .url = "/stats/dns",
+ .handler = http_stats_dns
+};
+
#endif
#endif
httpd_register(&stats_http_messages);
httpd_register(&stats_http_listeners);
httpd_register(&stats_http_ltrace);
+ httpd_register(&stats_http_dns);
#endif
#endif
}
httpd_unregister(&stats_http_messages);
httpd_unregister(&stats_http_listeners);
httpd_unregister(&stats_http_ltrace);
+ httpd_unregister(&stats_http_dns);
#endif
#endif
}
sendto_one(source_p, ":%s %d %s t :accepts %u refused %u",
me.name, RPL_STATSDEBUG, source_p->name, sp->is_ac, sp->is_ref);
- sendto_one(source_p, ":%s %d %s t :dns cache %u dnsbl cache hit (clear) %u dnsbl cache hit %u",
+ sendto_one(source_p, ":%s %d %s t :dnsbl cache %u dnsbl cache hit (clear) %u dnsbl cache hit %u",
me.name, RPL_STATSDEBUG, source_p->name, sp->is_dc, sp->is_rblc, sp->is_rblh);
+ sendto_one(source_p, ":%s %d %s t :dns rcode noerror %lu fmterr %lu servfail %lu nameerr %lu ni %lu refused %lu",
+ me.name, RPL_STATSDEBUG, source_p->name, sp->is_dnsnoerr, sp->is_dnsfmterr, sp->is_dnsservfail, sp->is_dnsnameerr, sp->is_dnsnierr, sp->is_dnsreferr);
+ sendto_one(source_p, ":%s %d %s t :dns query succ %lu fail %lu retry %lu timeout %lu",
+ me.name, RPL_STATSDEBUG, source_p->name, sp->is_dnssucc, sp->is_dnsfail, sp->is_dnsretry, sp->is_dnstimeout);
sendto_one(source_p, ":%s %d %s t :unknown commands %u prefixes %u",
me.name, RPL_STATSDEBUG, source_p->name, sp->is_unco, sp->is_unpf);
sendto_one(source_p, ":%s %d %s t :nick collisions %u unknown closes %u",
{
++request->ns->failure_count;
request->timeout += request->timeout;
+ ++ServerStats.is_dnstimeout;
resend_query(request); /* this may delete the request if there are no more retries */
}
else
unlink_request(request);
(*request->callback)(request->callback_ctx, NULL, NULL);
rem_request(request);
+ ++ServerStats.is_dnsfail;
return;
}
+ ++ServerStats.is_dnsretry;
+
/* move query to the end of the list */
assert(dlinkFind(&request_list_timeout, request));
dlinkDelete(&request->tnode, &request_list_timeout);
return 1;
}
+static void
+record_rcode_stats(unsigned int rcode)
+{
+ switch (rcode)
+ {
+ case NO_ERRORS:
+ ++ServerStats.is_dnsnoerr;
+ break;
+ case FMTERROR:
+ ++ServerStats.is_dnsfmterr;
+ break;
+ case SERVFAIL:
+ ++ServerStats.is_dnsservfail;
+ break;
+ case NXDOMAIN:
+ ++ServerStats.is_dnsnameerr;
+ break;
+ case NOTIMP:
+ ++ServerStats.is_dnsnierr;
+ break;
+ case REFUSED:
+ ++ServerStats.is_dnsreferr;
+ break;
+ }
+}
+
/*
* res_readreply - read a dns reply from the nameserver and process it.
*/
server->failure_count += 3;
}
+ record_rcode_stats(header->rcode);
+
if (header->rcode != NO_ERRORS || header->ancount == 0)
{
switch (header->rcode)
++server->failure_count;
resend_query(request);
break;
+ case NO_ERRORS:
case NXDOMAIN:
/* this is a good answer, domain doesn't exist */
server->failure_count /= 4;
- /* FALLTHROUGH */
+ ++ServerStats.is_dnssucc;
+ goto unlink;
default:
/*
* If a bad error was returned, stop here and don't
* send any more (no retries granted).
*/
+ ++ServerStats.is_dnsfail;
+ unlink:
unlink_request(request);
(*request->callback)(request->callback_ctx, NULL, NULL);
rem_request(request);
* don't bother trying again, the client address doesn't resolve
*/
++server->failure_count;
+ ++ServerStats.is_dnsfail;
unlink_request(request);
(*request->callback)(request->callback_ctx, NULL, NULL);
rem_request(request);
}
server->failure_count /= 4;
+ ++ServerStats.is_dnssucc;
}
void