Batch Conversion Domain to IP - perl

I have a list of domains I would like to convert to their respective IP. Let's say:
domain1.com
domain2.com
domain3.com
I would like to get the IP of each of these domains, such as:
domain1.com -> 111.111.111.111
domain2.com -> 222.222.222.222
domain3.com -> 333.333.333.333
I'm using a Perl script I found online and adding my domain list where it says :
echo "
<insert_list>
" | perl -MSocket -lne'
my $address = ( split /:/ )[ 0 ] or next;
my $number = inet_aton $address;
my $ip = inet_ntoa $number;
print "$address -> $ip";
'
This works, but some of the domains on my list have expired and no longer have IPs, in which case I get the following error message:
Bad arg length for Socket::inet_ntoa, length is 0, should be 4 at -e line 4, <> line 9.
I'd like to have a printed list that also tells me if a domain is unassigned. Example:
domain1.com -> 111.111.111.111
domain2.com -> 222.222.222.222
domain3.com -> 333.333.333.333
domain4.com -> Unknown Host
My list is fairly long: I have about 500 domains to organize and clean-up. What would be the best way to get the IP of each domain?
Any help would be greatly appreciated. Thanks!

Try changing the $ip assignment line to:
my $ip = $number ? inet_ntoa $number : "Unknown Host";
This checks the $number variable to see whether it's empty or not, and only if it isn't does it call inet_ntoa to convert the address to a printable form. If $number is empty, it assigns the string "Unknown Host".

Related

Reversing the IP address in Linux using perl

I have a job where I need to do nslookup on an IP address. If it matches then I need to print the name of the host. The problem is that the IP address comes reversed when running the command.
nslookup 10.11.12.13
13.12.11.10.in-addr.arpa
I tried to use reverse but that reversed everything which is not what I want.
my $ip = '13.12.11.10';
$result = reverse($ip);
print $result;
which then prints 01.11.21.31
I do not want to reverse everything, just the full numbers.
Please can someone help?
Simply split the IP address on .s using split, reverse the resulting array, then rejoin it:
join(".", reverse(split(/\./, $ip)))
This will give you the "reversed" IP address, which you can then compare to the nslookup result.
So what we need to do is to just split the actual address, reorder them in reverse and then match the IP to the reversed IP.
use strict;
use warnings;
my $ipaddress = '10.11.12.13';
my #ip = split /\./,$ipaddress; #split the IP by .
my $sserddapi = "$ip[3].$ip[2].$ip[1].$ip[0]"; #reverse it
my #lookup = `nslookup $ipaddress`; #do the match
$lookup[3] =~ s/\s+//g; #remove all whitespace
my #device = split /=/, $lookup[3]; #get the hostname
if ($lookup[3] =~ /^$sserddapi/) { #see if it matches
$lookup[3] =~ s/$sserddapi.in-addr.arpaname=//g; #Remove the unwanted stuff
print "$ipaddress = $lookup[3]\n"; #print the result
}

