From what I can tell, there aren’t many…if any, IPv6 address range calculators. While I read it is recommended that you use the entire /64 block, I don’t think it’s always necessary to do so. Besides, what happens when you want to route only a portion of the block to one place?
Example usage:
ipv6range.ps1 2001:470:1f10:60::10 64 | ft ipaddress* ipv6range.ps1 2003:5:1f:fa0::10 104 | ft ipaddress* #ipv4 /8 equivalent ipv6range.ps1 2003:5:1f:fa0::10 112 | ft ipaddress* #ipv4 /16 equivalent ipv6range.ps1 2003:5:1f:fa0::10 120 | ft ipaddress* #ipv4 /24 equivalent ipv6range.ps1 2003:5:1f:fa0::10 124 | ft ipaddress* #ipv4 /28 equivalent
….and the code….
param(
[net.ipaddress]$Addr,
[int]$netmask = 64,
[switch]$ForceListing
)
if($Addr.AddressFamily -ne 'InterNetworkV6') { throw "`$Addr must be a valid IPv6 address."; }
<#
Create a subnet mask based on a CIDR input.
#>
function subnet {
param(
[int]$netmask
)
if($netmask -gt 128) { throw "`$netmask cannot be greater than 128"; }
$mask = (@($true) * $netmask) + (@($false) * (128-$netmask));
return New-Object Collections.BitArray @(,$mask);
}
<#
Convert a BitArray into a byte array for easy conversion into an IPAddress.
#>
function bit2byte {
param(
[Collections.BitArray]$bitArray
)
for($i = 0; $i -lt $bitArray.length; $i+=8) {
[convert]::ToByte([string]::Join("", ([string[]][byte[]]($bitArray[$i..($i+7)]))), 2)
}
}
<#
convert an ip into a BitArray for easy bitwise operations.
#>
function ip2bit {
param([net.ipaddress]$addr)
$b = $addr.GetAddressBytes();
$bits = @();
foreach($a in $b) {
$t = [convert]::ToString($a,2).padleft(8,"0") #[7..0];
$bits += [string]::join("",$t);
}
$nbits = ($bits | %{[char[]]$_} | %{[bool]::Parse("$_".replace("1","true").replace("0","false"))});
return New-Object collections.bitarray @(,$nbits)
}
<#
Increment an ipv6 address.
#>
function inc {
param([net.ipaddress]$addr)
$b = $addr.GetAddressBytes();
for($i = $b.length-1; $i -ge 0; $i--) {
if($b[$i] -gt 254) { continue; }
$b[$i]++;
break;
}
New-Object net.ipaddress @(,$b);
}
<#
Decrement an ipv6 address.
#>
function dec {
param([net.ipaddress]$addr)
$b = $addr.GetAddressBytes();
for($i = $b.length-1; $i -ge 0; $i--) {
if($b[$i] -eq 0) { continue; }
$b[$i]--;
break;
}
New-Object net.ipaddress @(,$b);
}
$ipArr = new-object collections.bitarray @(,(ip2bit $Addr.GetAddressBytes()))
$netBits = New-Object collections.bitarray @(,(subnet $netmask))
$hostBits = (New-Object collections.bitarray $netBits).Xor((New-Object collections.bitarray 128, $true)) #.xor((New-Object collections.bitarray 128, $true))
$netId = New-Object net.ipaddress @(, (bit2byte (New-Object collections.bitarray $ipArr).And($netBits)));
$netBcast = New-Object net.ipaddress @(, (bit2byte (New-Object collections.bitarray $ipArr).Or($hostBits)));
$numHosts = [math]::Pow(2, ($hostBits | ?{$_} | measure).count)
if($numHosts -gt 256 -and !$ForceListing.ispresent) {
#well, if we have more than this, just output the (ipv4 equivalent) network id and broadcast address.
$netId
$netBcast
} else {
Add-Member -PassThru -Force -InputObject $netId -MemberType NoteProperty -Name IsUsable -Value $false;
try {
$lastAddr = $netId;
for($i = 0; $i -lt $numHosts-2; $i ++) {
$lastAddr = inc $lastAddr
Add-Member -PassThru -Force -InputObject $lastAddr -MemberType NoteProperty -Name IsUsable -Value $true;
}
} catch {}
Add-Member -PassThru -Force -InputObject $netBcast -MemberType NoteProperty -Name IsUsable -Value $false;
#$res
}
Notes:
- Not commented well. RTCFA (read the code for answers)! >:(
- Only increments despite there being a decrement function.
- If the number of host addresses is less then 256, it will always display the complete listing.

RSS