mikejones has asked for the wisdom of the Perl Monks concerning the following question:

Perl Monks, In this code I am looking for the Presence of IPs, %AoH within two different domains, $domains.

It ends with the expected data, but it only goes once through the loop using 10.220.84.30. Any help or ideas? thx! : )

#!/usr/bin/perl use strict; use warnings; use Carp; use Net::DNS; use Data::Dumper; #print qq ( Host\tIP\tNS7Host\tNS7IP\tWRHost\tWRIP ); my %AoH = ( q(client_IP) => [ qw (10.220.84.30 10.220.84.51 10.220.84.52 10.220.84.54 10.220.84.55 10.220.84.56 10.220.84.57 10.220.84.58 10.220.84.59 10.220.84.60 10.220.84.61 10.220.84.62 10.220.84.64 10.220.84.65 10.220.84.70 10.220.84.71 10.220.84.72 10.220.84.73 10.220.84.74 10.220.84.80 10.220.84.81 10.220.84.82 10.220.84.98 10.220.84.99 10.220.84.100 10.220.84.101 10.8.239.102 10.8.239.103 10.8.239.104 10.8.239.105 10.220.84.112 10.220.84.122 10.220.84.123 10.220.84.124 10.220.84.210 10.220.84.213 10.220.84.218 10.220.84.220 10.220.84.225 10.220.84.226 10.220.84.227 10.220.84.228 10.220.84.237 10.220.84.231 10.8.239.232 10.220.84.233 10.220.84.234 10.8.239.238 10.8.239.254 204.193.39.221 204.193.39.222 204.193.39.223 10.15.254.220 147.204.64.1 204.79.199.2 194.39.138.2 147.204.96.8 194.39.134.5 204.193.38.235 204.193.32.128 10.240.60.32 10.240.60.40 204.193.32.137 10.240.60.34 10.240.60.36 10.240.60.38 10.240.60.43 10.240.60.44 10.240.60.41 10.240.60.42 204.193.32.224 192.168.3.3 161.244.156.53 161.244.156.54 161.244.155.158 161.244.154.140 161.244.154.141 161.244.156.183 161.244.156.135 161.244.156.174 161.244.156.103 161.244.156.178 161.244.157.191 161.244.157.190) ] ) ; #for my $key (keys %AoH) { #print $key,' => ',join "\n\t", sort @{$AoH{$key}},"\n"; # print "\n"; # print "\n\t", sort @{$AoH{$key}},"\n"; #} #print sort @{$AoH{$_}} for (keys %AoH); for my $key (keys %AoH) { for my $domain qw(ns7.xxx.com wrnadc02.xx.xxxxxx.com) { nsqry($domain, @{$AoH{$key}} ) ; } } sub nsqry { my $nssvr = shift @_ ; my $client = shift @_ ; my $res = Net::DNS::Resolver->new ( nameservers => [$nssvr], recurse => 1, ## do recursive lookups retry => 1, debug => 0, ) ; my $query = $res->search($client) ; if ($query) { for my $rr ($query->answer) { next unless ($rr->type eq "PTR"); ## skip record if not eq + PTR ## print $rr->ptrdname, "\n" ; } } else { warn "query failed: ", $res->errorstring, "\n" ; } }

Replies are listed 'Best First'.
Re: loop ending b4 I want it to
by FunkyMonk (Bishop) on Oct 26, 2007 at 23:05 UTC
    You pass an array to nsqry like so:
    nsqry($domain, @{$AoH{$key}} ) ;

    but, in nsqry you only pick up the first element of the array with

    my $nssvr = shift @_ ; my $client = shift @_ ;

    You could get all the IP addresses you pass to nsqry by using

    my $nssvr = shift @_ ; my @clients = @_ ;

    and then you'd have to loop over your existing code with something like:

    for my $client ( @clients ) { ... }

    update: Errors pointed out by jasonk corrected. Thanks jasonk

      And after all those changes, you still have exactly the same result, because my @clients = shift @_ is always going to give you a one-element array. I think you wanted to say my @clients = @_ although I tend to prefer the more concise my ( $nssvr, @clients ) = @_


      We're not surrounded, we're in a target-rich environment!
