[lug] Calculating network addresses

Ralf Mattes rm at ns.aura.de
Wed Mar 8 10:43:45 MST 2000


On Wed, 8 Mar 2000, Ian Hall-Beyer wrote:

> 
> Does anyone hava  quick and dirty alogorithm for extrapolating a network
> address from an IP and subnet mask, preferably one that can be implemented
> in bash?
> 

Here a simple solution if you are willing to use/install the perl
Net::Netmask module

cat - > net_address.pl
#!/usr/bin/perl

use Net::Netmask;

my ($ip, $mask) = @ARGV;
my $net = new Net::Netmask($ip, $mask)
   or die "The values you gave me make no sense to me :-)\n";

printf (qq{

        IP: %s
   Netmask: %s
   Network: %s
 Broadcast: %s
  Hostmask: %s
      Bits: %s

}, $ip, $net->mask, $net->base, $net->broadcast, $net->hostmask, $net->bits);

exit 0;
^D

You then can type things like 'net_address.pl 192.168.2.44 255.255.255.248' or
'10.0.0.32/28'. If you want to code it yourself, you basically just have to
bitwise-and the IP-address and the netmask:

cat - > handcoded.pl
#!/usr/bin/perl

# get program arguments
# (we don't support xx.xxx.xxx.xxx/nnn
# notation here)
my ($ip, $mask) = @ARGV;

# convert ip to number
map { ($ip_num *=  256) += $_ }
split (/\.|:/, $ip);

# do the same thing for the netmask
map { ($mask_num *=  256) += $_ }
split (/\.|:/, $mask);

# get network address
$net_num = $ip_num & $mask_num;

# convert the network address back to
# ip notation
print join(".", unpack ("CCCC", pack("NNNN", $net_num))), "\n";

# of course, you coul use pack() also for
# the convertion to numbers, but that wouldn't
# be half as fun ;-)

exit 0;
^D

And here for a bash version (contibuted by courtesy of my collegue
Tomas) that still has a small 'bug':

cat - >net_bash.sh
#!/bin/bash

ptobin()
{
  a=0
  for i in ${1//./ } ; do
    a=$((256*$a + $i))
  done;
  echo $a
}

bintoip()
{
  bin=$1
  ip=$(($bin % 256))
  for x in 0 1 2 ; do
    bin=$(($bin / 256))
    ip=$(($(($bin % 256 + 256)) % 256)).$ip; # get rid of negatives
  done
  echo $ip
}

get_network()
{
   bintoip $((`iptobin $1` & `iptobin $2`))
}
^D

You can run '. net_bash.sh' and then use get_network in your
bash. The bug: if one of your IP address parts is greater than
127 the convertion will go wrong--the number will be one to big
(thanks to signed integers in bash ...). We'll leave this as an
exercise ... 

 Ralf

*-------------------------------------------------------------------*
|                                     |                             |==
| Ralf Mattes                         | rm at schauinsland.com         |==
| Programming, Administration         | rm at ns.aura.de               |==
|                                     |                             |==
*-------------------------------------------------------------------*==
   ====================================================================





More information about the LUG mailing list