Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re: Need to calculate IP address

by johngg (Canon)
on Dec 29, 2017 at 00:39 UTC ( [id://1206381]=note: print w/replies, xml ) Need Help??


in reply to Need to calculate IP address

You could use inet_aton() and inet_ntoa() from the core Socket module for converting IPs. Use unpack to obtain a numeric value you can do an addition with. Then pack the result and convert back to a textual IP address.

johngg@shiraz:~/perl/Monks > perl -Mstrict -Mwarnings -MSocket -E ' do { print qq{Old IP: $_ ... }; my $isOdd = substr( $_, -1 ) % 2; my $IPn = unpack q{N}, inet_aton( $_ ); $IPn += ( $isOdd ? 1 : -1 ); my $newIP = inet_ntoa( pack( q{N}, $IPn ) ); say qq{New IP: $newIP}; } for qw{ 10.1.1.5 10.1.1.6 };' Old IP: 10.1.1.5 ... New IP: 10.1.1.6 Old IP: 10.1.1.6 ... New IP: 10.1.1.5

I hope this is of interest.

Update: Turning the one-liner into a script and adding an error check for invalid IPs (inet_aton() returns undef if given an invalid address). Because each valid IPv4 quad is in the range 0 .. 255 the "numeric" value produced by inet_aton() is actually a 4-byte string, e.g.

johngg@shiraz:~/perl/Monks > perl -Mstrict -Mwarnings -MSocket -E ' my $IP = q{10.1.1.255}; my $packed = inet_aton( $IP ); printf qq{%8d %8d %8d %8d\n}, map ord, split m{}, $packed; printf qq{%8s %8s %8s %8s\n}, unpack q{(B8)*}, $packed;' 10 1 1 255 00001010 00000001 00000001 11111111

That's why unpacking the string to a network-order number allows us to increment or decrement and also takes care of the roll-over when incrementing 255 or decrementing 0. The script.

use strict; use warnings; use Socket; my @IPs = qw{ 10.1.1.5 10.1.1.6 172.16.0.0 192.168.33.17 192.168.331.54 192.168.33.74 172.16.204.255 0.0.0.0 255.255.255.255 10.1.255.255 }; foreach my $IP ( @IPs ) { my $packed = inet_aton( $IP ); do { warn qq{Error: $IP is not a valid IPv4 address\n}; next; } unless defined $packed; my $numeric = unpack q{N}, $packed; my $isOdd = substr( $IP, -1 ) % 2; $numeric += ( $isOdd ? 1 : -1 ); my $newIP = inet_ntoa( pack( q{N}, $numeric ) ); printf qq{Old IP: %15s ... New IP: %15s\n}, $IP, $newIP; }

The output.

Old IP: 10.1.1.5 ... New IP: 10.1.1.6 Old IP: 10.1.1.6 ... New IP: 10.1.1.5 Old IP: 172.16.0.0 ... New IP: 172.15.255.255 Old IP: 192.168.33.17 ... New IP: 192.168.33.18 Error: 192.168.331.54 is not a valid IPv4 address Old IP: 192.168.33.74 ... New IP: 192.168.33.73 Old IP: 172.16.204.255 ... New IP: 172.16.205.0 Old IP: 0.0.0.0 ... New IP: 255.255.255.255 Old IP: 255.255.255.255 ... New IP: 0.0.0.0 Old IP: 10.1.255.255 ... New IP: 10.2.0.0

Update 2: Used printf to make the explanatory one-liner output more legible.

Update 3: Corrected spelling mistake s{adress}{address} d'oh.

Cheers,

JohnGG

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1206381]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2024-04-25 10:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found