Re: loop ending b4 I want it to
by NetWallah (Canon) on Oct 27, 2007 at 12:09 UTC
    As an alternative to FunkyMonk's suggestion (essentially echoed by jasonk), you may want to keep your "sub nsqry" to answer just a single Name lookup.

    If this is the case, you need to add one more loop :

    for my $key (keys %AoH) { for my $domain qw(ns7.xxx.com wrnadc02.xx.xxxxxx.com) { nsqry($domain, $_ ) for @{$AoH{$key}} ; } }
    By the way, your %AoH is really a HASH whose VALUES are Array-refs, and would probably be better named as "HoA".

    I imagine (Having written similar functionality myself), that you may eventually want to associate the domain name with the IP-address when you find it. Your current data structure will make that association very complicated. Here is my suggested structure/code:

    my @domain = ( {NAME => 'ns7.xxx.com', IPLIST => []} # IP +LIST gets populated dynamically, as discovered , {NAME => 'wrnadc02.xx.xxxxxx.com', IPLIST => []} ); my %IPinfo; # This will be a HoH for (qw (10.220.84.30 10.220.84.51 10.220.84.52 10.220.84.54 ...){ $IPinfo{$_}= {DOMAININDEX => undef, TYPE => "CLIENT"}; } .... OUTER: for my $ip (keys %IPinfo){ for my $domidx (0..$#domain){ my $ptr = nsquery($domain[$domidx]->{NAME}, $ip) ; # Assumi +ng "nsquery" has been modified to return the info next unless $ptr; # No change, if $ptr is empty $IPinfo{$ip}{DOMAININDEX} = $domidx; # Forward ref from IP +to DOMAIN $IPinfo{$ip}{PTR} = $ptr; push @{$domain[$domidx]->{IPLIST}}, $ip; # Keep a list of I +P's that live in this domain next OUTER; # we bail after the first domain found (More ef +ficient) } }

         "As you get older three things happen. The first is your memory goes, and I can't remember the other two... " - Sir Norman Wisdom

      yes you are right...I would like to match the domain names with the IP lookup, however I do not want to skip the second lookup if any IP is found in the 1st domain because I want to see if an IP is in both domains. When you said "Assuming "nsqry" has been modified to return the info," I became confused in trying to modify the sub. Will you help?
      #!/usr/bin/perl use strict; use warnings; use Carp; use Net::DNS; use Data::Dumper; my @domain = ( { NAME => 'ns7.pyxis.com', IPLIST => [] } , ## Autovivification { NAME => 'wrnadc02.na.alarismed.com', IPLIST => [] } ) ; my %IPinfo; # HoH for my $IP (qw ( 10.220.84.30 10.220.84.51 10.220.84.52 10.220.84.54 10.220.84.55 10.220.84.56 10.220.84.57 10.220.84.58 10.220.84.59 10.220.84.60 10.220.84.61 10.220.84.62 10.220.84.64 10.220.84.65 10.220.84.70 10.220.84.71 10.220.84.72 10.220.84.73 10.220.84.74 )) { $IPinfo{$IP} = {DOMAININDEX => undef, TYPE => "CLIENT" } ; } for my $ip (keys %IPinfo) { for my $domids (0..$#domain) { my $ptr = nsqry($domain[$domids]->{NAME}, $ip) ; next unless $ptr ; # No change, if $ptr is empty $IPinfo{$ip}{DOMAININDEX} = $domids ; $IPinfo{$ip}{PTR} = $ptr ; push @{$domain[$domids]->{IPLIST}}, $ip ; } } sub nsqry { my ( $nssvr, @clients ) = @_ ; my $res = Net::DNS::Resolver->new ( nameservers => [$nssvr], recurse => 1, ## do recursive lookups retry => 1, debug => 0, ) ; for my $client (@clients) { my $query = $res->search($client) ; if ($query) { for my $rr ($query->answer) { next unless ($rr->type eq "PTR"); print $rr->ptrdname, "\n" ; } } else { warn "query failed: ", $res->errorstring, "\n" ; } } } print Dumper(\@domain); $VAR1 = [ { 'NAME' => 'ns7.pyxis.com', 'IPLIST' => [] }, { 'NAME' => 'wrnadc02.na.alarismed.com', 'IPLIST' => [] } ];
        It is not clear what you are trying to achieve.

        Your code shows attempts to explicitly specify domain name servers. Some issues that leave your approach and objectives hazy are:

        • You explicitly specify Name SERVERS, not domain names. This is OK, if all you want are PTR records.
        • 'wrnadc02.na.alarismed.com' does not seem to exist. In fact the "na" subdomain does not seem to exist
        • "alarismed.com" seems to have the same name server(s) as "pyxis.com", so the reason for specifying different Name servers is not clear.
        • You are re-creating a new $res object for each query.
        If your "sub nsqry" works as you expect, the only change necessary is to "return $rr->ptrdname" after (or instead of) printing it.On failure, "return undef".

        You can also use a modified example from the Net::DNS docs:

        sub new-nsqry{ my ($res, $IP) = @_; # Note: $res is created OUTSIDE the sub ... my $query = $res->query($IP, "PTR"); if ($query) { foreach $rr (grep { $_->type eq 'PTR' } $query->answer) { print $rr->ptrdname, " : $IP\n"; return $rr->ptrdname; } return undef; } else { warn "query failed for $IP: ", $res->errorstring, "\n"; return undef; } }

             "As you get older three things happen. The first is your memory goes, and I can't remember the other two... " - Sir Norman Wisdom