Why am I getting warnings about an uninitialized value in this Perl program? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I get these errors
Use of uninitialized value $vm_name in pattern match (m//) at testscript.pl line 164, <STDIN> line 1.
Use of uninitialized value $vm_name in concatenation (.) or string at testscript.pl line 173, <STDIN> line 1.
Can anyone help? I have a feeling it is to do with the subroutine but cannot figure it out exactly. I am new to Perl and have been poring over this for hours.
# !/usr/bin/perl
use strict;
use warnings;
use feature ":5.10";
###############################################################################
# Static Variables
my $templateID = "XXXXXXXXXX";
my $serviceID = "XXXXXXXXXXX";
###############################################################################
###############################################################################
# Global Variables
my $zone;
my $input;
my $zone_ID;
my $vm_name;
my $net_default;
my $net_secondary;
my $vm_ID;
my $start;
my $char_count;
my $ipaddr_1;
my $ipaddr_2;
###############################################################################
# ----------------------- BASIC CONFIGURATIONS [ZONES] ------------------------
print " *** ";
print "
ZONES: paris, milan, berlin, geneva, amsterdam, london, slough";
print " which zone would you like to deploy to? \n ";
# Capture input for ZONE
$input = <STDIN>;
# Data formatting
$input =~ s/^\s+|\s+$|^\t//g;
$zone = lc $input;
# Declare ZONE to USER
print "You are deploying to $zone \n";
# Map input to function
# ZONE PARIS
if ($zone eq "paris") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "374b937d-2051-4440-b02c-a314dd9cb27e";
}
# ZONE MILAN
elsif ($zone eq "milan") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "58848a37-db49-4518-946a-88911db0ee2b";
}
# ZONE BERLIN
elsif ($zone eq "berlin") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "fc129b38-d490-4cd9-acf8-838cf7eb168d";
}
# ZONE GENEVE
elsif ($zone eq "geneva") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "1ef96ec0-9e51-4502-9a81-045bc37ecc0a";
}
# ZONE AMSTERDAM
elsif ($zone eq "amsterdam") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "3c43b32b-fadf-4629-b8e9-61fb7a5b9bb8";
}
# ZONE SLOUGH
elsif ($zone eq "slough") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "5343ddc2-919f-4d1b-a8e6-59f91d901f8e";
}
# ZONE LONDON
elsif ($zone eq "london") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "f6b0d029-8e53-413b-99f3-e0a2a543ee1d";
}
# ELSE
else {
print "Please choose a ZONE";
system('./deploy_vm');
}
# SUBROUTINE: Assigning Virtual Machine name
sub vm_name {
# Name of Virtual Machine
print "Enter name of Virtual Machine: \n";
print "[VDC Bug: Please do not include '_' in the name]\n";
my $vm_name = <STDIN>;
# Data formatting
$vm_name =~ s/^\s+|\s+$//g;
print("VM Name: $vm_name");
}
# Apply input filters (no underscores, length constraints)
if (my $vm_name =~ /_/) {
return ('underscore error');
print "Cannot use underscore in VM name, please try again";
vm_name();
}
# DisPlay config
print "
$vm_name will be provisioned with:
1GB HDD and compute offering of 2CPUs with 2GB-RAM";
# ----------------------- NETWORK CONFIGURATIONS ------------------------------
# Gather network information
print "available networks in $zone";
system('cloudmonkey list networks zoneid=$zone_id filter=name,id');
# Users to choose Networks through display
print "";
# Default NIC & IP address
print "please enter Network ID for Default NIC:\n";
$net_default = <STDIN>;
# IP Address DEFAULT
print "please enter IP address\n";
$ipaddr_1 = <STDIN>;
# formatting IP address
$ipaddr_1 =~ m/^\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
# SECONDARY NIC & IP address
print "please enter Network ID for secondary NIC";
$net_secondary = <STDIN>;
# IP Address SECONDARY
print "please enter IP address\n";
$ipaddr_2 = <STDIN>;
# Formatting IP address
$ipaddr_2 =~ m/^\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
print "IP ADDRESS is $ipaddr_2\n";
# Deployment notice
print "... deploying ... \n";
# Provision Machine
# + startvm=false due to provisioning constraints
system('cloudmonkey deploy virtualmachine startvm=false name=$vm_name diplayname=$vm_name zoneid=$zone_id templateid=$templateID serviceofferingid=$serviceID networkids=$net_default ipaddress=$ipaddr_1');
# Add second network to VM
print "Adding second network to VM";
system('cloudmonkey addNicToVirtualMachine networkid=$network_id_second ipaddress=$ip_address_second virtualmachineid=$vm_id');
# Display machine ID
print "$vm_ID";
my $feedback = system('cloudmonkey list networks zoneid=$zone_id filter=name,id');
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
# # Sotiris Comments # #
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
# if (lc($feedback) =~ /error/) {
# Warn user and fall back to known state. }
# User to copy&paste ID
print "Paste VM ID:\n";
$vm_ID = <STDIN>;
# Data Validation
$vm_ID =~ s/^\s+|\s+$//g;
$vm_ID = lc $vm_ID;
$char_count = length($vm_ID);
# IF statement to impliment length validation
if ($char_count != 36) {
print "your ID is too long/short";
}
# Start Virtual Machine?
print "Start Virtual Machine $vm_name?";
$start = <STDIN>;
if ($start eq "yes") {
system('');
}
elsif ($start eq "no") {
system('');
}
# done!
You have posted a poor piece of Perl code that you have presumably written all in one chunk. Programming doesn't work like that, especially in script-like languages, and you should write just two or three lines at a time before testing that it works as you expect. That way, if you have a question at all, it can be about just a few lines of code whose input you know but whose behaviour you can't explain. In this case your Use of uninitialized value errors are the least of your worries.
You really shouldn't delcare everything at the top of your program, C-style. Declarations should be as close as possible to their first point of use.
Comments should be kept to the absolute minimum. It is very rare that a program contains a construct that is incomprehensible without the addition of comments, and your program is inflated around 100% by unnecessary commenting
The mapping between zones and zone IDs is best implemented as a Perl hash, not as an if/elsif/else chain
The vm_name subroutine is never called except in the test if (my $vm_name =~ /_/) { ... }, and your use of my here declares a new $vm_name which will always be undef
The lines you have commented with formatting IP address do no formatting at all. They test whether the variables' contents match the regular expression, and then ignore and discard the result of the test
The calls to system use single quotes, so the string is passed verbatim to the cloudmonkey program, and no interpolations are done. For instance, the variable names $vm_name, $zone_id, $templateID, $serviceID etc. are not replaced by their values
There are several more problems, but I strongly suggest that, as I said at the start, you should write the program incrementally in very small parts. That way you have the encouraging pleasure of seeing your code in action and wortking, as well as knowing for sure that, as you write, you have a firm foundation to build on.
if (my $vm_name =~ /_/)
will always warn Use of uninitialized value $vm_name in pattern match under warnings, as you're mistakenly declaring another lexical with my inside if condition.
Also you should sanitize user input as
my $vm_name = <STDIN>;
returned undefined if the user presses Ctrl-D or there was end of piped input.
You're reached the end of the input, but you pretend you actually read something in. Maybe you want to add
die "Premature EOF\n" if !defined($vm_name);
after
my $vm_name=<STDIN>;

