1#!/usr/bin/perl 2# 3# $Id: Connectivity.pm 885 2010-06-18 14:26:03Z calle $ 4# 5# Copyright (c) 2007 .SE (The Internet Infrastructure Foundation). 6# All rights reserved. 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 21# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28# 29###################################################################### 30 31package DNSCheck::Test::Connectivity; 32 33require 5.008; 34use warnings; 35use strict; 36use Net::IP; 37 38our $SVN_VERSION = '$Revision: 885 $'; 39 40use base 'DNSCheck::Test::Common'; 41 42###################################################################### 43 44sub test { 45 my $self = shift; 46 my $zone = shift; 47 48 my $parent = $self->parent; 49 my $qclass = $self->qclass; 50 my $logger = $self->logger; 51 52 return unless $parent->config->should_run; 53 54 $logger->module_stack_push(); 55 $logger->auto("CONNECTIVITY:BEGIN", $zone); 56 57 my $errors = $self->test_v4($zone) + $self->test_v6($zone); 58 59 $logger->auto("CONNECTIVITY:END", $zone); 60 $logger->module_stack_pop(); 61 62 return $errors; 63} 64 65sub test_v4 { 66 my $self = shift; 67 my $zone = shift; 68 69 my $parent = $self->parent; 70 my $qclass = $self->qclass; 71 my $logger = $self->logger; 72 my $errors = 0; 73 74 return 0 unless $parent->config->should_run; 75 76 my %as_set; 77 my @nameservers = (); 78 79 # Fetch IPv4 nameservers 80 my $ipv4 = $parent->dns->get_nameservers_ipv4($zone, $qclass); 81 push @nameservers, @{$ipv4} if ($ipv4); 82 83 foreach my $address (@nameservers) { 84 my $as_lookup = $parent->asn->lookup($address); 85 my @as_list = (); 86 @as_list = @{$as_lookup} if $as_lookup; 87 88 foreach my $asn (@as_list) { 89 $as_set{$asn} = $asn; 90 } 91 92 $logger->auto("CONNECTIVITY:ANNOUNCED_BY_ASN", 93 $address, join(",", @as_list)); 94 95 # REQUIRE: A name server must be announced 96 if (scalar @as_list < 1) { 97 $errors += $logger->auto("CONNECTIVITY:NOT_ANNOUNCED", $address); 98 } 99 } 100 101 $logger->auto("CONNECTIVITY:ASN_LIST", join(",", keys(%as_set))); 102 103 # REQUIRE: Domain name servers should live in more than one AS 104 my $as_count = scalar keys %as_set; 105 if ($as_count <= 1) { 106 $errors += $logger->auto("CONNECTIVITY:TOO_FEW_ASN", $as_count); 107 } else { 108 $logger->auto("CONNECTIVITY:ASN_COUNT_OK", $as_count); 109 } 110 111 DONE: 112 113 return $errors; 114} 115 116sub test_v6 { 117 my $self = shift; 118 my $zone = shift; 119 120 my $parent = $self->parent; 121 my $qclass = $self->qclass; 122 my $logger = $self->logger; 123 my $errors = 0; 124 125 return 0 unless $parent->config->should_run; 126 127 my %as_set; 128 my @nameservers = (); 129 130 # Fetch IPv6 nameservers. 131 my $ipv6 = $parent->dns->get_nameservers_ipv6($zone, $qclass); 132 push @nameservers, @{$ipv6} if ($ipv6); 133 134 foreach my $address (map { Net::IP->new($_)->ip } @nameservers) { 135 my $as_lookup = $parent->asn->lookup($address); 136 my @as_list = (); 137 @as_list = @{$as_lookup} if $as_lookup; 138 139 foreach my $asn (@as_list) { 140 $as_set{$asn} = $asn; 141 } 142 143 $logger->auto("CONNECTIVITY:V6_ANNOUNCED_BY_ASN", 144 $address, join(",", @as_list)); 145 146 # REQUIRE: A name server must be announced 147 if (scalar @as_list < 1) { 148 $errors += $logger->auto("CONNECTIVITY:V6_NOT_ANNOUNCED", $address); 149 } 150 } 151 152 $logger->auto("CONNECTIVITY:V6_ASN_LIST", join(",", keys(%as_set))); 153 154 # REQUIRE: Domain name servers should live in more than one AS 155 my $as_count = scalar keys %as_set; 156 if ($as_count <= 1) { 157 $errors += $logger->auto("CONNECTIVITY:V6_TOO_FEW_ASN", $as_count); 158 } else { 159 $logger->auto("CONNECTIVITY:V6_ASN_COUNT_OK", $as_count); 160 } 161 162 DONE: 163 return $errors; 164} 165 1661; 167 168__END__ 169 170 171=head1 NAME 172 173DNSCheck::Test::Connectivity - Test zone connectivity 174 175=head1 DESCRIPTION 176 177Test connectivity for a zone's nameservers. The following tests are made: 178 179=over 4 180 181=item * 182A name server should not be announced by more than one AS. 183 184=item * 185A name server must be announced. 186 187=item * 188Domain name servers should live in more than one AS. 189 190=back 191 192=head1 METHODS 193 194=over 195 196=item ->test($zonename); 197 198=back 199 200=head1 EXAMPLES 201 202=head1 SEE ALSO 203 204L<DNSCheck>, L<DNSCheck::Logger> 205 206=cut 207