[Ottawa-pm] CIDR to IP:netmask

allan.fields at gmail.com allan.fields at gmail.com
Fri Apr 1 12:19:54 PDT 2011


What do you'all do to get the netmask in dotted-quad form from CIDR?  Or apply the mask to your IP to get the subnet?

Does anyone have the arithmetic answer?  No modules allowed!  I do a bitwise-stringy version.

The reason I ask is I found this an interesting example of using perl's pack/unpack as an IP calculator.  Linux has a command named ipcalc, but you may know not all installs can just request specific binary/modules.

As a reminder CIDR for IPv4 is:
    IP ::= ([0-9]{1,3} '.' ){3} [0-9]{1,3}
    MASK ::= integer(0..32)
    CIDR ::= IP '/' MASK

Example (not meant to resemble real network):
    166.66.7.24/23
    166.66.7.0/23
    0.0.0.0/32
    1.2.3.4/22
    
I do something like:

If ($IPADDR=~qr{ \s* ['"]*
    ( (?:[0-9]{1,3}\.){3} [0-9]{1,3} ) /
    (     [0-9]{1,2}.                           )
['"]* \s* }x) {
    ($subnet_ip, $subnet_mask) = ($1,$2);

    if (not defined $subnet_mask or
        ($subnet_mask < 0 or $subnet_mask > 32)) {
        print "CIDR: Invalid mask\n";
        return 1;
    }

    my $bitstr = '1';
          $bitstr.= '0' x (32 - $subnet_mask);

    my $mask = join('.',unpack('C4',pack('B*',$bitstr)));

    print "IP: $subnet_ip Netmask: $mask\n";

    return 0;
} else {
    print "CIDR: Invalid\n"; 
    return 1:
}

# More advanced examples include calculating the subnet mask for two CIDR's and determining if they reside in the same range.

.. Tired of typing on my BB keyboard.
Please post your code.

Sent from my BlackBerry device on the Rogers Wireless Network


More information about the Ottawa-pm mailing list