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

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.