An implementation:
use strict; use warnings; sub parse_ipv4 { local *_ = \(@_ ? $_[0] : $_); return unpack('N', pack('C4', split(/\./))); } sub format_ipv4 { local *_ = \(@_ ? $_[0] : $_); return join('.', unpack('C4', pack('N', $_))); } my $member = parse_ipv4('10.20.40.183'); my $mask = parse_ipv4('255.255.0.0'); my $first = $member & $mask; my $broadcast = $first | ~$mask; # my $num_machines = $broadcast - $first + 1 - 2; # which simplifies to: my $num_machines = ~$mask + 1 - 2; printf("first = %s\n", format_ipv4($first)); printf("mask = %s\n", format_ipv4($mask)); printf("broadcast = %s\n", format_ipv4($broadcast)); printf("first usable = %s\n", format_ipv4($first+1)); printf("last usable = %s\n", format_ipv4($broadcast-1)); printf("This subnet can handle %d machines:\n", $num_machines); # 128.x.x.x and higher pack into a negative number on # 32-bit machines, so the following won't work: # # print(format_ipv4, $/) # for ($first+1 .. $broadcast-1); if ($mask & 0x7FFFFFFF == 0) { print(format_ipv4($_), $/) for (1 .. 0x7FFFFFFF); print(format_ipv4($_|0x80000000), $/) for (0 .. 0x7FFFFFFE); } else { print(format_ipv4($_+$first), $/) for ($first+1-$first .. $broadcast-1-$first); } __END__ first = 10.20.0.0 mask = 255.255.0.0 broadcast = 10.20.255.255 first usable = 10.20.0.1 last usable = 10.20.255.254 This subnet can handle 65534 machines: 10.20.0.1 10.20.0.2 . . . 10.20.255.253 10.20.255.254
Update: Tweaks.
Update 2: Fixed for ($first+1 .. $broadcast-1).
Note: Requires a perl with 32-bit integers.
Note: I didn't write code to check if IP address and the mask are in the valid format.
sub parse_ipv4 { local *_ = \(@_ ? $_[0] : $_); /^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$/ && $1 < 256 && $2 < 256 && $3 < 256 && $4 < 256 or return undef; return unpack('N', pack('C4', $1, $2, $3, $4)); }
Note: The mask isn't validated. The binary representation of the mask must matched (length == 32 && /^1*0*$/) || $_ == 0.
Note: Keep in mind the above code can print over 4 billion addresses!
Mask Number of addresses printed /32 255.255.255.255 0 /31 255.255.255.254 0 /30 255.255.255.252 2 /29 255.255.255.248 6 /28 255.255.255.240 14 /27 255.255.255.240 30 /26 255.255.255.240 62 /25 255.255.255.240 126 /24 255.255.255.0 254 ... /16 255.255.0.0 65,534 ... /8 255.0.0.0 16,777,214 ... /3 224.0.0.0 536,870,910 /2 192.0.0.0 1,073,741,822 /1 128.0.0.0 2,147,483,646 /0 0.0.0.0 4,294,967,294
In reply to Enumerating IP Addresses in a Subnet
by ikegami
in thread algorithm for network address enumeration
by knave
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |