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

Is there any way to get a domain name from an ip? I know how to get a hostname, ex:
use strict; use Socket; my $addr = inet_aton("209.214.174.80"); my $host = gethostbyaddr($addr, AF_INET);
but is it possible to get a domin?

Thanks in advance,
blax

Replies are listed 'Best First'.
Re: Domain name from ip.
by rob_au (Abbot) on Dec 03, 2001 at 05:04 UTC
    Probably the easiest way to do this is through the use of the Net::hostent module. eg.

    use Net::hostent; use strict; my $host = gethost("209.214.174.80"); print $host->name, "\n";

    Remember though that domain resolution is only as good as the domain system - Some IP addresses may not have been set up with PTR records back to fully-qualified domain names.

    Update #1 - Another excellent solution might be to use Net::Domain which provides methods not only for IP address resolution, but also hostname and hostdomain for system hostname and domain respectively.

    Update #2 - Ugh, Net::Domain is only good for determining this information about the local machine.

     

    perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

      Remember though that domain resolution is only as good as the domain system - Some IP addresses may not have been set up with PTR records back to fully-qualified domain names.

      Indeed. Most of the odd hits in my server logs can't be backtraced to valid domain names, though there is often enough information available to find out what "neighborhood" they're in (e.g., who an IP addr's provider is).

      To dig up what info I could on suspect IP addresses, I whipped up the following script, which front-ends dig(1) on FreeBSD.

      #!/usr/bin/perl -w # # simple frontend for dig(1) # use strict; my $tracing = 1; sub usage { print <<EOM; usage: $0 ipaddr EOM exit(1); } my $ipaddr = shift @ARGV || usage(); my @ipaddr = split(/\./ , $ipaddr); # work our way through the parts of the ip address, stopping # when we're down to 1. do { dig_on(@ipaddr); pop @ipaddr; } until ( @ipaddr == 1 ); sub dig_on { my @addr = @_; my $subaddr = join('.', @addr); my $revaddr = join('.', reverse @ipaddr); print "going after $subaddr ...\n" if $tracing; open(IN, "dig -x $subaddr | grep $revaddr | ") or die "open(): $!"; while ( <IN> ) { next if /^;/; print; } close(IN); }
      Suggestions on how to improve this are welcome.

Re: Domain name from ip.
by Kanji (Parson) on Dec 03, 2001 at 05:20 UTC

    If you have the hostname, it's just a matter of string manipulation to extract the domain.

    The trick is knowing what counts as a domain.

    With gTLDs (.com, .net, .org, etc.), it's easy: you just want the last two atoms of the hostname ...

    my $domain = join( '.' => ( split /\./ => $host )[-1,-2] );

    ... but with ccTLDs (.uk, .jp, .us), things get a lot more tricky as many of those have their own .com equivalents (.co.uk) which should be considered to be the real domains, or -- worse still -- use a mix of the two and three level styles.

    An imperfect approach could be...

    my @atom = split /\./, $host; if ( length($atom[-1]) == 3 ) { # gTLD $domain = join( '.', @atom[-2,-1] ); } elsif ( length($atom[-1]) == 2 ) { # ccTLD # Check if ccTLD domains are name.x.tld or # name.tld style. This is /NOT/ 100% accurate! $domain = join '.' => $atom[-2] =~ /^(?:com?|net|org|ac|edu)$/ ? @atom[-3,-2,-1] : @atom[-2,-1]; } else { warn("Couldn't extract gTLD/ccTLD from $host\n"); $domain = undef; }

        --k.


      Remembering of course that com|net|org|edu|gov|int aren't the only gTLD's anymore. :(
      Kanji,

      That method would not work all of the time. Sometimes gethostbyaddr will return a hostname that looks something like this: HOST5-209.252.153.98.

      Thanks everyone for your help,
      <RB> blax