nsprobe.c revision 02638c8b40cf967cf30956201d5fa333852d8730
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews/*
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 2009-2013 Internet Systems Consortium, Inc. ("ISC")
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews *
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 *
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 Andrews */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews/* $Id$ */
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff
dfea6f0eaadb9287cfcdc1566ac2f997af1b075aBob Halley#include <config.h>
dfea6f0eaadb9287cfcdc1566ac2f997af1b075aBob Halley
3761c433912beabe43abeed2c3513b6201c59f64Mark Andrews#include <sys/types.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <sys/socket.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <stdio.h>
b57bb9136af9f1bf84378f1f11f0efc55c52c628Mark Andrews#include <stdlib.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <string.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <unistd.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <netdb.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <isc/app.h>
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence#include <isc/buffer.h>
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence#include <isc/lib.h>
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence#include <isc/mem.h>
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence#include <isc/socket.h>
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence#include <isc/sockaddr.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <isc/string.h>
d981ca645597116d227a48bf37cc5edc061c854dBob Halley#include <isc/task.h>
d981ca645597116d227a48bf37cc5edc061c854dBob Halley#include <isc/timer.h>
d981ca645597116d227a48bf37cc5edc061c854dBob Halley#include <isc/util.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews#include <dns/client.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <dns/fixedname.h>
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson#include <dns/lib.h>
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson#include <dns/message.h>
d981ca645597116d227a48bf37cc5edc061c854dBob Halley#include <dns/name.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <dns/rdata.h>
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews#include <dns/rdataset.h>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#include <dns/rdatastruct.h>
d981ca645597116d227a48bf37cc5edc061c854dBob Halley#include <dns/rdatatype.h>
d981ca645597116d227a48bf37cc5edc061c854dBob Halley#include <dns/result.h>
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define MAX_PROBES 1000
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic dns_client_t *client = NULL;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic isc_task_t *probe_task = NULL;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic isc_appctx_t *actx = NULL;
d981ca645597116d227a48bf37cc5edc061c854dBob Halleystatic isc_mem_t *mctx = NULL;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic unsigned int outstanding_probes = 0;
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrewsconst char *cacheserver = "127.0.0.1";
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic FILE *fp;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
d981ca645597116d227a48bf37cc5edc061c854dBob Halleytypedef enum {
d981ca645597116d227a48bf37cc5edc061c854dBob Halley none,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews exist,
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews nxdomain,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews othererr,
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews multiplesoa,
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews multiplecname,
d981ca645597116d227a48bf37cc5edc061c854dBob Halley brokenanswer,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews lame,
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews timedout,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews notype,
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews unexpected
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews} query_result_t;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrewsstruct server {
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews ISC_LINK(struct server) link;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_sockaddr_t address;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews query_result_t result_a;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley query_result_t result_aaaa;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews};
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstruct probe_ns {
d981ca645597116d227a48bf37cc5edc061c854dBob Halley ISC_LINK(struct probe_ns) link;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
d981ca645597116d227a48bf37cc5edc061c854dBob Halley dns_fixedname_t fixedname;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley dns_name_t *name;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley struct server *current_server;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley ISC_LIST(struct server) servers;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley};
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halley
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halleystruct probe_trans {
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halley isc_boolean_t inuse;
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halley char *domain;
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halley dns_fixedname_t fixedname;
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halley dns_name_t *qname;
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halley const char **qlabel;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_boolean_t qname_found;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_clientrestrans_t *resid;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_message_t *qmessage;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_message_t *rmessage;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_clientreqtrans_t *reqid;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* NS list */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews struct probe_ns *current_ns;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ISC_LIST(struct probe_ns) nslist;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews};
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstruct lcl_stat {
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 multiplecname;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long brokenanswer;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long lame;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned long unknown;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews} server_stat, domain_stat;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
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 isc_boolean_t debug_mode = ISC_FALSE;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic int verbose_level = 0;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic const char *qlabels[] = {"www.", "ftp.", NULL};
d981ca645597116d227a48bf37cc5edc061c854dBob Halleystatic struct probe_trans probes[MAX_PROBES];
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
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,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_rdatatype_t type);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff/* Dump an rdataset for debug */
6324997211a5e2d82528dcde98e8981190a35faeMichael Graffstatic isc_result_t
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graffprint_rdataset(dns_rdataset_t *rdataset, dns_name_t *owner) {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff isc_buffer_t target;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff isc_result_t result;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff isc_region_t r;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews char t[4096];
217f572018871cdf09db052a676b9933512cdbfaMark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (!debug_mode)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (ISC_R_SUCCESS);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews isc_buffer_init(&target, t, sizeof(t));
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (!dns_rdataset_isassociated(rdataset))
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff return (ISC_R_SUCCESS);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff &target);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (result);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff isc_buffer_usedregion(&target, &r);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff printf("%.*s", (int)r.length, (char *)r.base);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff
b57bb9136af9f1bf84378f1f11f0efc55c52c628Mark Andrews return (ISC_R_SUCCESS);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews}
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff
6324997211a5e2d82528dcde98e8981190a35faeMichael Graffstatic isc_result_t
6324997211a5e2d82528dcde98e8981190a35faeMichael Graffprint_name(dns_name_t *name) {
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff isc_result_t result;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff isc_buffer_t target;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff isc_region_t r;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff char t[4096];
89bc8a8876a94d840aa034afb8905d4735b3af7eMichael Graff
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_buffer_init(&target, t, sizeof(t));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = dns_name_totext(name, ISC_TRUE, &target);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff if (result == ISC_R_SUCCESS) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_buffer_usedregion(&target, &r);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews printf("%.*s", (int)r.length, (char *)r.base);
217f572018871cdf09db052a676b9933512cdbfaMark Andrews } else
217f572018871cdf09db052a676b9933512cdbfaMark Andrews printf("(invalid name)");
217f572018871cdf09db052a676b9933512cdbfaMark Andrews
217f572018871cdf09db052a676b9933512cdbfaMark Andrews return (result);
217f572018871cdf09db052a676b9933512cdbfaMark Andrews}
217f572018871cdf09db052a676b9933512cdbfaMark Andrews
217f572018871cdf09db052a676b9933512cdbfaMark Andrewsstatic isc_result_t
217f572018871cdf09db052a676b9933512cdbfaMark Andrewsprint_address(FILE *fp, isc_sockaddr_t *addr) {
217f572018871cdf09db052a676b9933512cdbfaMark Andrews char buf[NI_MAXHOST];
217f572018871cdf09db052a676b9933512cdbfaMark Andrews
217f572018871cdf09db052a676b9933512cdbfaMark Andrews if (getnameinfo(&addr->type.sa, addr->length, buf, sizeof(buf),
217f572018871cdf09db052a676b9933512cdbfaMark Andrews NULL, 0, NI_NUMERICHOST) == 0) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews fprintf(fp, "%s", buf);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews } else {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews fprintf(fp, "(invalid address)");
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (ISC_R_SUCCESS);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews}
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
217f572018871cdf09db052a676b9933512cdbfaMark Andrewsstatic void
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrewsctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp,
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews isc_timermgr_t **timermgrp)
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews{
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (*taskmgrp != NULL)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_taskmgr_destroy(taskmgrp);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (*timermgrp != NULL)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_timermgr_destroy(timermgrp);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (*socketmgrp != NULL)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_socketmgr_destroy(socketmgrp);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews if (*actxp != NULL)
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews isc_appctx_destroy(actxp);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews if (*mctxp != NULL)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_mem_destroy(mctxp);
611a37e72daff14666f7dcc781674775e0c8e5eaMark Andrews}
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic isc_result_t
d981ca645597116d227a48bf37cc5edc061c854dBob Halleyctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
7c89c5c5747cacffddc6dfff44bbb5010d1beb3fMark Andrews isc_timermgr_t **timermgrp)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews{
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_result_t result;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = isc_mem_create(0, 0, mctxp);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews if (result != ISC_R_SUCCESS)
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews goto fail;
217f572018871cdf09db052a676b9933512cdbfaMark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = isc_appctx_create(*mctxp, actxp);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS)
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews goto fail;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley
217f572018871cdf09db052a676b9933512cdbfaMark Andrews result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp);
217f572018871cdf09db052a676b9933512cdbfaMark Andrews if (result != ISC_R_SUCCESS)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews goto fail;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS)
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews goto fail;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews if (result != ISC_R_SUCCESS)
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews goto fail;
611a37e72daff14666f7dcc781674775e0c8e5eaMark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (ISC_R_SUCCESS);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews fail:
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews return (result);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews}
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews/*
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews * Common routine to make query data
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic isc_result_t
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsmake_querymessage(dns_message_t *message, dns_name_t *qname0,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_rdatatype_t rdtype)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews{
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_name_t *qname = NULL;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_rdataset_t *qrdataset = NULL;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_result_t result;
217f572018871cdf09db052a676b9933512cdbfaMark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews message->opcode = dns_opcode_query;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews message->rdclass = dns_rdataclass_in;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
d981ca645597116d227a48bf37cc5edc061c854dBob Halley result = dns_message_gettempname(message, &qname);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (result != ISC_R_SUCCESS)
4529cdaedaf1a0a5f8ff89aeca510b7a4475446cBob Halley goto cleanup;
217f572018871cdf09db052a676b9933512cdbfaMark Andrews
217f572018871cdf09db052a676b9933512cdbfaMark Andrews result = dns_message_gettemprdataset(message, &qrdataset);
217f572018871cdf09db052a676b9933512cdbfaMark Andrews if (result != ISC_R_SUCCESS)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews goto cleanup;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
4529cdaedaf1a0a5f8ff89aeca510b7a4475446cBob Halley dns_name_init(qname, NULL);
217f572018871cdf09db052a676b9933512cdbfaMark Andrews dns_name_clone(qname0, qname);
217f572018871cdf09db052a676b9933512cdbfaMark Andrews dns_rdataset_init(qrdataset);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ISC_LIST_APPEND(qname->list, qrdataset, link);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_message_addname(message, qname, DNS_SECTION_QUESTION);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff return (ISC_R_SUCCESS);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff cleanup:
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff if (qname != NULL)
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff dns_message_puttempname(message, &qname);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff if (qrdataset != NULL)
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff dns_message_puttemprdataset(message, &qrdataset);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff return (result);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff}
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff/*
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff * Update statistics
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff */
6324997211a5e2d82528dcde98e8981190a35faeMichael Graffstatic inline void
6324997211a5e2d82528dcde98e8981190a35faeMichael Graffincrement_entry(unsigned long *entryp) {
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff (*entryp)++;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff INSIST(*entryp != 0U); /* check overflow */
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff}
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graffstatic void
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graffupdate_stat(struct probe_trans *trans) {
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff struct probe_ns *pns;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff struct server *server;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff struct lcl_stat local_stat;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff unsigned int err_count = 0;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff const char *stattype;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff increment_entry(&number_of_domains);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff memset(&local_stat, 0, sizeof(local_stat));
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff /* Update per sever statistics */
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff for (pns = ISC_LIST_HEAD(trans->nslist); pns != NULL;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff pns = ISC_LIST_NEXT(pns, link)) {
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff for (server = ISC_LIST_HEAD(pns->servers); server != NULL;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff server = ISC_LIST_NEXT(server, link)) {
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff increment_entry(&number_of_servers);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff if (server->result_aaaa == exist ||
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff server->result_aaaa == notype) {
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff /*
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff * Don't care about the result of A query if
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff * the answer to AAAA query was expected.
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff */
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff stattype = "valid";
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff increment_entry(&server_stat.valid);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff increment_entry(&local_stat.valid);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff } else if (server->result_a == exist) {
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff switch (server->result_aaaa) {
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff case exist:
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff case notype:
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff stattype = "valid";
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff increment_entry(&server_stat.valid);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff increment_entry(&local_stat.valid);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff break;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff case timedout:
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff stattype = "ignore";
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff increment_entry(&server_stat.ignore);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff increment_entry(&local_stat.ignore);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff break;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff case nxdomain:
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff stattype = "nxdomain";
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&server_stat.nxdomain);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley increment_entry(&local_stat.nxdomain);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews break;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews case othererr:
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews stattype = "othererr";
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&server_stat.othererr);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&local_stat.othererr);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews break;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews case multiplesoa:
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews stattype = "multiplesoa";
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews increment_entry(&server_stat.multiplesoa);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&local_stat.multiplesoa);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews break;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews case multiplecname:
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews stattype = "multiplecname";
d981ca645597116d227a48bf37cc5edc061c854dBob Halley increment_entry(&server_stat.multiplecname);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&local_stat.multiplecname);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews break;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews case brokenanswer:
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews stattype = "brokenanswer";
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&server_stat.brokenanswer);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&local_stat.brokenanswer);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley break;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews case lame:
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews stattype = "lame";
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&server_stat.lame);
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews increment_entry(&local_stat.lame);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews break;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews default:
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews stattype = "unknown";
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&server_stat.unknown);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&local_stat.unknown);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews break;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews } else {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews stattype = "unknown";
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&server_stat.unknown);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley increment_entry(&local_stat.unknown);
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (verbose_level > 1 ||
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews (verbose_level == 1 &&
d981ca645597116d227a48bf37cc5edc061c854dBob Halley strcmp(stattype, "valid") != 0 &&
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews strcmp(stattype, "unknown") != 0)) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews print_name(pns->name);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews putchar('(');
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews print_address(stdout, &server->address);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley printf(") for %s:%s\n", trans->domain,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews stattype);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews /* Update per domain statistics */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (local_stat.ignore > 0U) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (verbose_level > 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews printf("%s:ignore\n", trans->domain);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&domain_stat.ignore);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews err_count++;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews }
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence if (local_stat.nxdomain > 0U) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (verbose_level > 0)
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews printf("%s:nxdomain\n", trans->domain);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&domain_stat.nxdomain);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews err_count++;
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (local_stat.othererr > 0U) {
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence if (verbose_level > 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews printf("%s:othererr\n", trans->domain);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&domain_stat.othererr);
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews err_count++;
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence }
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence if (local_stat.multiplesoa > 0U) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (verbose_level > 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews printf("%s:multiplesoa\n", trans->domain);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&domain_stat.multiplesoa);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews err_count++;
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews }
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence if (local_stat.multiplecname > 0U) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (verbose_level > 0)
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence printf("%s:multiplecname\n", trans->domain);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews increment_entry(&domain_stat.multiplecname);
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence err_count++;
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (local_stat.brokenanswer > 0U) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (verbose_level > 0)
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff printf("%s:brokenanswer\n", trans->domain);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff increment_entry(&domain_stat.brokenanswer);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff err_count++;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff }
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff if (local_stat.lame > 0U) {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff if (verbose_level > 0)
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff printf("%s:lame\n", trans->domain);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff increment_entry(&domain_stat.lame);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff err_count++;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff }
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff if (err_count > 1U)
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff increment_entry(&multiple_error_domains);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /*
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.
d981ca645597116d227a48bf37cc5edc061c854dBob Halley */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (local_stat.valid > 0U && err_count == 0U) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (verbose_level > 1)
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews printf("%s:valid\n", trans->domain);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff increment_entry(&domain_stat.valid);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff }
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /*
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 */
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews if (local_stat.valid == 0U && err_count == 0U) {
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews if (verbose_level > 1)
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews printf("%s:unknown\n", trans->domain);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff increment_entry(&domain_stat.unknown);
217f572018871cdf09db052a676b9933512cdbfaMark Andrews }
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews}
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews/*
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews * Search for an existent name with an A RR
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence */
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graffstatic isc_result_t
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graffset_nextqname(struct probe_trans *trans) {
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews isc_result_t result;
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley size_t domainlen;
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence isc_buffer_t b;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews char buf[4096]; /* XXX ad-hoc constant, but should be enough */
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews if (*trans->qlabel == NULL)
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews return (ISC_R_NOMORE);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews result = isc_string_copy(buf, sizeof(buf), *trans->qlabel);
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews if (result != ISC_R_SUCCESS)
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews return (result);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews result = isc_string_append(buf, sizeof(buf), trans->domain);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews if (result != ISC_R_SUCCESS)
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews return (result);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews domainlen = strlen(buf);
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews isc_buffer_init(&b, buf, domainlen);
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews isc_buffer_add(&b, domainlen);
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews dns_fixedname_init(&trans->fixedname);
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews trans->qname = dns_fixedname_name(&trans->fixedname);
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews result = dns_name_fromtext(trans->qname, &b, dns_rootname,
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews 0, NULL);
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews trans->qlabel++;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley return (result);
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence}
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrewsstatic void
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrencerequest_done(isc_task_t *task, isc_event_t *event) {
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews struct probe_trans *trans = event->ev_arg;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews dns_clientreqevent_t *rev = (dns_clientreqevent_t *)event;
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence dns_message_t *rmessage;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews struct probe_ns *pns;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews struct server *server;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews isc_result_t result;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews query_result_t *resultp;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_name_t *name;
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley dns_rdataset_t *rdataset;
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence dns_rdatatype_t type;
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews REQUIRE(task == probe_task);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews REQUIRE(trans != NULL && trans->inuse == ISC_TRUE);
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence rmessage = rev->rmessage;
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence REQUIRE(rmessage == trans->rmessage);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley INSIST(outstanding_probes > 0);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
d981ca645597116d227a48bf37cc5edc061c854dBob Halley server = trans->current_ns->current_server;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews INSIST(server != NULL);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
d981ca645597116d227a48bf37cc5edc061c854dBob Halley if (server->result_a == none) {
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence type = dns_rdatatype_a;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews resultp = &server->result_a;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley } else {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews resultp = &server->result_aaaa;
53bd3f325f898b6892742ce928da3daa02ba0eddDavid Lawrence type = dns_rdatatype_aaaa;
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews }
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (rev->result == ISC_R_SUCCESS) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if ((rmessage->flags & DNS_MESSAGEFLAG_AA) == 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews *resultp = lame;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews else if (rmessage->rcode == dns_rcode_nxdomain)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews *resultp = nxdomain;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews else if (rmessage->rcode != dns_rcode_noerror)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews *resultp = othererr;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews else if (rmessage->counts[DNS_SECTION_ANSWER] == 0) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* no error but empty answer */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews *resultp = notype;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews } else {
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews result = dns_message_firstname(rmessage,
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff DNS_SECTION_ANSWER);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff while (result == ISC_R_SUCCESS) {
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff name = NULL;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff dns_message_currentname(rmessage,
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff DNS_SECTION_ANSWER,
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews &name);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews for (rdataset = ISC_LIST_HEAD(name->list);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews rdataset != NULL;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews rdataset = ISC_LIST_NEXT(rdataset,
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews link)) {
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews (void)print_rdataset(rdataset, name);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews if (rdataset->type ==
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews dns_rdatatype_cname ||
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews rdataset->type ==
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews dns_rdatatype_dname) {
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews /* Should chase the chain? */
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews *resultp = exist;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews goto found;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews } else if (rdataset->type == type) {
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews *resultp = exist;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews goto found;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley }
d981ca645597116d227a48bf37cc5edc061c854dBob Halley }
d981ca645597116d227a48bf37cc5edc061c854dBob Halley result = dns_message_nextname(rmessage,
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halley DNS_SECTION_ANSWER);
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halley }
477437f48d24f46c2c2f5271c53e759f0b4ca1caBob Halley
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews /*
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.
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff */
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews *resultp = unexpected;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff }
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff } else if (rev->result == DNS_R_RECOVERABLE ||
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graff rev->result == DNS_R_BADLABELTYPE) {
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graff /* Broken response. Try identifying known cases. */
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff *resultp = brokenanswer;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff if (rmessage->counts[DNS_SECTION_ANSWER] > 0) {
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff result = dns_message_firstname(rmessage,
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff DNS_SECTION_ANSWER);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff while (result == ISC_R_SUCCESS) {
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff /*
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff * Check to see if the response has multiple
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff * CNAME RRs. Update the result code if so.
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff */
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff name = NULL;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff dns_message_currentname(rmessage,
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff DNS_SECTION_ANSWER,
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff &name);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff for (rdataset = ISC_LIST_HEAD(name->list);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff rdataset != NULL;
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff rdataset = ISC_LIST_NEXT(rdataset,
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff link)) {
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graff if (rdataset->type ==
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff dns_rdatatype_cname &&
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff dns_rdataset_count(rdataset) > 1) {
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff *resultp = multiplecname;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff goto found;
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff }
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff }
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff result = dns_message_nextname(rmessage,
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff DNS_SECTION_ANSWER);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff }
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff }
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff if (rmessage->counts[DNS_SECTION_AUTHORITY] > 0) {
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff result = dns_message_firstname(rmessage,
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff DNS_SECTION_AUTHORITY);
8de9b6a1767498243d06359830d7840fdd10e49fMichael Graff while (result == ISC_R_SUCCESS) {
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff /*
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff * Check to see if the response has multiple
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff * SOA RRs. Update the result code if so.
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff */
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff name = NULL;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff dns_message_currentname(rmessage,
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff DNS_SECTION_AUTHORITY,
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff &name);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff for (rdataset = ISC_LIST_HEAD(name->list);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff rdataset != NULL;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff rdataset = ISC_LIST_NEXT(rdataset,
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff link)) {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff if (rdataset->type ==
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff dns_rdatatype_soa &&
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff dns_rdataset_count(rdataset) > 1) {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff *resultp = multiplesoa;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff goto found;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff }
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff }
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff result = dns_message_nextname(rmessage,
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff DNS_SECTION_AUTHORITY);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff }
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff }
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff } else if (rev->result == ISC_R_TIMEDOUT)
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff *resultp = timedout;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff else {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff fprintf(stderr, "unexpected result: %d (domain=%s, server=",
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff rev->result, trans->domain);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff print_address(stderr, &server->address);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff fputc('\n', stderr);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff *resultp = unexpected;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff }
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff found:
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff INSIST(*resultp != none);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff if (type == dns_rdatatype_a && *resultp == exist)
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff trans->qname_found = ISC_TRUE;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff dns_client_destroyreqtrans(&trans->reqid);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff isc_event_free(&event);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff dns_message_reset(trans->rmessage, DNS_MESSAGE_INTENTPARSE);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff result = probe_name(trans, type);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff if (result == ISC_R_NOMORE) {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff /* We've tried all addresses of all servers. */
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff if (type == dns_rdatatype_a && trans->qname_found) {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff /*
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * If we've explored A RRs and found an existent
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * record, we can move to AAAA.
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff */
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff trans->current_ns = ISC_LIST_HEAD(trans->nslist);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff probe_name(trans, dns_rdatatype_aaaa);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff result = ISC_R_SUCCESS;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff } else if (type == dns_rdatatype_a) {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff /*
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * No server provided an existent A RR of this name.
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff * Try next label.
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff */
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff dns_fixedname_invalidate(&trans->fixedname);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff trans->qname = NULL;
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff result = set_nextqname(trans);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff if (result == ISC_R_SUCCESS) {
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff trans->current_ns =
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff ISC_LIST_HEAD(trans->nslist);
6324997211a5e2d82528dcde98e8981190a35faeMichael Graff for (pns = trans->current_ns; pns != NULL;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews pns = ISC_LIST_NEXT(pns, link)) {
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews for (server = ISC_LIST_HEAD(pns->servers);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews server != NULL;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews server = ISC_LIST_NEXT(server,
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews link)) {
d981ca645597116d227a48bf37cc5edc061c854dBob Halley INSIST(server->result_aaaa ==
d981ca645597116d227a48bf37cc5edc061c854dBob Halley none);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews server->result_a = none;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews }
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews }
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews result = probe_name(trans, dns_rdatatype_a);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews }
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews }
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews if (result != ISC_R_SUCCESS) {
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews /*
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.
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews */
217f572018871cdf09db052a676b9933512cdbfaMark Andrews reset_probe(trans);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews }
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews } else if (result != ISC_R_SUCCESS)
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews reset_probe(trans); /* XXX */
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews}
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrewsstatic isc_result_t
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrewsprobe_name(struct probe_trans *trans, dns_rdatatype_t type) {
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews isc_result_t result;
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews struct probe_ns *pns;
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews struct server *server;
217f572018871cdf09db052a676b9933512cdbfaMark Andrews
d981ca645597116d227a48bf37cc5edc061c854dBob Halley REQUIRE(trans->reqid == NULL);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews REQUIRE(type == dns_rdatatype_a || type == dns_rdatatype_aaaa);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews for (pns = trans->current_ns; pns != NULL;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews pns = ISC_LIST_NEXT(pns, link)) {
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews for (server = ISC_LIST_HEAD(pns->servers); server != NULL;
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews server = ISC_LIST_NEXT(server, link)) {
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews if ((type == dns_rdatatype_a &&
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews server->result_a == none) ||
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews (type == dns_rdatatype_aaaa &&
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews server->result_aaaa == none)) {
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews pns->current_server = server;
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews goto found;
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews }
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews }
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews }
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews found:
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews trans->current_ns = pns;
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews if (pns == NULL)
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews return (ISC_R_NOMORE);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews INSIST(pns->current_server != NULL);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews dns_message_reset(trans->qmessage, DNS_MESSAGE_INTENTRENDER);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews result = make_querymessage(trans->qmessage, trans->qname, type);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews if (result != ISC_R_SUCCESS)
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews return (result);
0c67279acb4a6ac356879498b220645755d77cc9Mark Andrews result = dns_client_startrequest(client, trans->qmessage,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews trans->rmessage,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews &pns->current_server->address,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews 0, DNS_MESSAGEPARSE_BESTEFFORT,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews NULL, 120, 0, 4,
10ba7f6f563d68b8f1284847ccce85b706e793feBob Halley probe_task, request_done, trans,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews &trans->reqid);
return (result);
}
/*
* Get IP addresses of NSes
*/
static void
resolve_nsaddress(isc_task_t *task, isc_event_t *event) {
struct probe_trans *trans = event->ev_arg;
dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
dns_name_t *name;
dns_rdataset_t *rdataset;
dns_rdata_t rdata = DNS_RDATA_INIT;
struct probe_ns *pns = trans->current_ns;
isc_result_t result;
REQUIRE(task == probe_task);
REQUIRE(trans->inuse == ISC_TRUE);
REQUIRE(pns != NULL);
INSIST(outstanding_probes > 0);
for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
name = ISC_LIST_NEXT(name, link)) {
for (rdataset = ISC_LIST_HEAD(name->list);
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link)) {
(void)print_rdataset(rdataset, name);
if (rdataset->type != dns_rdatatype_a)
continue;
for (result = dns_rdataset_first(rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset)) {
dns_rdata_in_a_t rdata_a;
struct server *server;
dns_rdataset_current(rdataset, &rdata);
result = dns_rdata_tostruct(&rdata, &rdata_a,
NULL);
if (result != ISC_R_SUCCESS)
continue;
server = isc_mem_get(mctx, sizeof(*server));
if (server == NULL) {
fprintf(stderr, "resolve_nsaddress: "
"mem_get failed");
result = ISC_R_NOMEMORY;
POST(result);
goto cleanup;
}
isc_sockaddr_fromin(&server->address,
&rdata_a.in_addr, 53);
ISC_LINK_INIT(server, link);
server->result_a = none;
server->result_aaaa = none;
ISC_LIST_APPEND(pns->servers, server, link);
}
}
}
cleanup:
dns_client_freeresanswer(client, &rev->answerlist);
dns_client_destroyrestrans(&trans->resid);
isc_event_free(&event);
next_ns:
trans->current_ns = ISC_LIST_NEXT(pns, link);
if (trans->current_ns == NULL) {
trans->current_ns = ISC_LIST_HEAD(trans->nslist);
dns_fixedname_invalidate(&trans->fixedname);
trans->qname = NULL;
result = set_nextqname(trans);
if (result == ISC_R_SUCCESS)
result = probe_name(trans, dns_rdatatype_a);
} else {
result = fetch_nsaddress(trans);
if (result != ISC_R_SUCCESS)
goto next_ns; /* XXX: this is unlikely to succeed */
}
if (result != ISC_R_SUCCESS)
reset_probe(trans);
}
static isc_result_t
fetch_nsaddress(struct probe_trans *trans) {
struct probe_ns *pns;
pns = trans->current_ns;
REQUIRE(pns != NULL);
return (dns_client_startresolve(client, pns->name, dns_rdataclass_in,
dns_rdatatype_a, 0, probe_task,
resolve_nsaddress, trans,
&trans->resid));
}
/*
* Get NS RRset for a given domain
*/
static void
reset_probe(struct probe_trans *trans) {
struct probe_ns *pns;
struct server *server;
isc_result_t result;
REQUIRE(trans->resid == NULL);
REQUIRE(trans->reqid == NULL);
update_stat(trans);
dns_message_reset(trans->qmessage, DNS_MESSAGE_INTENTRENDER);
dns_message_reset(trans->rmessage, DNS_MESSAGE_INTENTPARSE);
trans->inuse = ISC_FALSE;
if (trans->domain != NULL)
isc_mem_free(mctx, trans->domain);
trans->domain = NULL;
if (trans->qname != NULL)
dns_fixedname_invalidate(&trans->fixedname);
trans->qname = NULL;
trans->qlabel = qlabels;
trans->qname_found = ISC_FALSE;
trans->current_ns = NULL;
while ((pns = ISC_LIST_HEAD(trans->nslist)) != NULL) {
ISC_LIST_UNLINK(trans->nslist, pns, link);
while ((server = ISC_LIST_HEAD(pns->servers)) != NULL) {
ISC_LIST_UNLINK(pns->servers, server, link);
isc_mem_put(mctx, server, sizeof(*server));
}
isc_mem_put(mctx, pns, sizeof(*pns));
}
outstanding_probes--;
result = probe_domain(trans);
if (result == ISC_R_NOMORE && outstanding_probes == 0)
isc_app_ctxshutdown(actx);
}
static void
resolve_ns(isc_task_t *task, isc_event_t *event) {
struct probe_trans *trans = event->ev_arg;
dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
dns_name_t *name;
dns_rdataset_t *rdataset;
isc_result_t result = ISC_R_SUCCESS;
dns_rdata_t rdata = DNS_RDATA_INIT;
struct probe_ns *pns;
REQUIRE(task == probe_task);
REQUIRE(trans->inuse == ISC_TRUE);
INSIST(outstanding_probes > 0);
for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
name = ISC_LIST_NEXT(name, link)) {
for (rdataset = ISC_LIST_HEAD(name->list);
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link)) {
(void)print_rdataset(rdataset, name);
if (rdataset->type != dns_rdatatype_ns)
continue;
for (result = dns_rdataset_first(rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset)) {
dns_rdata_ns_t ns;
dns_rdataset_current(rdataset, &rdata);
/*
* Extract the name from the NS record.
*/
result = dns_rdata_tostruct(&rdata, &ns, NULL);
if (result != ISC_R_SUCCESS)
continue;
pns = isc_mem_get(mctx, sizeof(*pns));
if (pns == NULL) {
fprintf(stderr,
"resolve_ns: mem_get failed");
result = ISC_R_NOMEMORY;
POST(result);
/*
* XXX: should we continue with the
* available servers anyway?
*/
goto cleanup;
}
dns_fixedname_init(&pns->fixedname);
pns->name =
dns_fixedname_name(&pns->fixedname);
ISC_LINK_INIT(pns, link);
ISC_LIST_APPEND(trans->nslist, pns, link);
ISC_LIST_INIT(pns->servers);
dns_name_copy(&ns.name, pns->name, NULL);
dns_rdata_reset(&rdata);
dns_rdata_freestruct(&ns);
}
}
}
cleanup:
dns_client_freeresanswer(client, &rev->answerlist);
dns_client_destroyrestrans(&trans->resid);
isc_event_free(&event);
if (!ISC_LIST_EMPTY(trans->nslist)) {
/* Go get addresses of NSes */
trans->current_ns = ISC_LIST_HEAD(trans->nslist);
result = fetch_nsaddress(trans);
} else
result = ISC_R_FAILURE;
if (result == ISC_R_SUCCESS)
return;
reset_probe(trans);
}
static isc_result_t
probe_domain(struct probe_trans *trans) {
isc_result_t result;
size_t domainlen;
isc_buffer_t b;
char buf[4096]; /* XXX ad hoc constant, but should be enough */
char *cp;
REQUIRE(trans != NULL);
REQUIRE(trans->inuse == ISC_FALSE);
REQUIRE(outstanding_probes < MAX_PROBES);
/* Construct domain */
cp = fgets(buf, sizeof(buf), fp);
if (cp == NULL)
return (ISC_R_NOMORE);
if ((cp = strchr(buf, '\n')) != NULL) /* zap NL if any */
*cp = '\0';
trans->domain = isc_mem_strdup(mctx, buf);
if (trans->domain == NULL) {
fprintf(stderr,
"failed to allocate memory for domain: %s", cp);
return (ISC_R_NOMEMORY);
}
/* Start getting NS for the domain */
domainlen = strlen(buf);
isc_buffer_init(&b, buf, domainlen);
isc_buffer_add(&b, domainlen);
dns_fixedname_init(&trans->fixedname);
trans->qname = dns_fixedname_name(&trans->fixedname);
result = dns_name_fromtext(trans->qname, &b, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_client_startresolve(client, trans->qname,
dns_rdataclass_in, dns_rdatatype_ns,
0, probe_task, resolve_ns, trans,
&trans->resid);
if (result != ISC_R_SUCCESS)
goto cleanup;
trans->inuse = ISC_TRUE;
outstanding_probes++;
return (ISC_R_SUCCESS);
cleanup:
isc_mem_free(mctx, trans->domain);
dns_fixedname_invalidate(&trans->fixedname);
return (result);
}
ISC_PLATFORM_NORETURN_PRE static void
usage(void) ISC_PLATFORM_NORETURN_POST;
static void
usage(void) {
fprintf(stderr, "usage: nsprobe [-d] [-v [-v...]] [-c cache_address] "
"[input_file]\n");
exit(1);
}
int
main(int argc, char *argv[]) {
int i, ch, error;
struct addrinfo hints, *res;
isc_result_t result;
isc_sockaddr_t sa;
isc_sockaddrlist_t servers;
isc_taskmgr_t *taskmgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
isc_timermgr_t *timermgr = NULL;
while ((ch = getopt(argc, argv, "c:dhv")) != -1) {
switch (ch) {
case 'c':
cacheserver = optarg;
break;
case 'd':
debug_mode = ISC_TRUE;
break;
case 'h':
usage();
break;
case 'v':
verbose_level++;
break;
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
/* Common set up */
isc_lib_register();
result = dns_lib_init();
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "dns_lib_init failed: %d\n", result);
exit(1);
}
result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr,
&timermgr);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "ctx create failed: %d\n", result);
exit(1);
}
isc_app_ctxstart(actx);
result = dns_client_createx(mctx, actx, taskmgr, socketmgr,
timermgr, 0, &client);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "dns_client_createx failed: %d\n", result);
exit(1);
}
/* Set local cache server */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
error = getaddrinfo(cacheserver, "53", &hints, &res);
if (error != 0) {
fprintf(stderr, "failed to convert server name (%s): %s\n",
cacheserver, gai_strerror(error));
exit(1);
}
if (res->ai_addrlen > sizeof(sa.type)) {
fprintf(stderr,
"assumption failure: addrlen is too long: %ld\n",
(long)res->ai_addrlen);
exit(1);
}
memcpy(&sa.type.sa, res->ai_addr, res->ai_addrlen);
sa.length = res->ai_addrlen;
freeaddrinfo(res);
ISC_LINK_INIT(&sa, link);
ISC_LIST_INIT(servers);
ISC_LIST_APPEND(servers, &sa, link);
result = dns_client_setservers(client, dns_rdataclass_in, NULL,
&servers);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "failed to set server: %d\n", result);
exit(1);
}
/* Create the main task */
probe_task = NULL;
result = isc_task_create(taskmgr, 0, &probe_task);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "failed to create task: %d\n", result);
exit(1);
}
/* Open input file */
if (argc == 0)
fp = stdin;
else {
fp = fopen(argv[0], "r");
if (fp == NULL) {
fprintf(stderr, "failed to open input file: %s\n",
argv[0]);
exit(1);
}
}
/* Set up and start probe */
for (i = 0; i < MAX_PROBES; i++) {
probes[i].inuse = ISC_FALSE;
probes[i].domain = NULL;
dns_fixedname_init(&probes[i].fixedname);
probes[i].qname = NULL;
probes[i].qlabel = qlabels;
probes[i].qname_found = ISC_FALSE;
probes[i].resid = NULL;
ISC_LIST_INIT(probes[i].nslist);
probes[i].reqid = NULL;
probes[i].qmessage = NULL;
result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
&probes[i].qmessage);
if (result == ISC_R_SUCCESS) {
result = dns_message_create(mctx,
DNS_MESSAGE_INTENTPARSE,
&probes[i].rmessage);
}
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "initialization failure\n");
exit(1);
}
}
for (i = 0; i < MAX_PROBES; i++) {
result = probe_domain(&probes[i]);
if (result == ISC_R_NOMORE)
break;
else if (result != ISC_R_SUCCESS) {
fprintf(stderr, "failed to issue an initial probe\n");
exit(1);
}
}
/* Start event loop */
isc_app_ctxrun(actx);
/* Dump results */
printf("Per domain results (out of %lu domains):\n",
number_of_domains);
printf(" valid: %lu\n"
" ignore: %lu\n"
" nxdomain: %lu\n"
" othererr: %lu\n"
" multiplesoa: %lu\n"
" multiplecname: %lu\n"
" brokenanswer: %lu\n"
" lame: %lu\n"
" unknown: %lu\n"
" multiple errors: %lu\n",
domain_stat.valid, domain_stat.ignore, domain_stat.nxdomain,
domain_stat.othererr, domain_stat.multiplesoa,
domain_stat.multiplecname, domain_stat.brokenanswer,
domain_stat.lame, domain_stat.unknown, multiple_error_domains);
printf("Per server results (out of %lu servers):\n",
number_of_servers);
printf(" valid: %lu\n"
" ignore: %lu\n"
" nxdomain: %lu\n"
" othererr: %lu\n"
" multiplesoa: %lu\n"
" multiplecname: %lu\n"
" brokenanswer: %lu\n"
" lame: %lu\n"
" unknown: %lu\n",
server_stat.valid, server_stat.ignore, server_stat.nxdomain,
server_stat.othererr, server_stat.multiplesoa,
server_stat.multiplecname, server_stat.brokenanswer,
server_stat.lame, server_stat.unknown);
/* Cleanup */
for (i = 0; i < MAX_PROBES; i++) {
dns_message_destroy(&probes[i].qmessage);
dns_message_destroy(&probes[i].rmessage);
}
isc_task_detach(&probe_task);
dns_client_destroy(&client);
dns_lib_shutdown();
isc_app_ctxfinish(actx);
ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
return (0);
}