Canonicalize CIDR: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Perl}}: Add comments, remove some extraneous parens.)
Line 6: Line 6:


=={{header|Perl}}==
=={{header|Perl}}==
<lang perl>
<lang perl>#!/usr/bin/env perl
#!/usr/bin/env perl
use v5.16;
use v5.16;
use Socket qw(inet_aton inet_ntoa);
use Socket qw(inet_aton inet_ntoa);
Line 17: Line 16:


for (@ARGV) {
for (@ARGV) {
# dotted-decimal / bits in network part
my ($dotted, $size) = split m#/#;
my ($dotted, $size) = split m#/#;

my $binary = sprintf "%032b", unpack('N', inet_aton($dotted));
# get IP as binary string
my $binary = sprintf "%032b", unpack('N', inet_aton $dotted);

# Replace the host part with all zeroes
substr($binary,$size) = "0" x (32 - $size);
substr($binary,$size) = "0" x (32 - $size);

$dotted = inet_ntoa(pack('B32', $binary));
# Convert back to dotted-decimal
$dotted = inet_ntoa(pack 'B32', $binary);

# And output
print "$dotted/$size\n";
print "$dotted/$size\n";
}</lang>
}
</lang>
{{Out}}
{{Out}}
<pre>$ canonicalize_cidr.pl 87.70.141.1/22
<pre>$ canonicalize_cidr.pl 87.70.141.1/22

Revision as of 03:54, 9 July 2020

Task
Canonicalize CIDR
You are encouraged to solve this task according to the task description, using any language you may know.

Implement a function or program that, given a range of IP addresses in CIDR notation (dotted-decimal/network-bits), will return/output the same range in canonical form, that is, with none of the host bits set.

Example: given 87.70.141.1/22, your code should output 87.70.140.0/22.

Perl

<lang perl>#!/usr/bin/env perl use v5.16; use Socket qw(inet_aton inet_ntoa);

  1. canonicalize a CIDR block: make sure none of the host bits are set

if (!@ARGV) {

  chomp(@ARGV = <>);

}

for (@ARGV) {

 # dotted-decimal / bits in network part
 my ($dotted, $size) = split m#/#;
 # get IP as binary string
 my $binary = sprintf "%032b", unpack('N', inet_aton $dotted);
 # Replace the host part with all zeroes
 substr($binary,$size) = "0" x (32 - $size);
 # Convert back to dotted-decimal
 $dotted = inet_ntoa(pack 'B32', $binary);
 # And output
 print "$dotted/$size\n";

}</lang>

Output:
$ canonicalize_cidr.pl 87.70.141.1/22
87.70.140.0/22

Python

Translation of: Perl

<lang python>

  1. !/usr/bin/env python
  2. canonicalize a CIDR block specification:
  3. make sure none of the host bits are set

import sys from socket import inet_aton, inet_ntoa from struct import pack, unpack

for cidr in sys.argv[1:]:

  # IP in dotted-decimal / bits in network part
  dotted, size_str = cidr.split('/')
  size = int(size_str)
  numeric = unpack('!I', inet_aton(dotted))[0]  # IP as an integer
  binary = f'{numeric:#034b}'                   # then as a padded binary string
  prefix = binary[:size + 2]                    # just the network part
                                                #   (34 and +2 are to account
                                                #    for leading '0b')
  canon_binary = prefix + '0' * (32 - size)     # replace host part with all zeroes
  canon_numeric = int(canon_binary, 2)          # convert back to integer
  canon_dotted = inet_ntoa(pack('!I',
                           (canon_numeric)))    # and then to dotted-decimal
  print(f'{canon_dotted}/{size}')               # output result

</lang>

Output:
$ canonicalize_cidr.py 87.70.141.1/22
87.70.140.0/22