Pattern matching an array with specific start and end words/characters

Have some output in an array which I am trying to pull details from where the output begins with a specific word and ends with a specific word/character. This output is then to be printed to the screen.
The output in the array which I am working with is:
router rip
version 2
redistribute bgp 45134 metric 3
passive-interface Serial1/3:1.333
passive-interface Serial3/1:3.333
passive-interface Serial3/1:5.333
passive-interface Serial3/2:1.333
passive-interface Serial3/4:1.333
passive-interface Serial3/4:17.333
passive-interface Serial6/1:1.333
no auto-summary
!
address-family ipv4 vrf TestVRF-0001
redistribute bgp 45134 metric 3
network 10.0.0.0
no auto-summary
version 2
exit-address-family
!
The perl code I have generated so far is below:
elsif ( $action eq "show_vrf1" ) {
my $cmd = "show run | begin router rip";
my #lines = $s->cmd(String => $cmd,
Prompt => "/$enableprompt/",
Timeout => 10);
foreach my $line (#lines) {
if(/address-family ipv4 vrf TestVRF-0001.*?!/){
$result=$1;
print $result;
}
}
}
Which I am wanting to only pull the below out of the array:
address-family ipv4 vrf TestVRF-0001
redistribute bgp 45134 metric 3
network 10.0.0.0
no auto-summary
version 2
exit-address-family
!
For some reason when I run the script, I just get a blank screen with no data pulled from the array.
if($line =~ /address-family ipv4 vrf TestVRF-0001.*?!/){
instead of
if(/address-family ipv4 vrf TestVRF-0001.*?!/){
?
You match $line against the regular expression. The output you expect is not on one line, so no line can match it.
You can store the whole multiline string in a scalar:
my $output = join q(), $s->cmd(...);
And then, you can retrieve the output, if you use parentheses to really capture a part of the string:
if ($output =~ /(address-family ipv4 vrf TestVRF-0001.*?!)/s) {
my $result = $1;
Note that the /s modifier is needed to make dot match a newline, which it normaly does not.

Getting all hostnames from IP address in Perl

I'm trying to find a way to get all hostnames that resolve to an IP address.
The gethostbyaddr function appears to only retrieve the first record from DNS (no matter if it's in scalar or list context).
Example:
my $hostname = gethostbyaddr(inet_aton($ip_to_check), AF_INET);
$print($hostname); //output: joe.example.com
my #hostnames = gethostbyaddr(inet_aton($ip_to_check), AF_INET);
foreach my $hostname (#hostnames){
print "(", join(',',#hostnames), ")"; //output: (joe.example.com,,2,4,?)
}
From the terminal:
$ host 192.168.1.5
5.1.168.192.in-addr.arpa domain name pointer joe.example.com.
5.1.168.192.in-addr.arpa domain name pointer john.example.com.
I've heard that Net::DNS is a little more robust, but I haven't had any luck getting that to pull all entries as well.
I used a combination of answers given here and elsewhere on stack overflow to find the answer I was looking for.
# create new Resolver Object
my $res = Net::DNS::Resolver->new;
# change IP from 192.168.1.15 to 15.1.168.192.in-addr.arpa for searching
my $target_IP = join('.', reverse split(/\./, $ip_to_check)).".in-addr.arpa";
# query DNS
my $query = $res->query("$target_IP", "PTR");
# if a result is found
if ($query){
print("Resolves to:\n");
# for every result, print the IP address
foreach my $rr ($query->answer){
# show all unless the type is PTR (pointer to a canonical name)
next unless $rr->type eq "PTR";
# remove the period at the end
printf(substr($rr->rdatastr, 0, -1));
}
}
The gethostby... interface is quite old and clunky, being defined back in primeval times before Perl got references and pretensions to OO. And it doesn't work the way you're trying to use it. When used in list context, it returns the primary name as the first element and a space-separated(!) list of aliases as the second:
my ($hostname, $aliases) = gethostbyaddr($addr, AF_INET);
my #hostname = ($hostname, split ' ', $aliases);
say join ' ', #hostname;
Now that's the theory; I didn't locate any IP addresses with multiple PTR records offhand, so I can't test if gethostbyaddr will actually return them -- it probably depends on your underlying C runtime as well -- but it does work if you use gethostbyname with a CNAMEd name, for instance.
Here's a small program I use to lookup all PTR records for a netmask (for example 192.0.2.0/28 ) when doing abuse tracking tasks. It sends up to 15 queries a second and when they are all sent then starts reading the responses (so it'd need a little work to function properly for bigger net blocks).
#!/usr/bin/env perl
use strict;
use warnings;
use Net::Netmask;
use Net::DNS;
#ARGV or die "$0 ip/cidr\n";
my $block = Net::Netmask->new(shift);
my $res = Net::DNS::Resolver->new;
my %sockets;
my $i = 0;
for my $i (1 .. $block->size - 1) {
my $ip = $block->nth($i);
my $reverse_ip = join ".", reverse split m/\./, $ip;
$reverse_ip .= ".in-addr.arpa";
#print "$ip\n";
my $bgsock = $res->bgsend($reverse_ip, 'PTR');
$sockets{$ip} = $bgsock;
sleep 1 unless $i % 15;
}
$i = 0;
for my $i (1 .. $block->size - 1) {
my $ip = $block->nth($i);
my $socket = $sockets{$ip};
my $wait = 0;
until ($res->bgisready($socket)) {
print "waiting for $ip\n" if $wait > 0;
sleep 1 + $wait;
$wait++;
}
my $packet = $res->bgread($socket);
my #rr = $packet->answer;
printf "%-15s %s\n", $ip, $res->errorstring
unless #rr;
for my $rr (#rr) {
printf "%-15s %s\n", $ip, $rr->string;
}
}
I don't think this is a well-formed problem statement. In the general case, there's a nearly infinite number of DNS names that could resolve to any IP address, even unknown to the party that holds the address. Reverse-lookups are fundamentally unreliable, and are not capable of answering the question the poster would like, since all names for an IP do not need to be in the visible reverse map.
The first answer, which enumerates the reverse map, is the best one can do, but it will miss any names that have not been entered in the map.
This is what I have used:
sub getauthoritivename
{
my ($printerdns)=#_;
my $res = Net::DNS::Resolver->new(searchlist=>$config->{searchlist});
my $query = $res->search($printerdns);
if ($query)
{
foreach my $rr ($query->answer)
{
next unless $rr->type eq "A";
print $rr->name;
}
}
else
{
warn "query failed: ", $res->errorstring, "\n";
return 0;
}
}
As long as $rr->name finds names, it keeps adding them.

Reverse DNS lookup in perl

How do I perform a reverse DNS lookup, that is how do I resolve an IP address to its DNS hostname in Perl?
If you need more detailed DNS info use the Net::DNS module, here is an example:
use Net::DNS;
my $res = Net::DNS::Resolver->new;
# create the reverse lookup DNS name (note that the octets in the IP address need to be reversed).
my $IP = "209.85.173.103";
my $target_IP = join('.', reverse split(/\./, $IP)).".in-addr.arpa";
my $query = $res->query("$target_IP", "PTR");
if ($query) {
foreach my $rr ($query->answer) {
next unless $rr->type eq "PTR";
print $rr->rdatastr, "\n";
}
} else {
warn "query failed: ", $res->errorstring, "\n";
}
Original Source EliteHackers.info, more details there as well.
gethostbyaddr and similar calls. See http://perldoc.perl.org/functions/gethostbyaddr.html
use Socket;
$iaddr = inet_aton("127.0.0.1"); # or whatever address
$name = gethostbyaddr($iaddr, AF_INET);
perl -MSocket -E 'say scalar gethostbyaddr(inet_aton("69.89.27.250"), AF_INET)'
Returns: Can't find string terminator "'" anywhere before EOF at -e line 1.
perl -MSocket -E "say scalar gethostbyaddr(inet_aton(\"69.89.27.250\"), AF_INET)"
Returns: box250.bluehost.com
I have to change the line to use double quotes and then escape out the quotes around the IP address
one-liner:
perl -MSocket -E 'say scalar gethostbyaddr(inet_aton("79.81.152.79"), AF_INET)'
There may be an easier way, but for IPv4, if you can perform ordinary DNS lookups, you can always construct the reverse query yourself. For the IPv4 address A.B.C.D, look up any PTR records at D.C.B.A.in-addr.arpa. For IPv6, you take the 128 hex nibbles and flip them around and append ipv6.arpa. and do the same thing.
If gethostbyaddr doesn't fit your needs, Net::DNS is more flexible.
This might be useful...
$ip = "XXX.XXX.XXX.XXX" # IPV4 address.
my #numbers = split (/\./, $ip);
if (scalar(#numbers) != 4)
{
print "$ip is not a valid IP address.\n";
next;
}
my $ip_addr = pack("C4", #numbers);
# First element of the array returned by gethostbyaddr is host name.
my ($name) = (gethostbyaddr($ip_addr, 2))[0];