简体   繁体   中英

How can I match an IP address in Perl?

I have a local DNS script that I've inherited from a past employee that needs to compare some values to see if they match specific MX records and IP addresses.

The MX part I have down okay:

120 $doug = doug.local
139 if ($mx_record =~ /$doug/) {
140         print ("Mail on doug.\n");
141 }
142         else {
143                 print ("Not on doug.\n");
144 }

$mx_record is a line from an mx query that would look like this:

thomas.            302     IN      MX      10 doug.local.

Now I need to see if the A record matches.

The $a_record variable from the query looks like this.

thomas.            300     IN      A       10.0.0.47

How do I do a conditional statement to match an IP address?

I need to define the IP in a variable and then see if the $a_record variable contains that defined IP.

If you just want to match an IPv4 regex, use Regexp::Common::net .

Rather than running a regex over the whole line, its safer to tokenize them and match individual parts as necessary.

use strict;
use warnings;

use Data::Dumper;

sub parse_record {
    my $line = shift;

    # special rules for parsing different types
    my %More4Type = (
        MX      => sub { return( priority => $_[0], provider => $_[1] ) },
        default => sub { return( provider => $_[0] ) }
    );

    my(%record, @more);
    (@record{qw(host uhh class type)}, @more) = split /\s+/, $line;
    my $more_func = $More4Type{$record{type}} || $More4Type{default};
    %record = (%record, $more_func->(@more));

    return \%record;
}

while(my $line = <DATA>) {
    print Dumper parse_record($line);
}

__END__
thomas.            302     IN      MX      10 doug.local.
thomas.            300     IN      A       10.0.0.47
google.com.     24103   IN  NS  ns2.google.com.

Now that you've parsed the line, its a simple matter of looking at $record{type} and $record{provider} or whatever you need. For a little bit of effort this is far more flexible and less bug prone.

Though there's probably something on CPAN to do the parsing for you.

I'm sure there's a better way, but this will get you pretty close:

if($a_record =~ /((?:\d{1,3}\.){3}\d{1,3})/) {
     warn "IP was: $1";
}

# IP was: 10.0.0.47

This matches 10.0.0. then the final 47 .

This will match a entry that looks like a ip address, but will also match 999.999.999.999. Make sure to validate the matched address before using it.

if ($mx_record =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/) {...}

try this:

if ($mx_record =~ /A\w+(<record_ip>(?:/[0-9]{1,3}.){4})/ {
   print $record_ip
}

This will check for A followed by whitespace, followed by a dotted quad. The quad is saved in the variable $record_ip

my $a_record = 'thomas.            300     IN      A       10.0.0.47';
my $ip = '10.0.0.47';

if ($a_record =~ /\b(\Q$ip\E)$/) {
    print "Matches: $1\n";
}

Since the IP address might not be in its most compact decimal notation, I suggest you should use the inet_aton() function from the Socket module:

use Socket;

my $ip_to_match = inet_aton('10.0.0.47');
...
if (inet_aton($field) == $ip_to_match) {
    ...
}

NB: assumes that the DNS record has already been split down to its component parts

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM