Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Canonicalize-CIDR/00-META.yaml
Normal file
2
Task/Canonicalize-CIDR/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Canonicalize_CIDR
|
||||
27
Task/Canonicalize-CIDR/00-TASK.txt
Normal file
27
Task/Canonicalize-CIDR/00-TASK.txt
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
;Task:
|
||||
Implement a function or program that, given a range of IPv4 addresses in CIDR notation (dotted-decimal/network-bits), will return/output the same range in canonical form.
|
||||
|
||||
That is, the IP address portion of the output CIDR block must not contain any set (1) bits in the host part of the address.
|
||||
|
||||
|
||||
;Example:
|
||||
Given '''87.70.141.1/22''', your code should output '''87.70.140.0/22'''
|
||||
|
||||
|
||||
;Explanation:
|
||||
An Internet Protocol version 4 address is a 32-bit value, conventionally represented as a number in base 256 using dotted-decimal notation, where each base-256 digit is given in decimal and the digits are separated by periods. Logically, this 32-bit value represents two components: the leftmost (most-significant) bits determine the network portion of the address, while the rightmost (least-significant) bits determine the host portion. Classless Internet Domain Routing block notation indicates where the boundary between these two components is for a given address by adding a slash followed by the number of bits in the network portion.
|
||||
|
||||
In general, CIDR blocks stand in for the entire set of IP addresses sharing the same network component, so it's common to see access control lists that specify individual IP addresses using /32 to indicate that only the one address is included. Software accepting this notation as input often expects it to be entered in canonical form, in which the host bits are all zeroes. But network admins sometimes skip this step and just enter the address of a specific host on the subnet with the network size, resulting in a non-canonical entry.
|
||||
|
||||
The example address, 87.70.141.1/22, represents binary 0101011101000110100011 / 0100000001, with the / indicating the network/host division. To canonicalize, clear all the bits to the right of the / and convert back to dotted decimal: 0101011101000110100011 / 0000000000 → 87.70.140.0.
|
||||
|
||||
|
||||
;More examples for testing
|
||||
<pre>
|
||||
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
|
||||
</pre>
|
||||
<br><br>
|
||||
33
Task/Canonicalize-CIDR/11l/canonicalize-cidr.11l
Normal file
33
Task/Canonicalize-CIDR/11l/canonicalize-cidr.11l
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
F cidr_parse(str)
|
||||
V (addr_str, m_str) = str.split(‘/’)
|
||||
V (a, b, c, d) = addr_str.split(‘.’).map(Int)
|
||||
V m = Int(m_str)
|
||||
I m < 1 | m > 32
|
||||
| a < 0 | a > 255
|
||||
| b < 0 | b > 255
|
||||
| c < 0 | c > 255
|
||||
| d < 0 | d > 255
|
||||
R (0, 0)
|
||||
V mask = (-)((1 << (32 - m)) - 1)
|
||||
V address = (a << 24) + (b << 16) + (c << 8) + d
|
||||
address [&]= mask
|
||||
R (address, m)
|
||||
|
||||
F cidr_format(=address, mask_length)
|
||||
V d = address [&] F'F
|
||||
address >>= 8
|
||||
V c = address [&] F'F
|
||||
address >>= 8
|
||||
V b = address [&] F'F
|
||||
address >>= 8
|
||||
V a = address [&] F'F
|
||||
R a‘.’b‘.’c‘.’d‘/’mask_length
|
||||
|
||||
L(test) [‘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’]
|
||||
V (address, mask_length) = cidr_parse(test)
|
||||
print(‘#<18 -> #.’.format(test, cidr_format(address, mask_length)))
|
||||
121
Task/Canonicalize-CIDR/ALGOL-68/canonicalize-cidr.alg
Normal file
121
Task/Canonicalize-CIDR/ALGOL-68/canonicalize-cidr.alg
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
BEGIN # show IPv4 addresses in CIDR notation in canonical form #
|
||||
# mode to hold an IPv4 address in CIDR notation #
|
||||
MODE CIDR = STRUCT( BITS address
|
||||
, INT network bits
|
||||
, BOOL valid
|
||||
, STRING error
|
||||
);
|
||||
# returns a CIDR parsed from address #
|
||||
OP TOCIDR = ( STRING address text )CIDR:
|
||||
BEGIN
|
||||
STRING addr = "." + address text + "$";
|
||||
STRING error := "";
|
||||
BITS address := 16r0;
|
||||
INT bits count := 0;
|
||||
INT dot count := 0;
|
||||
INT slash count := 0;
|
||||
BOOL valid := TRUE;
|
||||
INT s pos := LWB addr;
|
||||
INT s max = UPB addr;
|
||||
WHILE s pos < s max AND valid DO
|
||||
IF addr[ s pos ] = "." THEN
|
||||
# must have an octet next #
|
||||
dot count +:= 1;
|
||||
INT octet := 0;
|
||||
INT digits := 0;
|
||||
WHILE CHAR c = addr[ s pos +:= 1 ];
|
||||
c >= "0" AND c <= "9"
|
||||
DO
|
||||
octet *:= 10 +:= ( ABS c - ABS "0" );
|
||||
digits +:= 1
|
||||
OD;
|
||||
address := ( address SHL 8 ) OR BIN ( octet MOD 256 );
|
||||
valid := valid AND digits > 0 AND digits < 4 AND octet < 256;
|
||||
IF NOT valid THEN error := "too many digits/octet to large" FI
|
||||
ELIF addr[ s pos ] = "/" THEN
|
||||
# must have the network mask length next #
|
||||
slash count +:= 1;
|
||||
WHILE CHAR c = addr[ s pos +:= 1 ];
|
||||
c >= "0" AND c <= "9"
|
||||
DO
|
||||
bits count *:= 10 +:= ( ABS c - ABS "0" )
|
||||
OD;
|
||||
# should be "$" ( end of string marker ) next #
|
||||
valid := valid AND addr[ s pos ] = "$";
|
||||
IF NOT valid THEN error := "bit length not followed by end-of-string" FI
|
||||
ELIF addr[ s pos ] = "$" THEN
|
||||
# end of address marker - must be the final character #
|
||||
valid := valid AND s pos = s max;
|
||||
IF NOT valid THEN error := "Invalid character: ""$""" FI
|
||||
ELSE
|
||||
# invalid character #
|
||||
valid := FALSE;
|
||||
error := "Invalid character: """ + addr[ s pos ] + """"
|
||||
FI
|
||||
OD;
|
||||
IF valid THEN
|
||||
# address is OK so far - check it had four octets and one mask length #
|
||||
valid := dot count = 4 # note a leading "." was added for parsing #
|
||||
AND slash count = 1
|
||||
AND bits count > 0
|
||||
AND bits count < 33;
|
||||
IF NOT valid THEN error := "too many dots, slashes or bits" FI
|
||||
FI;
|
||||
CIDR( address, bits count, valid, error )
|
||||
END # TOCIDR # ;
|
||||
# returns address in canonical form #
|
||||
OP CANONICALISE = ( CIDR address )CIDR:
|
||||
IF NOT valid OF address THEN
|
||||
# invalid address #
|
||||
address
|
||||
ELSE
|
||||
# valid address - retain the top most bits #
|
||||
CIDR( address OF address AND ( 16rffffffff
|
||||
SHL ( 32 - network bits OF address )
|
||||
)
|
||||
, network bits OF address
|
||||
, TRUE
|
||||
, ""
|
||||
)
|
||||
FI # CANONICALISE # ;
|
||||
# returns a readable form of address #
|
||||
OP TOSTRING = ( CIDR address )STRING:
|
||||
BEGIN
|
||||
[ 1 : 4 ]INT octet;
|
||||
BITS addr := address OF address;
|
||||
FOR o pos FROM UPB octet BY -1 TO LWB octet DO
|
||||
octet[ o pos ] := ABS ( addr AND 16rff );
|
||||
addr := addr SHR 8
|
||||
OD;
|
||||
STRING result := whole( octet[ LWB octet ], 0 );
|
||||
FOR o pos FROM 1 + LWB octet TO UPB octet DO
|
||||
result +:= "." + whole( octet[ o pos ], 0 )
|
||||
OD;
|
||||
result + "/" + whole( network bits OF address, 0 )
|
||||
END # TOSTRING # ;
|
||||
# task examples : input expected result #
|
||||
[,]STRING test cases = ( ( "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" )
|
||||
);
|
||||
FOR t pos FROM 1 LWB test cases TO 1 UPB test cases DO
|
||||
STRING addr = test cases[ t pos, 1 ];
|
||||
CIDR canon = CANONICALISE TOCIDR addr;
|
||||
IF NOT valid OF canon THEN
|
||||
print( ( "Invalid address: """, addr, """: ", error OF canon, newline ) )
|
||||
ELSE
|
||||
STRING actual = TOSTRING canon;
|
||||
STRING expected = test cases[ t pos, 2 ];
|
||||
print( ( addr
|
||||
, " -> "
|
||||
, actual
|
||||
, IF expected = actual THEN "" ELSE " ** EXPECTED: """ + expected + """" FI
|
||||
, newline
|
||||
)
|
||||
)
|
||||
FI
|
||||
OD
|
||||
END
|
||||
8
Task/Canonicalize-CIDR/APL/canonicalize-cidr-1.apl
Normal file
8
Task/Canonicalize-CIDR/APL/canonicalize-cidr-1.apl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
canonicalize←{
|
||||
nums←(2⊃⎕VFI)¨(~⍵∊'./')⊆⍵
|
||||
ip len←(4↑nums)(5⊃nums)
|
||||
ip←(32/2)⊤256⊥⊃¨ip
|
||||
ip←ip∧32↑len⍴1
|
||||
ip←(4/256)⊤2⊥ip
|
||||
(1↓∊'.',¨⍕¨ip),'/',⍕len
|
||||
}
|
||||
2
Task/Canonicalize-CIDR/APL/canonicalize-cidr-2.apl
Normal file
2
Task/Canonicalize-CIDR/APL/canonicalize-cidr-2.apl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
canonicalize '87.70.141.1/22'
|
||||
87.70.140.0/22
|
||||
78
Task/Canonicalize-CIDR/C++/canonicalize-cidr.cpp
Normal file
78
Task/Canonicalize-CIDR/C++/canonicalize-cidr.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
// Class representing an IPv4 address + netmask length
|
||||
class ipv4_cidr {
|
||||
public:
|
||||
ipv4_cidr() {}
|
||||
ipv4_cidr(std::uint32_t address, unsigned int mask_length)
|
||||
: address_(address), mask_length_(mask_length) {}
|
||||
std::uint32_t address() const {
|
||||
return address_;
|
||||
}
|
||||
unsigned int mask_length() const {
|
||||
return mask_length_;
|
||||
}
|
||||
friend std::istream& operator>>(std::istream&, ipv4_cidr&);
|
||||
private:
|
||||
std::uint32_t address_ = 0;
|
||||
unsigned int mask_length_ = 0;
|
||||
};
|
||||
|
||||
// Stream extraction operator, also performs canonicalization
|
||||
std::istream& operator>>(std::istream& in, ipv4_cidr& cidr) {
|
||||
int a, b, c, d, m;
|
||||
char ch;
|
||||
if (!(in >> a >> ch) || a < 0 || a > UINT8_MAX || ch != '.'
|
||||
|| !(in >> b >> ch) || b < 0 || b > UINT8_MAX || ch != '.'
|
||||
|| !(in >> c >> ch) || c < 0 || c > UINT8_MAX || ch != '.'
|
||||
|| !(in >> d >> ch) || d < 0 || d > UINT8_MAX || ch != '/'
|
||||
|| !(in >> m) || m < 1 || m > 32) {
|
||||
in.setstate(std::ios_base::failbit);
|
||||
return in;
|
||||
}
|
||||
uint32_t mask = ~((1 << (32 - m)) - 1);
|
||||
uint32_t address = (a << 24) + (b << 16) + (c << 8) + d;
|
||||
address &= mask;
|
||||
cidr.address_ = address;
|
||||
cidr.mask_length_ = m;
|
||||
return in;
|
||||
}
|
||||
|
||||
// Stream insertion operator
|
||||
std::ostream& operator<<(std::ostream& out, const ipv4_cidr& cidr) {
|
||||
uint32_t address = cidr.address();
|
||||
unsigned int d = address & UINT8_MAX;
|
||||
address >>= 8;
|
||||
unsigned int c = address & UINT8_MAX;
|
||||
address >>= 8;
|
||||
unsigned int b = address & UINT8_MAX;
|
||||
address >>= 8;
|
||||
unsigned int a = address & UINT8_MAX;
|
||||
out << a << '.' << b << '.' << c << '.' << d << '/'
|
||||
<< cidr.mask_length();
|
||||
return out;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const char* 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"
|
||||
};
|
||||
for (auto test : tests) {
|
||||
std::istringstream in(test);
|
||||
ipv4_cidr cidr;
|
||||
if (in >> cidr)
|
||||
std::cout << std::setw(18) << std::left << test << " -> "
|
||||
<< cidr << '\n';
|
||||
else
|
||||
std::cerr << test << ": invalid CIDR\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
63
Task/Canonicalize-CIDR/C-sharp/canonicalize-cidr.cs
Normal file
63
Task/Canonicalize-CIDR/C-sharp/canonicalize-cidr.cs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
string[] 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"
|
||||
};
|
||||
|
||||
foreach (string t in tests) Console.WriteLine($"{t} => {Canonicalize(t)}");
|
||||
}
|
||||
|
||||
static string Canonicalize(string cidr) => CIDR.Parse(cidr).Canonicalize().ToString();
|
||||
}
|
||||
|
||||
readonly struct CIDR
|
||||
{
|
||||
public readonly IPAddress ip;
|
||||
public readonly int length;
|
||||
|
||||
public static CIDR Parse(string cidr)
|
||||
{
|
||||
string[] parts = cidr.Split('/');
|
||||
return new CIDR(IPAddress.Parse(parts[0]), int.Parse(parts[1]));
|
||||
}
|
||||
|
||||
public CIDR(IPAddress ip, int length) => (this.ip, this.length) = (ip, length);
|
||||
|
||||
public CIDR Canonicalize() =>
|
||||
new CIDR(
|
||||
new IPAddress(
|
||||
ToBytes(
|
||||
ToInt(
|
||||
ip.GetAddressBytes()
|
||||
)
|
||||
& ~((1 << (32 - length)) - 1)
|
||||
)
|
||||
),
|
||||
length
|
||||
);
|
||||
|
||||
private int ToInt(byte[] bytes) => bytes.Aggregate(0, (n, b) => (n << 8) | b);
|
||||
|
||||
private byte[] ToBytes(int n)
|
||||
{
|
||||
byte[] bytes = new byte[4];
|
||||
for (int i = 3; i >= 0; i--) {
|
||||
bytes[i] = (byte)(n & 0xFF);
|
||||
n >>= 8;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public override string ToString() => $"{ip}/{length}";
|
||||
}
|
||||
64
Task/Canonicalize-CIDR/C/canonicalize-cidr.c
Normal file
64
Task/Canonicalize-CIDR/C/canonicalize-cidr.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct cidr_tag {
|
||||
uint32_t address;
|
||||
unsigned int mask_length;
|
||||
} cidr_t;
|
||||
|
||||
// Convert a string in CIDR format to an IPv4 address and netmask,
|
||||
// if possible. Also performs CIDR canonicalization.
|
||||
bool cidr_parse(const char* str, cidr_t* cidr) {
|
||||
int a, b, c, d, m;
|
||||
if (sscanf(str, "%d.%d.%d.%d/%d", &a, &b, &c, &d, &m) != 5)
|
||||
return false;
|
||||
if (m < 1 || m > 32
|
||||
|| a < 0 || a > UINT8_MAX
|
||||
|| b < 0 || b > UINT8_MAX
|
||||
|| c < 0 || c > UINT8_MAX
|
||||
|| d < 0 || d > UINT8_MAX)
|
||||
return false;
|
||||
uint32_t mask = ~((1 << (32 - m)) - 1);
|
||||
uint32_t address = (a << 24) + (b << 16) + (c << 8) + d;
|
||||
address &= mask;
|
||||
cidr->address = address;
|
||||
cidr->mask_length = m;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write a string in CIDR notation into the supplied buffer.
|
||||
void cidr_format(const cidr_t* cidr, char* str, size_t size) {
|
||||
uint32_t address = cidr->address;
|
||||
unsigned int d = address & UINT8_MAX;
|
||||
address >>= 8;
|
||||
unsigned int c = address & UINT8_MAX;
|
||||
address >>= 8;
|
||||
unsigned int b = address & UINT8_MAX;
|
||||
address >>= 8;
|
||||
unsigned int a = address & UINT8_MAX;
|
||||
snprintf(str, size, "%u.%u.%u.%u/%u", a, b, c, d,
|
||||
cidr->mask_length);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const char* 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"
|
||||
};
|
||||
for (int i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) {
|
||||
cidr_t cidr;
|
||||
if (cidr_parse(tests[i], &cidr)) {
|
||||
char out[32];
|
||||
cidr_format(&cidr, out, sizeof(out));
|
||||
printf("%-18s -> %s\n", tests[i], out);
|
||||
} else {
|
||||
fprintf(stderr, "%s: invalid CIDR\n", tests[i]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
100 REM THE BINARY OPS ONLY WORK ON SIGNED 16-BIT NUMBERS
|
||||
110 REM SO WE STORE THE IP ADDRESS AS AN ARRAY OF FOUR OCTETS
|
||||
120 DIM IP(3)
|
||||
130 REM READ DEMO DATA
|
||||
140 READ CI$
|
||||
150 IF CI$="" THEN END
|
||||
160 REM FIND /
|
||||
170 SL=0
|
||||
180 FOR I=LEN(CI$) TO 1 STEP -1
|
||||
190 : IF MID$(CI$,I,1)="/" THEN SL=I:I=1
|
||||
200 NEXT I
|
||||
210 IF SL=0 THEN PRINT "INVALID CIDR STRING: '"CI$"'":GOTO 140
|
||||
220 NW=VAL(MID$(CI$,SL+1))
|
||||
230 IF NW < 1 OR NW > 32 THEN PRINT "INVALID NETWORK WIDTH:"NW:GOTO 140
|
||||
240 REM PARSE OCTETS INTO IP ARRAY
|
||||
250 BY=0:N=0
|
||||
260 FOR I=1 TO SL-1
|
||||
270 : C$=MID$(CI$,I,1):IF C$<>"." THEN 300
|
||||
280 : IP(N)=BY:N=N+1:BY=0:IF IP(N-1)<256 THEN 310
|
||||
290 : PRINT "INVALID OCTET VALUE:"IP(N-1):GOTO 140
|
||||
300 : C=VAL(C$):IF C OR (C$="0") THEN BY=BY*10+C
|
||||
310 NEXT I
|
||||
320 IP(N)=BY:N=N+1:IF IP(N-1)>255 THEN 290
|
||||
330 REM NUMBER OF COMPLETE OCTETS IN NETWORK PART
|
||||
340 NB=INT(NW/8)
|
||||
350 REM NUMBER OF NETWORK BITS IN PARTIAL OCTET
|
||||
360 XB=NW AND 7
|
||||
370 REM ZERO OUT HOST BITS IN PARTIAL OCTET
|
||||
380 IP(NB) = IP(NB) AND (255 - 2^(8-XB) + 1)
|
||||
390 REM AND SET ANY ALL-HOST OCTETS TO 0
|
||||
400 IF NB<3 THEN FOR I=NB+1 TO 3:IP(I)=0 :NEXT I
|
||||
410 REM PRINT OUT THE RESULT
|
||||
420 PRINT MID$(STR$(IP(0)),2);
|
||||
430 FOR I=1 TO 3: PRINT "."MID$(STR$(IP( I)),2);:NEXT I
|
||||
440 PRINT MID$(CI$,SL)
|
||||
450 REM AND GO BACK FOR NEXT INPUT
|
||||
460 GOTO 140
|
||||
500 DATA 87.70.141.1/22, 36.18.154.103/12, 62.62.197.11/29
|
||||
510 DATA 67.137.119.181/4, 161.214.74.21/24, 184.232.176.184/18
|
||||
520 REM SOME INVALID INPUTS
|
||||
530 DATA 127.0.0.1, 123.45.67.89/0, 98.76.54.32/100, 123.456.789.0/12
|
||||
540 DATA
|
||||
34
Task/Canonicalize-CIDR/Common-Lisp/canonicalize-cidr.lisp
Normal file
34
Task/Canonicalize-CIDR/Common-Lisp/canonicalize-cidr.lisp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
(defun ip->bit-vector (ip)
|
||||
(flet ((int->bits (int)
|
||||
(loop :for i :below 8
|
||||
:collect (if (logbitp i int) 1 0) :into bits
|
||||
:finally (return (nreverse bits)))))
|
||||
(loop :repeat 4
|
||||
:with start := 0
|
||||
:for pos := (position #\. ip :start start)
|
||||
:collect (parse-integer ip :start start :end pos) :into res
|
||||
:while pos
|
||||
:do (setf start (1+ pos))
|
||||
:finally (return (apply #'concatenate 'bit-vector (mapcar #'int->bits res))))))
|
||||
|
||||
(defun bit-vector->ip (vec &optional n)
|
||||
(loop :repeat 4
|
||||
:for end :from 8 :by 8
|
||||
:for start := (- end 8)
|
||||
:for sub := (subseq vec start end)
|
||||
:collect (parse-integer (map 'string #'digit-char sub) :radix 2) :into res
|
||||
:finally (return (format nil "~{~D~^.~}~@[/~A~]" res n))))
|
||||
|
||||
(defun canonicalize-cidr (cidr)
|
||||
(let* ((n (position #\/ cidr))
|
||||
(ip (subseq cidr 0 n))
|
||||
(sn (parse-integer cidr :start (1+ n)))
|
||||
(ip* (ip->bit-vector ip))
|
||||
(canonical-ip (fill ip* 0 :start sn)))
|
||||
(bit-vector->ip canonical-ip sn)))
|
||||
|
||||
(loop :for cidr :in '("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 ccidr := (canonicalize-cidr cidr)
|
||||
:do (format t "~&~A~20,T→ ~A~%" cidr ccidr))
|
||||
82
Task/Canonicalize-CIDR/Cowgol/canonicalize-cidr.cowgol
Normal file
82
Task/Canonicalize-CIDR/Cowgol/canonicalize-cidr.cowgol
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
include "cowgol.coh";
|
||||
|
||||
typedef IP is uint32;
|
||||
|
||||
record CIDR is
|
||||
ip: IP;
|
||||
len: uint8;
|
||||
end record;
|
||||
|
||||
sub ParseIP(buffer: [uint8]): (result: IP, ptr: [uint8]) is
|
||||
var parts: uint8 := 4;
|
||||
var part: int32;
|
||||
result := 0;
|
||||
loop
|
||||
(part, buffer) := AToI(buffer);
|
||||
parts := parts - 1;
|
||||
result := result | ((part as IP & 0xFF) << (parts * 8));
|
||||
if parts == 0 then break;
|
||||
else buffer := @next buffer;
|
||||
end if;
|
||||
end loop;
|
||||
ptr := buffer;
|
||||
end sub;
|
||||
|
||||
sub ParseCIDR(buffer: [uint8], cidr: [CIDR]) is
|
||||
var len: int32;
|
||||
(cidr.ip, buffer) := ParseIP(buffer);
|
||||
(len, buffer) := AToI(@next buffer);
|
||||
cidr.len := len as uint8;
|
||||
end sub;
|
||||
|
||||
sub Canonicalize(cidr: [CIDR]) is
|
||||
var mask: IP := 0;
|
||||
var ones: uint8 := cidr.len;
|
||||
var len: uint8 := 32;
|
||||
while ones != 0 loop
|
||||
mask := (mask << 1) | 1;
|
||||
ones := ones - 1;
|
||||
len := len - 1;
|
||||
end loop;
|
||||
while len != 0 loop;
|
||||
mask := mask << 1;
|
||||
len := len - 1;
|
||||
end loop;
|
||||
cidr.ip := cidr.ip & mask;
|
||||
end sub;
|
||||
|
||||
sub FormatIP(ip: IP, buffer: [uint8]): (ptr: [uint8]) is
|
||||
ptr := buffer;
|
||||
ptr := UIToA((ip >> 24) & 0xFF, 10, ptr);
|
||||
[ptr] := '.';
|
||||
ptr := UIToA((ip >> 16) & 0xFF, 10, @next ptr);
|
||||
[ptr] := '.';
|
||||
ptr := UIToA((ip >> 8) & 0xFF, 10, @next ptr);
|
||||
[ptr] := '.';
|
||||
ptr := UIToA(ip & 0xFF, 10, @next ptr);
|
||||
[ptr] := 0;
|
||||
end sub;
|
||||
|
||||
sub FormatCIDR(cidr: [CIDR], buffer: [uint8]) is
|
||||
buffer := FormatIP(cidr.ip, buffer);
|
||||
[buffer] := '/';
|
||||
buffer := UIToA(cidr.len as uint32, 10, @next buffer);
|
||||
end sub;
|
||||
|
||||
var buffer: uint8[256];
|
||||
var string := &buffer[0];
|
||||
var cidr: CIDR;
|
||||
|
||||
ParseCIDR("87.70.141.1/22", &cidr);
|
||||
FormatCIDR(&cidr, string);
|
||||
|
||||
print("Before canonicalization: ");
|
||||
print(string);
|
||||
print_nl();
|
||||
|
||||
Canonicalize(&cidr);
|
||||
FormatCIDR(&cidr, string);
|
||||
|
||||
print(" After canonicalization: ");
|
||||
print(string);
|
||||
print_nl();
|
||||
22
Task/Canonicalize-CIDR/Factor/canonicalize-cidr.factor
Normal file
22
Task/Canonicalize-CIDR/Factor/canonicalize-cidr.factor
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
USING: command-line formatting grouping io kernel math.parser
|
||||
namespaces prettyprint sequences splitting ;
|
||||
IN: rosetta-code.canonicalize-cidr
|
||||
|
||||
! canonicalize a CIDR block: make sure none of the host bits are set
|
||||
command-line get [ lines ] when-empty
|
||||
[
|
||||
! ( CIDR-IP -- bits-in-network-part dotted-decimal )
|
||||
"/" split first2 string>number swap
|
||||
|
||||
! get IP as binary string
|
||||
"." split [ string>number "%08b" sprintf ] map "" join
|
||||
|
||||
! replace the host part with all zeros
|
||||
over cut length [ CHAR: 0 ] "" replicate-as append
|
||||
|
||||
! convert back to dotted-decimal
|
||||
8 group [ bin> number>string ] map "." join swap
|
||||
|
||||
! and output
|
||||
"%s/%d\n" printf
|
||||
] each
|
||||
61
Task/Canonicalize-CIDR/Go/canonicalize-cidr.go
Normal file
61
Task/Canonicalize-CIDR/Go/canonicalize-cidr.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// canonicalize a CIDR block: make sure none of the host bits are set
|
||||
func canonicalize(cidr string) string {
|
||||
// dotted-decimal / bits in network part
|
||||
split := strings.Split(cidr, "/")
|
||||
dotted := split[0]
|
||||
size, err := strconv.Atoi(split[1])
|
||||
check(err)
|
||||
|
||||
// get IP as binary string
|
||||
var bin []string
|
||||
for _, n := range strings.Split(dotted, ".") {
|
||||
i, err := strconv.Atoi(n)
|
||||
check(err)
|
||||
bin = append(bin, fmt.Sprintf("%08b", i))
|
||||
}
|
||||
binary := strings.Join(bin, "")
|
||||
|
||||
// replace the host part with all zeros
|
||||
binary = binary[0:size] + strings.Repeat("0", 32-size)
|
||||
|
||||
// convert back to dotted-decimal
|
||||
var canon []string
|
||||
for i := 0; i < len(binary); i += 8 {
|
||||
num, err := strconv.ParseInt(binary[i:i+8], 2, 64)
|
||||
check(err)
|
||||
canon = append(canon, fmt.Sprintf("%d", num))
|
||||
}
|
||||
|
||||
// and return
|
||||
return strings.Join(canon, ".") + "/" + split[1]
|
||||
}
|
||||
|
||||
func main() {
|
||||
tests := []string{
|
||||
"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 _, test := range tests {
|
||||
fmt.Printf("%-18s -> %s\n", test, canonicalize(test))
|
||||
}
|
||||
}
|
||||
44
Task/Canonicalize-CIDR/Hare/canonicalize-cidr.hare
Normal file
44
Task/Canonicalize-CIDR/Hare/canonicalize-cidr.hare
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
use fmt;
|
||||
use net::ip;
|
||||
use strings;
|
||||
|
||||
export fn main() void = {
|
||||
const array = ["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 (let i = 0z; i < len(array); i += 1) {
|
||||
match (canonicalizecidr(array[i])) {
|
||||
case let s: str =>
|
||||
fmt::printfln("{:-18} => {}", array[i], s)!;
|
||||
free(s);
|
||||
case net::ip::invalid =>
|
||||
fmt::errorfln("Error: invalid item: {}", array[i])!;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fn canonicalizecidr(a: str) (str | net::ip::invalid) = {
|
||||
const sub = net::ip::parsecidr(a)?;
|
||||
match (sub.addr) {
|
||||
case let addr4: net::ip::addr4 => void;
|
||||
case net::ip::addr6 => return net::ip::invalid;
|
||||
};
|
||||
|
||||
const net = sub.addr as [4]u8;
|
||||
const msk = sub.mask as [4]u8;
|
||||
|
||||
const net: u32 = net[0]: u32 << 24 | net[1]: u32 << 16 | net[2]: u32 << 8 | net[3]: u32;
|
||||
const msk: u32 = msk[0]: u32 << 24 | msk[1]: u32 << 16 | msk[2]: u32 << 8 | msk[3]: u32;
|
||||
|
||||
const result: u32 = net & msk;
|
||||
return fmt::asprintf("{}.{}.{}.{}/{}",
|
||||
result >> 24,
|
||||
0xff & result >> 16,
|
||||
0xff & result >> 8,
|
||||
0xff & result,
|
||||
strings::cut(a, "/").1);
|
||||
};
|
||||
78
Task/Canonicalize-CIDR/Haskell/canonicalize-cidr.hs
Normal file
78
Task/Canonicalize-CIDR/Haskell/canonicalize-cidr.hs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import Control.Monad (guard)
|
||||
import Data.Bits ((.|.), (.&.), complement, shiftL, shiftR, zeroBits)
|
||||
import Data.Maybe (listToMaybe)
|
||||
import Data.Word (Word32, Word8)
|
||||
import Text.ParserCombinators.ReadP (ReadP, char, readP_to_S)
|
||||
import Text.Printf (printf)
|
||||
import Text.Read.Lex (readDecP)
|
||||
|
||||
-- A 32-bit IPv4 address, with a netmask applied, and the number of leading bits
|
||||
-- that are in the network portion of the address.
|
||||
data CIDR = CIDR Word32 Word8
|
||||
|
||||
-- Convert a string to a CIDR, or nothing if it's invalid.
|
||||
cidrRead :: String -> Maybe CIDR
|
||||
cidrRead = listToMaybe . map fst . readP_to_S cidrP
|
||||
|
||||
-- Convert the CIDR to a string.
|
||||
cidrShow :: CIDR -> String
|
||||
cidrShow (CIDR addr n) = let (a, b, c, d) = octetsFrom addr
|
||||
in printf "%u.%u.%u.%u/%u" a b c d n
|
||||
|
||||
-- Parser for the string representation of a CIDR. For a successful parse the
|
||||
-- string must have the form a.b.c.d/n, where each of a, b, c and d are decimal
|
||||
-- numbers in the range [0, 255] and n is a decimal number in the range [0, 32].
|
||||
cidrP :: ReadP CIDR
|
||||
cidrP = do a <- octetP <* char '.'
|
||||
b <- octetP <* char '.'
|
||||
c <- octetP <* char '.'
|
||||
d <- octetP <* char '/'
|
||||
n <- netBitsP
|
||||
return $ CIDR (addrFrom a b c d .&. netmask n) n
|
||||
where octetP = wordP 255
|
||||
netBitsP = wordP 32
|
||||
|
||||
-- Parser for a decimal string, whose value is in the range [0, lim].
|
||||
--
|
||||
-- We want the limit argument to be an Integer, so that we can detect values
|
||||
-- that are too large, rather than having them silently wrap.
|
||||
wordP :: Integral a => Integer -> ReadP a
|
||||
wordP lim = do n <- readDecP
|
||||
guard $ n <= lim
|
||||
return $ fi n
|
||||
|
||||
-- The octets of an IPv4 address.
|
||||
octetsFrom :: Word32 -> (Word8, Word8, Word8, Word8)
|
||||
octetsFrom addr = (oct addr 3, oct addr 2, oct addr 1, oct addr 0)
|
||||
where oct w n = fi $ w `shiftR` (8*n) .&. 0xff
|
||||
|
||||
-- An IPv4 address from four octets. `ipAddr4 1 2 3 4' is the address 1.2.3.4.
|
||||
addrFrom :: Word8 -> Word8 -> Word8 -> Word8 -> Word32
|
||||
addrFrom a b c d = 0 <<+ a <<+ b <<+ c <<+ d
|
||||
where w <<+ o = w `shiftL` 8 .|. fi o
|
||||
|
||||
-- The value `netmask n' is the netmask whose leftmost n bits are 1, and the
|
||||
-- remainder are 0.
|
||||
netmask :: Word8 -> Word32
|
||||
netmask n = complement $ complement zeroBits `shiftR` fi n
|
||||
|
||||
fi :: (Integral a, Num b) => a -> b
|
||||
fi = fromIntegral
|
||||
|
||||
test :: String -> IO ()
|
||||
test str = do
|
||||
let cidrStr = maybe "invalid CIDR string" cidrShow (cidrRead str)
|
||||
printf "%-18s -> %s\n" str cidrStr
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
test "87.70.141.1/22"
|
||||
test "36.18.154.103/12"
|
||||
test "62.62.197.11/29"
|
||||
test "67.137.119.181/4"
|
||||
test "161.214.74.21/24"
|
||||
test "184.232.176.184/18"
|
||||
|
||||
test "184.256.176.184/12" -- octet value is too large
|
||||
test "184.232.176.184/33" -- netmask size is too large
|
||||
test "184.232.184/18" -- too few components
|
||||
4
Task/Canonicalize-CIDR/J/canonicalize-cidr-1.j
Normal file
4
Task/Canonicalize-CIDR/J/canonicalize-cidr-1.j
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
cidr=: {{
|
||||
'a e'=. 0 ".each (y rplc'. ')-.&;:'/'
|
||||
('/',":e),~rplc&' .'":_8#.\32{.e{.,(8#2)#:a
|
||||
}}
|
||||
12
Task/Canonicalize-CIDR/J/canonicalize-cidr-2.j
Normal file
12
Task/Canonicalize-CIDR/J/canonicalize-cidr-2.j
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
cidr '87.70.141.1/22'
|
||||
87.70.140.0/22
|
||||
cidr '36.18.154.103/12'
|
||||
36.16.0.0/12
|
||||
cidr '62.62.197.11/29'
|
||||
62.62.197.8/29
|
||||
cidr '67.137.119.181/4'
|
||||
64.0.0.0/4
|
||||
cidr '161.214.74.21/24'
|
||||
161.214.74.0/24
|
||||
cidr '184.232.176.184/18'
|
||||
184.232.128.0/18
|
||||
66
Task/Canonicalize-CIDR/Java/canonicalize-cidr.java
Normal file
66
Task/Canonicalize-CIDR/Java/canonicalize-cidr.java
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import java.text.MessageFormat;
|
||||
import java.text.ParseException;
|
||||
|
||||
public class CanonicalizeCIDR {
|
||||
public static void main(String[] args) {
|
||||
for (String test : TESTS) {
|
||||
try {
|
||||
CIDR cidr = new CIDR(test);
|
||||
System.out.printf("%-18s -> %s\n", test, cidr.toString());
|
||||
} catch (Exception ex) {
|
||||
System.err.printf("Error parsing '%s': %s\n", test, ex.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class CIDR {
|
||||
private CIDR(int address, int maskLength) {
|
||||
this.address = address;
|
||||
this.maskLength = maskLength;
|
||||
}
|
||||
|
||||
private CIDR(String str) throws Exception {
|
||||
Object[] args = new MessageFormat(FORMAT).parse(str);
|
||||
int address = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int a = ((Number)args[i]).intValue();
|
||||
if (a < 0 || a > 255)
|
||||
throw new Exception("Invalid IP address");
|
||||
address <<= 8;
|
||||
address += a;
|
||||
}
|
||||
int maskLength = ((Number)args[4]).intValue();
|
||||
if (maskLength < 1 || maskLength > 32)
|
||||
throw new Exception("Invalid mask length");
|
||||
int mask = ~((1 << (32 - maskLength)) - 1);
|
||||
this.address = address & mask;
|
||||
this.maskLength = maskLength;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
int address = this.address;
|
||||
int d = address & 0xFF;
|
||||
address >>= 8;
|
||||
int c = address & 0xFF;
|
||||
address >>= 8;
|
||||
int b = address & 0xFF;
|
||||
address >>= 8;
|
||||
int a = address & 0xFF;
|
||||
Object[] args = { a, b, c, d, maskLength };
|
||||
return new MessageFormat(FORMAT).format(args);
|
||||
}
|
||||
|
||||
private int address;
|
||||
private int maskLength;
|
||||
private static final String FORMAT = "{0,number,integer}.{1,number,integer}.{2,number,integer}.{3,number,integer}/{4,number,integer}";
|
||||
};
|
||||
|
||||
private static final String[] 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"
|
||||
};
|
||||
}
|
||||
50
Task/Canonicalize-CIDR/JavaScript/canonicalize-cidr.js
Normal file
50
Task/Canonicalize-CIDR/JavaScript/canonicalize-cidr.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
const canonicalize = s => {
|
||||
|
||||
// Prepare a DataView over a 16 Byte Array buffer.
|
||||
// Initialised to all zeros.
|
||||
const dv = new DataView(new ArrayBuffer(16));
|
||||
|
||||
// Get the ip-address and cidr components
|
||||
const [ip, cidr] = s.split('/');
|
||||
|
||||
// Make sure the cidr component is a usable int, and
|
||||
// default to 32 if it does not exist.
|
||||
const cidrInt = parseInt(cidr || 32, 10);
|
||||
|
||||
// Populate the buffer with uint8 ip address components.
|
||||
// Use zero as the default for shorthand pool definitions.
|
||||
ip.split('.').forEach(
|
||||
(e, i) => dv.setUint8(i, parseInt(e || 0, 10))
|
||||
);
|
||||
|
||||
// Grab the whole buffer as a uint32
|
||||
const ipAsInt = dv.getUint32(0);
|
||||
|
||||
// Zero out the lower bits as per the CIDR number.
|
||||
const normIpInt = (ipAsInt >> 32 - cidrInt) << 32 - cidrInt;
|
||||
|
||||
// Plonk it back into the buffer
|
||||
dv.setUint32(0, normIpInt);
|
||||
|
||||
// Read each of the uint8 slots in the buffer and join them with a dot.
|
||||
const canonIp = [...'0123'].map((e, i) => dv.getUint8(i)).join('.');
|
||||
|
||||
// Attach the cidr number to the back of the normalised IP address.
|
||||
return [canonIp, cidrInt].join('/');
|
||||
}
|
||||
|
||||
const test = s => console.log(s, '->', canonicalize(s));
|
||||
[
|
||||
'255.255.255.255/10',
|
||||
'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',
|
||||
'10.207.219.251/32',
|
||||
'10.207.219.251',
|
||||
'110.200.21/4',
|
||||
'10..55/8',
|
||||
'10.../8'
|
||||
].forEach(test)
|
||||
28
Task/Canonicalize-CIDR/Jq/canonicalize-cidr-1.jq
Normal file
28
Task/Canonicalize-CIDR/Jq/canonicalize-cidr-1.jq
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# For gojq and fq
|
||||
def _nwise($n):
|
||||
def nw: if length <= $n then . else .[0:$n] , (.[$n:] | nw) end;
|
||||
nw;
|
||||
|
||||
def lpad($len; $fill): tostring | ($len - length) as $l | ($fill * $l)[:$l] + .;
|
||||
def lpad($len): lpad($len;" ");
|
||||
|
||||
# Convert the input integer to a string in the specified base (2 to 36 inclusive)
|
||||
def convert(base):
|
||||
def stream:
|
||||
recurse(if . >= base then ./base|floor else empty end) | . % base ;
|
||||
[stream] | reverse
|
||||
| if base < 10 then map(tostring) | join("")
|
||||
elif base <= 36 then map(if . < 10 then 48 + . else . + 87 end) | implode
|
||||
else error("base too large")
|
||||
end;
|
||||
|
||||
# input string is converted from "base" to an integer, within limits
|
||||
# of the underlying arithmetic operations, and without error-checking:
|
||||
def to_i(base):
|
||||
explode
|
||||
| reverse
|
||||
| map(if . > 96 then . - 87 else . - 48 end) # "a" ~ 97 => 10 ~ 87
|
||||
| reduce .[] as $c
|
||||
# state: [power, ans]
|
||||
([1,0]; (.[0] * base) as $b | [$b, .[1] + (.[0] * $c)])
|
||||
| .[1];
|
||||
29
Task/Canonicalize-CIDR/Jq/canonicalize-cidr-2.jq
Normal file
29
Task/Canonicalize-CIDR/Jq/canonicalize-cidr-2.jq
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Canonicalize a CIDR block: make sure none of the host bits are set
|
||||
def canonicalize:
|
||||
# dotted-decimal / bits in network part
|
||||
(. / "/") as [$dotted, $bits]
|
||||
| ($bits | tonumber) as $size
|
||||
|
||||
# get IP as binary string
|
||||
| {binary: (($dotted / ".") | map( tonumber | convert(2) | lpad(8; "0") ) | join("") )}
|
||||
|
||||
# replace the host part with all zeros
|
||||
| .binary |= .[0:$size] + "0" * (32 - $size)
|
||||
|
||||
# convert back to dotted-decimal
|
||||
| [.binary | explode | _nwise(8) | implode]
|
||||
| (map( to_i(2) | tostring ) | join(".")) as $canon
|
||||
|
||||
| $canon + "/" + $bits;
|
||||
|
||||
def 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"
|
||||
;
|
||||
|
||||
tests
|
||||
| "\(lpad(18)) -> \(canonicalize)"
|
||||
19
Task/Canonicalize-CIDR/Julia/canonicalize-cidr.julia
Normal file
19
Task/Canonicalize-CIDR/Julia/canonicalize-cidr.julia
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
using Sockets
|
||||
|
||||
function canonCIDR(cidr::String)
|
||||
cidr = replace(cidr, r"\.(\.|\/)" => s".0\1") # handle ..
|
||||
cidr = replace(cidr, r"\.(\.|\/)" => s".0\1") # handle ...
|
||||
ip = split(cidr, "/")
|
||||
dig = length(ip) > 1 ? 2^(32 - parse(UInt8, ip[2])) : 1
|
||||
ip4 = IPv4(UInt64(IPv4(ip[1])) & (0xffffffff - dig + 1))
|
||||
return length(ip) == 1 ? "$ip4/32" : "$ip4/$(ip[2])"
|
||||
end
|
||||
|
||||
println(canonCIDR("87.70.141.1/22"))
|
||||
println(canonCIDR("100.68.0.18/18"))
|
||||
println(canonCIDR("10.4.30.77/30"))
|
||||
println(canonCIDR("10.207.219.251/32"))
|
||||
println(canonCIDR("10.207.219.251"))
|
||||
println(canonCIDR("110.200.21/4"))
|
||||
println(canonCIDR("10..55/8"))
|
||||
println(canonCIDR("10.../8"))
|
||||
10
Task/Canonicalize-CIDR/Lua/canonicalize-cidr.lua
Normal file
10
Task/Canonicalize-CIDR/Lua/canonicalize-cidr.lua
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
inet = require 'inet'
|
||||
|
||||
test_cases = {
|
||||
'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 i, cidr in ipairs(test_cases) do
|
||||
print( inet(cidr):network() )
|
||||
end
|
||||
28
Task/Canonicalize-CIDR/Mathematica/canonicalize-cidr.math
Normal file
28
Task/Canonicalize-CIDR/Mathematica/canonicalize-cidr.math
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
ClearAll[CanonicalizeCIDR]
|
||||
CanonicalizeCIDR[str_String] := Module[{i, ip, chop, keep, change},
|
||||
If[StringMatchQ[str, "*.*.*.*/*"],
|
||||
i = StringSplit[str, "." | "/"];
|
||||
i = Interpreter["Integer"] /@ i;
|
||||
If[MatchQ[i, {_Integer, _Integer, _Integer, _Integer, _Integer}],
|
||||
If[AllTrue[i, Between[{0, 255}]],
|
||||
{ip, {chop}} = TakeDrop[i, 4];
|
||||
ip = Catenate[IntegerDigits[ip, 2, 8]];
|
||||
{keep, change} = TakeDrop[ip, chop];
|
||||
change = ConstantArray[0, Length[change]];
|
||||
ip = Partition[Join[keep, change], 8];
|
||||
ip = ToString[FromDigits[#, 2]] & /@ ip;
|
||||
StringRiffle[ip, "."] <> "/" <> ToString[chop]
|
||||
,
|
||||
Failure["Invalid range of numbers", <|"Input" -> str|>]
|
||||
]
|
||||
,
|
||||
Failure["Invalid format", <|"Input" -> str|>]
|
||||
]
|
||||
]
|
||||
]
|
||||
CanonicalizeCIDR["87.70.141.1/22"]
|
||||
CanonicalizeCIDR["36.18.154.103/12"]
|
||||
CanonicalizeCIDR["62.62.197.11/29"]
|
||||
CanonicalizeCIDR["67.137.119.181/4"]
|
||||
CanonicalizeCIDR["161.214.74.21/24"]
|
||||
CanonicalizeCIDR["184.232.176.184/18"]
|
||||
57
Task/Canonicalize-CIDR/Nim/canonicalize-cidr.nim
Normal file
57
Task/Canonicalize-CIDR/Nim/canonicalize-cidr.nim
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import net
|
||||
import strutils
|
||||
|
||||
|
||||
proc canonicalize*(address: var IpAddress; nbits: Positive) =
|
||||
## Canonicalize an IP address.
|
||||
|
||||
var zbits = 32 - nbits # Number of bits to reset.
|
||||
|
||||
# We process byte by byte which avoids byte order issues.
|
||||
for idx in countdown(address.address_v4.high, address.address_v4.low):
|
||||
if zbits == 0:
|
||||
# No more bits to reset.
|
||||
break
|
||||
if zbits >= 8:
|
||||
# Reset the current byte and continue with the remaining bits.
|
||||
address.address_v4[idx] = 0
|
||||
dec zbits, 8
|
||||
else:
|
||||
# Use a mask to reset the bits.
|
||||
address.address_v4[idx] = address.address_v4[idx] and (0xff'u8 shl zbits)
|
||||
zbits = 0
|
||||
|
||||
#———————————————————————————————————————————————————————————————————————————————————————————————————
|
||||
|
||||
when isMainModule:
|
||||
|
||||
import strformat
|
||||
|
||||
var ipAddress: IpAddress
|
||||
var nbits: int
|
||||
|
||||
for address in ["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"]:
|
||||
|
||||
# Parse the address.
|
||||
let parts = address.split('/')
|
||||
try:
|
||||
ipAddress = parseIpAddress(parts[0])
|
||||
if ipAddress.family == IPV6:
|
||||
raise newException(ValueError, "")
|
||||
except ValueError:
|
||||
echo "Invalid IP V4 address: ", parts[0]
|
||||
quit(QuitFailure)
|
||||
|
||||
# Check the number of bits.
|
||||
try:
|
||||
nbits = parseInt(parts[1])
|
||||
if nbits notin 1..32:
|
||||
raise newException(ValueError, "")
|
||||
except ValueError:
|
||||
echo "Invalid number of bits: ", parts[1]
|
||||
quit(QuitFailure)
|
||||
|
||||
# Canonicalize the address and display the result.
|
||||
ipAddress.canonicalize(nbits)
|
||||
echo &"{address:<18} ⇢ {ipAddress}/{nbits}"
|
||||
22
Task/Canonicalize-CIDR/OCaml/canonicalize-cidr.ocaml
Normal file
22
Task/Canonicalize-CIDR/OCaml/canonicalize-cidr.ocaml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
let mask = function
|
||||
| _, 0 -> 0l, 0
|
||||
| a, l -> Int32.(logand (shift_left minus_one (-l land 31)) a), l
|
||||
|
||||
let str_to_cidr s =
|
||||
let (<<+) b a = Int32.(add (shift_left b 8) a) in
|
||||
let recv d c b a l = d <<+ c <<+ b <<+ a, l in
|
||||
Scanf.sscanf s "%3lu.%3lu.%3lu.%3lu/%2u" recv
|
||||
|
||||
let cidr_to_str (a, l) =
|
||||
let addr n =
|
||||
let dgt = function
|
||||
| h :: t -> Int32.shift_right_logical h 8 :: Int32.logand h 255l :: t
|
||||
| l -> l
|
||||
in
|
||||
dgt [n] |> dgt |> dgt |> List.map Int32.to_string |> String.concat "."
|
||||
in
|
||||
Printf.sprintf "%s/%u" (addr a) l
|
||||
|
||||
let () =
|
||||
["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"; "10.207.219.251/32"]
|
||||
|> List.iter (fun s -> str_to_cidr s |> mask |> cidr_to_str |> print_endline)
|
||||
26
Task/Canonicalize-CIDR/Perl/canonicalize-cidr.pl
Normal file
26
Task/Canonicalize-CIDR/Perl/canonicalize-cidr.pl
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env perl
|
||||
use v5.16;
|
||||
use Socket qw(inet_aton inet_ntoa);
|
||||
|
||||
# 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
|
||||
say "$dotted/$size";
|
||||
}
|
||||
35
Task/Canonicalize-CIDR/Phix/canonicalize-cidr.phix
Normal file
35
Task/Canonicalize-CIDR/Phix/canonicalize-cidr.phix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> <span style="color: #000080;font-style:italic;">-- (not likely useful)</span>
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">canonicalize_cidr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">cidr</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">cidr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cidr</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"."</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (else %d eats 0.0 etc)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'/'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cidr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">cidr</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">"/32"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">scanf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cidr</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d %d %d %d/%d"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">a</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">255</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">b</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">255</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">c</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">255</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">d</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">255</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">m</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">32</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">mask</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">-</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">addr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">bytes_to_int</span><span style="color: #0000FF;">({</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000000;">addr</span> <span style="color: #0000FF;">-=</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">addr</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mask</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">addr</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d.%d.%d.%d/%d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #008000;">"???"</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"87.70.141.1/22"</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #008000;">"36.18.154.103/12"</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #008000;">"62.62.197.11/29"</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #008000;">"67.137.119.181/4"</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #008000;">"161.214.74.21/24"</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #008000;">"184.232.176.184/18"</span><span style="color: #0000FF;">}</span>
|
||||
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">ti</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%-18s -> %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">,</span><span style="color: #000000;">canonicalize_cidr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">)})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<!--
|
||||
28
Task/Canonicalize-CIDR/PicoLisp/canonicalize-cidr.l
Normal file
28
Task/Canonicalize-CIDR/PicoLisp/canonicalize-cidr.l
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
(de cidr (S)
|
||||
(let
|
||||
(L (rot (mapcar format (split (chop S) "." "/")))
|
||||
N (++ L)
|
||||
M
|
||||
(&
|
||||
(sum >> (-24 -16 -8 0) L)
|
||||
(rev 32 (dec (** 2 N))) ) )
|
||||
(pack
|
||||
(>> 24 M)
|
||||
"."
|
||||
(& 255 (>> 16 M))
|
||||
"."
|
||||
(& 255 (>> 8 M))
|
||||
"."
|
||||
(& 255 (& 255 M))
|
||||
"/"
|
||||
N ) ) )
|
||||
(let Fmt (18 3 17)
|
||||
(for A
|
||||
(quote
|
||||
"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" )
|
||||
(tab Fmt A "=>" (cidr A)) ) )
|
||||
28
Task/Canonicalize-CIDR/Python/canonicalize-cidr-1.py
Normal file
28
Task/Canonicalize-CIDR/Python/canonicalize-cidr-1.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/env python
|
||||
# canonicalize a CIDR block specification:
|
||||
# make sure none of the host bits are set
|
||||
|
||||
import sys
|
||||
from socket import inet_aton, inet_ntoa
|
||||
from struct import pack, unpack
|
||||
|
||||
args = sys.argv[1:]
|
||||
if len(args) == 0:
|
||||
args = sys.stdin.readlines()
|
||||
|
||||
for cidr in args:
|
||||
# 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
|
||||
38
Task/Canonicalize-CIDR/Python/canonicalize-cidr-2.py
Normal file
38
Task/Canonicalize-CIDR/Python/canonicalize-cidr-2.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
"""Canonicalize CIDR"""
|
||||
DIGITS = (24, 16, 8, 0)
|
||||
|
||||
|
||||
def dotted_to_int(dotted: str) -> int:
|
||||
digits = [int(digit) for digit in dotted.split(".")]
|
||||
return sum(a << b for a, b in zip(digits, DIGITS))
|
||||
|
||||
|
||||
def int_to_dotted(ip: int) -> str:
|
||||
digits = [(ip & (255 << d)) >> d for d in DIGITS]
|
||||
return ".".join(str(d) for d in digits)
|
||||
|
||||
|
||||
def network_mask(number_of_bits: int) -> int:
|
||||
return ((1 << number_of_bits) - 1) << (32 - number_of_bits)
|
||||
|
||||
|
||||
def canonicalize(ip: str) -> str:
|
||||
dotted, network_bits = ip.split("/")
|
||||
i = dotted_to_int(dotted)
|
||||
mask = network_mask(int(network_bits))
|
||||
return int_to_dotted(i & mask) + "/" + network_bits
|
||||
|
||||
|
||||
TEST_CASES = [
|
||||
("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"),
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
for ip, expect in TEST_CASES:
|
||||
rv = canonicalize(ip)
|
||||
print(f"{ip:<18} -> {rv}")
|
||||
assert rv == expect
|
||||
18
Task/Canonicalize-CIDR/Python/canonicalize-cidr-3.py
Normal file
18
Task/Canonicalize-CIDR/Python/canonicalize-cidr-3.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import ipaddress
|
||||
|
||||
def canonicalize(address: str) -> str:
|
||||
return str(ipaddress.ip_network(address, strict=False))
|
||||
|
||||
TEST_CASES = [
|
||||
("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"),
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
for ip, expect in TEST_CASES:
|
||||
rv = canonicalize(ip)
|
||||
print(f"{ip:<18} -> {rv}")
|
||||
assert rv == expect, expect
|
||||
32
Task/Canonicalize-CIDR/REXX/canonicalize-cidr.rexx
Normal file
32
Task/Canonicalize-CIDR/REXX/canonicalize-cidr.rexx
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*REXX pgm canonicalizes IPv4 addresses that are in CIDR notation (dotted─dec/network).*/
|
||||
parse arg a . /*obtain optional argument from the CL.*/
|
||||
if a=='' | a=="," then a= '87.70.141.1/22' , /*Not specified? Then use the defaults*/
|
||||
'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'
|
||||
|
||||
do i=1 for words(a); z= word(a, i) /*process each IPv4 address in the list*/
|
||||
parse var z # '/' -0 mask /*get the address nodes & network mask.*/
|
||||
#= subword( translate(#, , .) 0 0 0, 1, 4) /*elide dots from addr, ensure 4 nodes.*/
|
||||
$= # /*use original node address (for now). */
|
||||
hb= 32 - substr(word(mask .32, 1), 2) /*obtain the size of the host bits. */
|
||||
$=; ##= /*crop the host bits only if mask ≤ 32.*/
|
||||
do k=1 for 4; _= word(#, k) /*create a 32-bit (binary) IPv4 address*/
|
||||
##= ## || right(d2b(_), 8, 0) /*append eight bits of the " " */
|
||||
end /*k*/ /* [↑] ... and ensure a node is 8 bits.*/
|
||||
##= left(##, 32-hb, 0) /*crop bits in host part of IPv4 addr. */
|
||||
##= left(##, 32, 0) /*replace cropped bits with binary '0's*/
|
||||
do j=8 by 8 for 4 /* [↓] parse the four nodes of address*/
|
||||
$= $ || . || b2d(substr(##, j-7, 8)) /*reconstitute the decimal nodes. */
|
||||
end /*j*/ /* [↑] and insert a dot between nodes.*/
|
||||
say /*introduce a blank line between IPv4's*/
|
||||
$= substr($, 2) /*elid the leading decimal point in $ */
|
||||
say ' original IPv4 address: ' z /*display the original IPv4 address. */
|
||||
say ' canonicalized address: ' translate( space($), ., " ")mask /*canonicalized.*/
|
||||
end /*i*/
|
||||
exit 0 /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
b2d: return x2d( b2x( arg(1) ) ) + 0 /*convert binary ───► decimal number.*/
|
||||
d2b: return x2b( d2x( arg(1) ) ) + 0 /* " decimal ───► binary " */
|
||||
4
Task/Canonicalize-CIDR/Raku/canonicalize-cidr-1.raku
Normal file
4
Task/Canonicalize-CIDR/Raku/canonicalize-cidr-1.raku
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
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)";
|
||||
}
|
||||
29
Task/Canonicalize-CIDR/Raku/canonicalize-cidr-2.raku
Normal file
29
Task/Canonicalize-CIDR/Raku/canonicalize-cidr-2.raku
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#!/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";
|
||||
}
|
||||
35
Task/Canonicalize-CIDR/Raku/canonicalize-cidr-3.raku
Normal file
35
Task/Canonicalize-CIDR/Raku/canonicalize-cidr-3.raku
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# 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;
|
||||
25
Task/Canonicalize-CIDR/Ruby/canonicalize-cidr-1.rb
Normal file
25
Task/Canonicalize-CIDR/Ruby/canonicalize-cidr-1.rb
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# canonicalize a CIDR block: make sure none of the host bits are set
|
||||
if ARGV.length == 0 then
|
||||
ARGV = $stdin.readlines.map(&:chomp)
|
||||
end
|
||||
|
||||
ARGV.each do |cidr|
|
||||
|
||||
# dotted-decimal / bits in network part
|
||||
dotted, size_str = cidr.split('/')
|
||||
size = size_str.to_i
|
||||
|
||||
# get IP as binary string
|
||||
binary = dotted.split('.').map { |o| "%08b" % o }.join
|
||||
|
||||
# Replace the host part with all zeroes
|
||||
binary[size .. -1] = '0' * (32 - size)
|
||||
|
||||
# Convert back to dotted-decimal
|
||||
canon = binary.chars.each_slice(8).map { |a| a.join.to_i(2) }.join('.')
|
||||
|
||||
# And output
|
||||
puts "#{canon}/#{size}"
|
||||
end
|
||||
9
Task/Canonicalize-CIDR/Ruby/canonicalize-cidr-2.rb
Normal file
9
Task/Canonicalize-CIDR/Ruby/canonicalize-cidr-2.rb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
require "ipaddr"
|
||||
|
||||
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"]
|
||||
|
||||
tests.each do |str|
|
||||
ia = IPAddr.new(str)
|
||||
puts "#{ia}/#{ia.prefix}"
|
||||
end
|
||||
39
Task/Canonicalize-CIDR/Rust/canonicalize-cidr.rust
Normal file
39
Task/Canonicalize-CIDR/Rust/canonicalize-cidr.rust
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
use std::net::Ipv4Addr;
|
||||
|
||||
fn canonical_cidr(cidr: &str) -> Result<String, &str> {
|
||||
let mut split = cidr.splitn(2, '/');
|
||||
if let (Some(addr), Some(mask)) = (split.next(), split.next()) {
|
||||
let addr = addr.parse::<Ipv4Addr>().map(u32::from).map_err(|_| cidr)?;
|
||||
let mask = mask.parse::<u8>().map_err(|_| cidr)?;
|
||||
let bitmask = 0xff_ff_ff_ffu32 << (32 - mask);
|
||||
let addr = Ipv4Addr::from(addr & bitmask);
|
||||
Ok(format!("{}/{}", addr, mask))
|
||||
} else {
|
||||
Err(cidr)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
#[test]
|
||||
fn valid() {
|
||||
[
|
||||
("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"),
|
||||
]
|
||||
.iter()
|
||||
.cloned()
|
||||
.for_each(|(input, expected)| {
|
||||
assert_eq!(expected, super::canonical_cidr(input).unwrap());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{}", canonical_cidr("127.1.2.3/24").unwrap());
|
||||
}
|
||||
48
Task/Canonicalize-CIDR/Snobol/canonicalize-cidr.sno
Normal file
48
Task/Canonicalize-CIDR/Snobol/canonicalize-cidr.sno
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
* Pattern to match any number of digits
|
||||
D = SPAN('0123456789')
|
||||
|
||||
* Convert a dotted-decimal IP address to an integer
|
||||
DEFINE('INET_ATON(Str),B3,B2,B1,B0') :(END_INET_ATON)
|
||||
INET_ATON Str D . B3 '.' D . B2 '.' D . B1 '.' D . B0 :F(FRETURN)
|
||||
INET_ATON = B3 * 16777216 + B2 * 65536 + B1 * 256 + B0 :(RETURN)
|
||||
END_INET_ATON
|
||||
|
||||
* Convert an integer to dotted-decimal
|
||||
DEFINE('INET_NTOA(Addr),Count,Byte') :(END_INET_NTOA)
|
||||
INET_NTOA Count = 0
|
||||
N2ALOOP Byte = REMDR(Addr,256)
|
||||
Addr = (Addr - Byte) / 256
|
||||
INET_NTOA = Byte '.' INET_NTOA
|
||||
Count = Count + 1
|
||||
LT(Count,4) :S(N2ALOOP)
|
||||
INET_NTOA '.' RPOS(0) = '' :(RETURN)
|
||||
END_INET_NTOA
|
||||
|
||||
* Convert a CIDR range to canonical form
|
||||
DEFINE('FIXCIDR(Cidr),IP,Net,In,Host,Count,Pow,Out,Bit') :(END_FIXCIDR)
|
||||
FIXCIDR Cidr Arb . IP '/' D . Net :F(FRETURN)
|
||||
In = INET_ATON(IP)
|
||||
Host = 32 - Net
|
||||
|
||||
* Compute result of treating all bits in the host part as 0
|
||||
Out = 0
|
||||
Count = 0
|
||||
Pow = 1
|
||||
MASKLOOP Bit = REMDR(In, 2)
|
||||
In = (In - Bit) / 2
|
||||
Out = GE(Count, Host) Out + Bit * Pow
|
||||
Count = Count + 1
|
||||
Pow = Pow * 2
|
||||
LT(Count, 32) :S(MASKLOOP)
|
||||
|
||||
* Convert back to dotted-decimal
|
||||
FIXCIDR = INET_NTOA(Out) '/' Net :(RETURN)
|
||||
END_FIXCIDR
|
||||
|
||||
OUTPUT = FIXCIDR('87.70.141.1/22')
|
||||
OUTPUT = FIXCIDR('36.18.154.103/12')
|
||||
OUTPUT = FIXCIDR('62.62.197.11/29')
|
||||
OUTPUT = FIXCIDR('67.137.119.181/4')
|
||||
OUTPUT = FIXCIDR('161.214.74.21/24')
|
||||
OUTPUT = FIXCIDR('184.232.176.184/18')
|
||||
END
|
||||
3
Task/Canonicalize-CIDR/TXR/canonicalize-cidr-1.txr
Normal file
3
Task/Canonicalize-CIDR/TXR/canonicalize-cidr-1.txr
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
(defun cidr-canon (str)
|
||||
(let ((a (inaddr-str str)))
|
||||
`@(str-inaddr a.addr)/@{a.prefix}`))
|
||||
3
Task/Canonicalize-CIDR/TXR/canonicalize-cidr-2.txr
Normal file
3
Task/Canonicalize-CIDR/TXR/canonicalize-cidr-2.txr
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
(defun cidr-canon (str)
|
||||
(let ((a (inaddr-str str)))
|
||||
(str-inaddr-net a.addr a.prefix)))
|
||||
4
Task/Canonicalize-CIDR/TXR/canonicalize-cidr-3.txr
Normal file
4
Task/Canonicalize-CIDR/TXR/canonicalize-cidr-3.txr
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(defun cidr-canon (str)
|
||||
(flow str
|
||||
inaddr-str
|
||||
(str-inaddr-net @1.addr @1.prefix)))
|
||||
45
Task/Canonicalize-CIDR/UNIX-Shell/canonicalize-cidr.sh
Normal file
45
Task/Canonicalize-CIDR/UNIX-Shell/canonicalize-cidr.sh
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
function inet_aton {
|
||||
typeset -i addr byte
|
||||
typeset -a bytes
|
||||
if [[ -n $BASH_VERSION ]]; then
|
||||
IFS=. read -a bytes <<<"$1"
|
||||
elif [[ -n $ZSH_VERSION ]]; then
|
||||
IFS=. bytes=($=1)
|
||||
else
|
||||
IFS=. bytes=($1)
|
||||
fi
|
||||
addr=0
|
||||
for byte in "${bytes[@]}"; do
|
||||
(( addr = 256 * addr + byte ))
|
||||
done
|
||||
printf '%s\n' "$addr"
|
||||
}
|
||||
|
||||
function inet_ntoa {
|
||||
typeset -i addr=$1
|
||||
typeset dotted i
|
||||
for (( i=0; i<4; ++i )); do
|
||||
dotted=$(( addr & 255 ))${dotted:+.$dotted}
|
||||
(( addr >>= 8 ))
|
||||
done
|
||||
printf '%s\n' "$dotted"
|
||||
}
|
||||
|
||||
function canonicalize_cidr {
|
||||
typeset ip prefix fixed
|
||||
typeset -i netmask addr
|
||||
while (( $# )); do
|
||||
IFS=/ read ip prefix <<<"$1"
|
||||
netmask=$(( (-1 << (32-prefix)) & -1 ))
|
||||
addr=$(inet_aton "$ip")
|
||||
fixed=$(( addr & netmask ))
|
||||
printf '%s/%s\n' "$(inet_ntoa $fixed)" "$prefix"
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
# demo code
|
||||
if (( ! $# )); then
|
||||
set -- 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
|
||||
fi
|
||||
canonicalize_cidr "$@"
|
||||
36
Task/Canonicalize-CIDR/Wren/canonicalize-cidr.wren
Normal file
36
Task/Canonicalize-CIDR/Wren/canonicalize-cidr.wren
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import "/fmt" for Fmt, Conv
|
||||
import "/str" for Str
|
||||
|
||||
// canonicalize a CIDR block: make sure none of the host bits are set
|
||||
var canonicalize = Fn.new { |cidr|
|
||||
// dotted-decimal / bits in network part
|
||||
var split = cidr.split("/")
|
||||
var dotted = split[0]
|
||||
var size = Num.fromString(split[1])
|
||||
|
||||
// get IP as binary string
|
||||
var binary = dotted.split(".").map { |n| Fmt.swrite("$08b", Num.fromString(n)) }.join()
|
||||
|
||||
// replace the host part with all zeros
|
||||
binary = binary[0...size] + "0" * (32 - size)
|
||||
|
||||
// convert back to dotted-decimal
|
||||
var chunks = Str.chunks(binary, 8)
|
||||
var canon = chunks.map { |c| Conv.atoi(c, 2) }.join(".")
|
||||
|
||||
// and return
|
||||
return canon + "/" + split[1]
|
||||
}
|
||||
|
||||
var 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"
|
||||
]
|
||||
|
||||
for (test in tests) {
|
||||
Fmt.print("$-18s -> $s", test, canonicalize.call(test))
|
||||
}
|
||||
32
Task/Canonicalize-CIDR/XPL0/canonicalize-cidr.xpl0
Normal file
32
Task/Canonicalize-CIDR/XPL0/canonicalize-cidr.xpl0
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
proc Canonicalize(IPAddr);
|
||||
char IPAddr;
|
||||
int N, I, HostBits;
|
||||
[Text(0, IPAddr);
|
||||
Text(0, " ^i-> "); \^i = tab
|
||||
OpenO(8);
|
||||
Text(8, IPAddr); \ASCII out
|
||||
OpenI(8);
|
||||
N:= 0;
|
||||
for I:= 0 to 3 do
|
||||
N:= N<<8 + IntIn(8); \binary in
|
||||
HostBits:= IntIn(8);
|
||||
N:= N & -1<<(32-HostBits);
|
||||
for I:= 3 downto 0 do
|
||||
[IntOut(0, N>>(I*8) & $FF);
|
||||
ChOut(0, if I = 0 then ^/ else ^.);
|
||||
];
|
||||
IntOut(0, HostBits);
|
||||
CrLf(0);
|
||||
];
|
||||
|
||||
int IPAddrs, I;
|
||||
[IPAddrs:= [
|
||||
"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 I:= 0 to 6-1 do
|
||||
Canonicalize(IPAddrs(I));
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue