#!/usr/bin/env perl # # ipnum2name - translate IP addresses in the input to DNS names # # $Id$ # when a lookup fails, returns the IP address itself # caches all results use warnings; use strict; use Socket qw( getaddrinfo getnameinfo ); my %ipnum2name; $| = 1; # force output line flushing my $ipnum_rx = qr/([0-9a-f]*:[0-9a-f:]+|[0-9]{1,3}(?:\.[0-9]{1,3}){3})/i; # not entirely accurate for IPv6, see https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses sub ipnum2name # thank you, https://www.perlmonks.org/?node_id=938198 { my ($num) = @_; my ( $err, @addrs ) = getaddrinfo( $num, 0 ); if ($err) { $num; } elsif ( my ( $err, $hostname ) = getnameinfo( $addrs[0]->{addr} ) ) { $err ? $num : $hostname; } } while (<>) { my @line = split( $ipnum_rx, $_ ); #warn "line: ", join(' + ', @line); @line = map { my $fld = $line[$_]; if ( $_ % 2 == 0 ) { $fld; } elsif ( defined $ipnum2name{$fld} ) { # looked up before $ipnum2name{$fld}; } elsif ( ( grep { /^[0-9a-f]{0,4}$/i } split( /:/, $fld ) ) > 1 ) { #warn "looks like an IPv6 address: $fld\n"; # look it up and cache the result; lookups are expensive $ipnum2name{$fld} = ipnum2name($fld); } elsif ( !/[^.\d]/ && split( /\./, $fld ) == 4 && ( grep { $_ < 256 } split( /\./, $fld ) ) == 4 ) { #warn "looks like an IPv4 address: $fld\n"; # look it up and cache the result; lookups are expensive $ipnum2name{$fld} = ipnum2name($fld); } else { $fld; } } 0 .. $#line; print join( '', @line ); }