Canonicalize CIDR
Using library
use IP::Addr;
for «87.70.141.1/22 36.18.154.103/12 62.62.197.11/29 67.137.119.181/4 161.214.74.21/24 184.232.176.184/18» -> $cidr {
say "$cidr -> $(IP::Addr.new($cidr).network)";
}
String manipulation
#!/usr/bin/env raku
unit sub MAIN(*@cidrs);
if !@cidrs {
# test data
@cidrs = «87.70.141.1/22 36.18.154.103/12 62.62.197.11/29 67.137.119.181/4 161.214.74.21/24 184.232.176.184/18»;
}
for @cidrs -> $cidr {
say "$cidr -> $(canonicalize $cidr)";
}
# canonicalize a CIDR block: make sure none of the host bits are set
sub canonicalize($cidr) {
# dotted-decimal / bits in network part
my ($dotted, $size) = $cidr.split: '/';
# get network part of the IP as binary string
my $binary = $dotted.split('.')».fmt('%08b').join.substr(0, $size);
# Add host part with all zeroes
$binary ~= 0 x (32 - $size);
# Convert back to dotted-decimal
my $canon = $binary.comb(8)».parse-base(2).join: '.';
# And output
say "$canon/$size";
}
Output:
87.70.141.1/22 -> 87.70.140.0/22
36.18.154.103/12 -> 36.16.0.0/12
62.62.197.11/29 -> 62.62.197.8/29
67.137.119.181/4 -> 64.0.0.0/4
161.214.74.21/24 -> 161.214.74.0/24
184.232.176.184/18 -> 184.232.128.0/18
Bit mask and shift
# canonicalize a IP4 CIDR block
sub CIDR-IP4-canonicalize ($address) {
constant @mask = 24, 16, 8, 0;
# dotted-decimal / subnet size
my ($dotted, $size) = |$address.split('/'), 32;
# get IP as binary address
my $binary = sum $dotted.comb(/\d+/) Z+< @mask;
# mask off subnet
$binary +&= (2 ** $size - 1) +< (32 - $size);
# Return dotted-decimal notation
(@mask.map($binary +> * +& 0xFF).join('.'), $size)
}
my @tests = <
87.70.141.1/22
36.18.154.103/12
62.62.197.11/29
67.137.119.181/4
161.214.74.21/24
184.232.176.184/18
100.68.0.18/18
10.4.30.77/30
10.207.219.251/32
10.207.219.251
110.200.21/4
10.11.12.13/8
10.../8
>;
printf "CIDR: %18s Routing prefix: %s/%s\n", $_, |.&CIDR-IP4-canonicalize
for @*ARGS || @tests;
Output:
CIDR: 87.70.141.1/22 Routing prefix: 87.70.140.0/22
CIDR: 36.18.154.103/12 Routing prefix: 36.16.0.0/12
CIDR: 62.62.197.11/29 Routing prefix: 62.62.197.8/29
CIDR: 67.137.119.181/4 Routing prefix: 64.0.0.0/4
CIDR: 161.214.74.21/24 Routing prefix: 161.214.74.0/24
CIDR: 184.232.176.184/18 Routing prefix: 184.232.128.0/18
CIDR: 100.68.0.18/18 Routing prefix: 100.68.0.0/18
CIDR: 10.4.30.77/30 Routing prefix: 10.4.30.76/30
CIDR: 10.207.219.251/32 Routing prefix: 10.207.219.251/32
CIDR: 10.207.219.251 Routing prefix: 10.207.219.251/32
CIDR: 110.200.21/4 Routing prefix: 96.0.0.0/4
CIDR: 10.11.12.13/8 Routing prefix: 10.0.0.0/8
CIDR: 10.../8 Routing prefix: 10.0.0.0/8
Last updated