nsprobe.c revision 02638c8b40cf967cf30956201d5fa333852d8730
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 2009-2013 Internet Systems Consortium, Inc. ("ISC")
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Permission to use, copy, modify, and/or distribute this software for any
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * purpose with or without fee is hereby granted, provided that the above
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * copyright notice and this permission notice appear in all copies.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic unsigned int outstanding_probes = 0;
d981ca645597116d227a48bf37cc5edc061c854dBob Halleytypedef enum {
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halley const char **qlabel;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* NS list */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long valid;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long ignore;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long nxdomain;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long othererr;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long multiplesoa;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long brokenanswer;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long lame;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long unknown;
d981ca645597116d227a48bf37cc5edc061c854dBob Halleystatic unsigned long number_of_domains = 0;
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrewsstatic unsigned long number_of_servers = 0;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic unsigned long multiple_error_domains = 0;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic const char *qlabels[] = {"www.", "ftp.", NULL};
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic isc_result_t probe_domain(struct probe_trans *trans);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic void reset_probe(struct probe_trans *trans);
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halleystatic isc_result_t fetch_nsaddress(struct probe_trans *trans);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic isc_result_t probe_name(struct probe_trans *trans,
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff/* Dump an rdataset for debug */
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graffprint_rdataset(dns_rdataset_t *rdataset, dns_name_t *owner) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews char t[4096];
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff printf("%.*s", (int)r.length, (char *)r.base);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff char t[4096];
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = dns_name_totext(name, ISC_TRUE, &target);
217f572018871cdf09db052a676b9933512cdbfaMark Andrews if (getnameinfo(&addr->type.sa, addr->length, buf, sizeof(buf),
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrewsctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp,
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
d981ca645597116d227a48bf37cc5edc061c854dBob Halleyctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
217f572018871cdf09db052a676b9933512cdbfaMark Andrews result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews * Common routine to make query data
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsmake_querymessage(dns_message_t *message, dns_name_t *qname0,
d981ca645597116d227a48bf37cc5edc061c854dBob Halley result = dns_message_gettempname(message, &qname);
217f572018871cdf09db052a676b9933512cdbfaMark Andrews result = dns_message_gettemprdataset(message, &qrdataset);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_message_addname(message, qname, DNS_SECTION_QUESTION);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff dns_message_puttemprdataset(message, &qrdataset);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff * Update statistics
6324997211a5e2d82528dcde98e8981190a35faeMichael Graffstatic inline void
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff unsigned int err_count = 0;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff /* Update per sever statistics */
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff for (pns = ISC_LIST_HEAD(trans->nslist); pns != NULL;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff for (server = ISC_LIST_HEAD(pns->servers); server != NULL;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff * Don't care about the result of A query if
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff * the answer to AAAA query was expected.
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews /* Update per domain statistics */
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley * We regard the domain as valid if and only if no authoritative server
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley * has a problem and at least one server is known to be valid.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (local_stat.valid > 0U && err_count == 0U) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * If the domain has no available server or all servers have the
bfb2a81b65579882a80855c279cedc45aebd62e8Mark Andrews * 'unknown' result, the domain's result is also regarded as unknown.
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews if (local_stat.valid == 0U && err_count == 0U) {
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews * Search for an existent name with an A RR
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews char buf[4096]; /* XXX ad-hoc constant, but should be enough */
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews result = isc_string_copy(buf, sizeof(buf), *trans->qlabel);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews result = isc_string_append(buf, sizeof(buf), trans->domain);
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews trans->qname = dns_fixedname_name(&trans->fixedname);
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews result = dns_name_fromtext(trans->qname, &b, dns_rootname,
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrencerequest_done(isc_task_t *task, isc_event_t *event) {
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews dns_clientreqevent_t *rev = (dns_clientreqevent_t *)event;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews REQUIRE(trans != NULL && trans->inuse == ISC_TRUE);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if ((rmessage->flags & DNS_MESSAGEFLAG_AA) == 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews else if (rmessage->rcode == dns_rcode_nxdomain)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews else if (rmessage->counts[DNS_SECTION_ANSWER] == 0) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* no error but empty answer */
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews /* Should chase the chain? */
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * Something unexpected happened: the response
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * contained a non-empty authoritative answer, but we
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * could not find an expected result.
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff } else if (rev->result == DNS_R_RECOVERABLE ||
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graff /* Broken response. Try identifying known cases. */
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff if (rmessage->counts[DNS_SECTION_ANSWER] > 0) {
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff * Check to see if the response has multiple
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff * CNAME RRs. Update the result code if so.
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff if (rmessage->counts[DNS_SECTION_AUTHORITY] > 0) {
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff * Check to see if the response has multiple
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff * SOA RRs. Update the result code if so.
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff fprintf(stderr, "unexpected result: %d (domain=%s, server=",
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff if (type == dns_rdatatype_a && *resultp == exist)
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff dns_message_reset(trans->rmessage, DNS_MESSAGE_INTENTPARSE);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff /* We've tried all addresses of all servers. */
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff if (type == dns_rdatatype_a && trans->qname_found) {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * If we've explored A RRs and found an existent
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * record, we can move to AAAA.
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff trans->current_ns = ISC_LIST_HEAD(trans->nslist);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * No server provided an existent A RR of this name.
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * Try next label.
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews * We've explored AAAA RRs or failed to find a valid
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews * query label. Wrap up the result and move to the
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews * next domain.
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrewsprobe_name(struct probe_trans *trans, dns_rdatatype_t type) {
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews REQUIRE(type == dns_rdatatype_a || type == dns_rdatatype_aaaa);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews for (server = ISC_LIST_HEAD(pns->servers); server != NULL;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews dns_message_reset(trans->qmessage, DNS_MESSAGE_INTENTRENDER);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews result = make_querymessage(trans->qmessage, trans->qname, type);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews result = dns_client_startrequest(client, trans->qmessage,
return (result);
NULL);
goto cleanup;
static isc_result_t
goto cleanup;
static isc_result_t
isc_buffer_t b;
char *cp;
return (ISC_R_NOMORE);
return (ISC_R_NOMEMORY);
goto cleanup;
goto cleanup;
return (ISC_R_SUCCESS);
return (result);
ISC_PLATFORM_NORETURN_PRE static void
usage(void) {
switch (ch) {
usage();
usage();
&timermgr);
if (error != 0) {
&servers);
if (argc == 0)
argv[0]);
for (i = 0; i < MAX_PROBES; i++) {
for (i = 0; i < MAX_PROBES; i++) {
for (i = 0; i < MAX_PROBES; i++) {