Manipulate IPv6 with PowerShell

Envoyer Imprimer

 

For some needs related to the management of Active Directory subnets, I spent some times to manipulate IPv6 addresses with PowerShell. Since I’m not a guru in PowerShell, I have started to search some useful stuffs over Internet but without any success. So I have done it by my own. It is not really the cleanest way but it is almost working!

The objective was to manipulate a IPv6 subnet such as “2001:4cf8:0:220B::/64” to obtain something like that:

InputAddress: 2001:4cf8:0:220B::
Prefix: 64
NumberOfIPs: 18446744073709551616
NetworkAddress: 2001:4CF8:0000:220B:0000:0000:0000:0000
RangeStart: 42542049273690184588432901994040000512
RangeEnd: 42542049273690184606879646067749552127
IpStart: 2001:4CF8:0000:220B:0000:0000:0000:0000
IpEnd:

2001:4CF8:0000:220B:FFFF:FFFF:FFFF:FFFF

 

 

The script is using the class .Net IPAddress (http://msdn.microsoft.com/en-us/library/system.net.ipaddress.aspx).  I had to use also the System.Numerics.BigInteger. Unfortunatly, BigInteger is available only from the .Net Framework  4 and, moreover, PowerShell doesn’t use the lastest CLR available. So you have to install the framework 4 then indicate explicitly to PowerShell to use it You will just have to run the following from a “Command prompt”:

reg add hklm\software\microsoft\.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1

reg add hklm\software\wow6432node\microsoft\.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1

 

The complete code:

 
#========================================================================
# Created on:   18/04/2013
# Created by:   AUGAGNEUR Alexandre
# Website:                         www.alexwinner.com
# URL: 
# Filename:     Compute-IPv6Address.ps1
#
# Description:    Create an object from a string "IPv6Address/Prefix"
#               Members:
#               - InputAddress
#               - Prefix
#               - NumberOfIPs
#               - NetworkAddress
#               - RangeStart
#               - RangeEnd
#               - IpStart
#               - IpEnd
#========================================================================
 
param ( 
 [Parameter(mandatory=$true)] 
 [string] $InputAddress
)
 
$Message =
@"
 The script needs to use the CLR .Net Framework 4.0.
 
 If you have already installed it, you have to indicate to PowerShell to use it.
 
 Commands to run:
 reg add hklm\software\microsoft\.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1
 reg add hklm\software\wow6432node\microsoft\.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1
"@
 
#Region Functions
 
####################################################
# Functions
####################################################
 
#---------------------------------------------------
# Converting an array of bytes to IPv6 format
#---------------------------------------------------
function Convert-BytesToIPv6 ( $arrayBytes )
{
 $String = $null
 $j = 0
 
 foreach ( $Item in $arrayBytes )
 { 
 if ( $j -eq 2)
 {
 $String += ":"+[system.bitconverter]::Tostring($Item)
 $j = 1
 }
 else
 { 
 $String += [system.bitconverter]::Tostring($Item)
 $j++
 }
 }
 Return $String
}
 
#---------------------------------------------------
# Compute the network address
#---------------------------------------------------
function Compute-NetworkAddress ( $Address )
{
 #$Address = [System.Net.IPAddress] $Obj.InputAddress
 $ArrBytesAddress = $Address.GetAddressBytes()
 [array]::Reverse($ArrBytesAddress)
 
 # Sets a Block-Size to 0 if it is a part of the network length
 for ( $i=0; $i -lt $script:BlockBytes; $i++ )
 {
 $ArrBytesAddress[$i] = 0
 }
 
 # Returns the remaining bits of the prefix
 $Remaining =  $obj.Prefix % 8
 
 if ( $Remaining -gt 0 )
 {
 $Mask = ([Math]::Pow(2,$Remaining)-1)*([Math]::Pow(2,8-$Remaining))
 $BlockBytesValue = $ArrBytesAddress[$i] -band $Mask
 $ArrBytesAddress[$i] = $BlockBytesValue
 }
 
 [array]::Reverse($ArrBytesAddress)
 $NetworkAddress = Convert-BytesToIpv6 $ArrBytesAddress
 
 Return $NetworkAddress
}
 
#---------------------------------------------------
# Create the IPv6 object
#---------------------------------------------------
function Compute-IPv6 ( $Obj, $ObjInputAddress )
{
 try
 { 
 # Compute available IPs based on the IPv6 Prefix
 [System.Numerics.BigInteger] $NumberOfIPs = [System.Math]::Pow(2, $script:IntIPLength)
 $Obj | Add-Member -type NoteProperty -name NumberOfIPs -value $NumberOfIPs
 
 # Compute the network address
 $NetworkAddress = Compute-NetworkAddress $ObjInputAddress
 $Obj | Add-Member -type NoteProperty -name NetworkAddress -value $NetworkAddress
 
 # Convert NetworkAddress to decimal value
 $ObjNetworkAddress = [System.Net.IPAddress] $NetworkAddress
 $ArrBytesNetworkAddress = $ObjNetworkAddress.GetAddressBytes()
 [array]::Reverse($ArrBytesNetworkAddress)
 $BigIntRangeStart = [System.Numerics.BigInteger] $ArrBytesNetworkAddress
 $Obj | Add-Member -type NoteProperty -name RangeStart -value $BigIntRangeStart
 
 # Compute the lastest available IP in decimal value
 [System.Numerics.BigInteger] $BigIntRangeEnd = ($BigIntRangeStart + $NumberOfIPs) - 1
 $Obj | Add-Member -type NoteProperty -name RangeEnd -value $BigIntRangeEnd
 
 # Convert the decimal value of the range start to IPv6 format
 $ArrBytesRangeStart = $BigIntRangeStart.ToByteArray()
 [array]::Reverse($ArrBytesRangeStart)
 $IpStart = Convert-BytesToIpv6 $ArrBytesRangeStart
 $Obj | Add-Member -type NoteProperty -name IpStart -value $IpStart
 
 # Convert the lastest available IP in IPv6 format
 $ArrBytesRangeEnd = $BigIntRangeEnd.ToByteArray()
 [array]::Reverse($ArrBytesRangeEnd)
 $IpEnd = Convert-BytesToIpv6 $ArrBytesRangeEnd
 $Obj | Add-Member -type NoteProperty -name IpEnd -value $IpEnd
 
 return $Obj
 }
 catch
 {
 Write-Host $_.Exception.Message
 }
}
 
#EndRegion
 
#Region Main
 
####################################################
# Main
####################################################
 
# Check the CLR version (only version 4 can be used)
if ( ([environment]::Version).Major -ne 4 )
{
 Write-Host $Message -Foreground 'Red'
}
else
{
 try
 {
 # Add dll System.Numerics to use the BigInteger structure
 Add-Type -Path "C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Numerics.dll"
 
 # Construct the subnet object
 $ObjSubnet = New-Object -TypeName PsObject
 $ObjSubnet | Add-Member -type NoteProperty -name InputAddress -value ($InputAddress.split("/"))[0]
 $ObjSubnet | Add-Member -type NoteProperty -name Prefix -value ($InputAddress.split("/"))[1]
 
 # Compute IP length
 [int] $script:IntIPLength = 128 - $ObjSubnet.Prefix
 
 # Returns the number of block-size
 [int] $BlockBytes = [Math]::Floor($script:IntIPLength / 8)
 
 # Construct System.Net.IPAddress
 $ObjInputAddress = [System.Net.IPAddress] $ObjSubnet.InputAddress
 
 # Check if IP is a IPv6
 if ( $ObjInputAddress.AddressFamily -match "InterNetworkV6" )
 {
 # Compute network address and IP ranges
 $ObjSubnet = Compute-IPv6 $ObjSubnet $ObjInputAddress
 Return $ObjSubnet
 }
 else
 {
 Write-Host "The IP address is not an IPv6."
 }
 }
 catch
 {
 Write-Host "$($_.Exception.Message)"
 }
}
#EndRegion
 

 

You can download the full script from the Microsoft TechNet Script Library: http://gallery.technet.microsoft.com/scriptcenter/Manipulate-IPv6-Address-041661e4.

Its usage is simple. You just have to call the script with parameter “inputaddress” and a value “IPv6/Prefix”.

Example: .\Compute-IPv6Address.ps1 –InputAddress 2001:4cf8:0:220B::/64

#========================================================================

# Created on: 18/04/2013

# Created by: AUGAGNEUR Alexandre

# Website: www.alexwinner.com

# URL:

# Filename: Compute-IPv6Address.ps1

#

# Description: Create an object from a string "IPv6Address/Prefix"

# Members:

# - InputAddress

# - Prefix

# - NumberOfIPs

# - NetworkAddress

# - RangeStart

# - RangeEnd

# - IpStart

# - IpEnd

#========================================================================

param (

[Parameter(mandatory=$true)]

[string] $InputAddress

)

$Message =

@"

The script needs to use the CLR .Net Framework 4.0.

If you have already installed it, you have to indicate to PowerShell to use it.

Commands to run:

reg add hklm\software\microsoft\.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1

reg add hklm\software\wow6432node\microsoft\.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1

"@

#Region Functions

####################################################

# Functions

####################################################

#---------------------------------------------------

# Converting an array of bytes to IPv6 format

#---------------------------------------------------

function Convert-BytesToIPv6 ( $arrayBytes )

{

$String = $null

$j = 0

foreach ( $Item in $arrayBytes )

{

if ( $j -eq 2)

{

$String += ":"+[system.bitconverter]::Tostring($Item)

$j = 1

}

else

{

$String += [system.bitconverter]::Tostring($Item)

$j++

}

}

Return $String

}

#---------------------------------------------------

# Compute the network address

#---------------------------------------------------

function Compute-NetworkAddress ( $Address )

{

#$Address = [System.Net.IPAddress] $Obj.InputAddress

$ArrBytesAddress = $Address.GetAddressBytes()

[array]::Reverse($ArrBytesAddress)

# Sets a Block-Size to 0 if it is a part of the network length

for ( $i=0; $i -lt $script:BlockBytes; $i++ )

{

$ArrBytesAddress[$i] = 0

}

# Returns the remaining bits of the prefix

$Remaining = $obj.Prefix % 8

if ( $Remaining -gt 0 )

{

$Mask = ([Math]::Pow(2,$Remaining)-1)*([Math]::Pow(2,8-$Remaining))

$BlockBytesValue = $ArrBytesAddress[$i] -band $Mask

$ArrBytesAddress[$i] = $BlockBytesValue

}

[array]::Reverse($ArrBytesAddress)

$NetworkAddress = Convert-BytesToIpv6 $ArrBytesAddress

Return $NetworkAddress

}

#---------------------------------------------------

# Create the IPv6 object

#---------------------------------------------------

function Compute-IPv6 ( $Obj, $ObjInputAddress )

{

try

{

# Compute available IPs based on the IPv6 Prefix

[System.Numerics.BigInteger] $NumberOfIPs = [System.Math]::Pow(2, $script:IntIPLength)

$Obj | Add-Member -type NoteProperty -name NumberOfIPs -value $NumberOfIPs

# Compute the network address

$NetworkAddress = Compute-NetworkAddress $ObjInputAddress

$Obj | Add-Member -type NoteProperty -name NetworkAddress -value $NetworkAddress

# Convert NetworkAddress to decimal value

$ObjNetworkAddress = [System.Net.IPAddress] $NetworkAddress

$ArrBytesNetworkAddress = $ObjNetworkAddress.GetAddressBytes()

[array]::Reverse($ArrBytesNetworkAddress)

$BigIntRangeStart = [System.Numerics.BigInteger] $ArrBytesNetworkAddress

$Obj | Add-Member -type NoteProperty -name RangeStart -value $BigIntRangeStart

# Compute the lastest available IP in decimal value

[System.Numerics.BigInteger] $BigIntRangeEnd = ($BigIntRangeStart + $NumberOfIPs) - 1

$Obj | Add-Member -type NoteProperty -name RangeEnd -value $BigIntRangeEnd

# Convert the decimal value of the range start to IPv6 format

$ArrBytesRangeStart = $BigIntRangeStart.ToByteArray()

[array]::Reverse($ArrBytesRangeStart)

$IpStart = Convert-BytesToIpv6 $ArrBytesRangeStart

$Obj | Add-Member -type NoteProperty -name IpStart -value $IpStart

# Convert the lastest available IP in IPv6 format

$ArrBytesRangeEnd = $BigIntRangeEnd.ToByteArray()

[array]::Reverse($ArrBytesRangeEnd)

$IpEnd = Convert-BytesToIpv6 $ArrBytesRangeEnd

$Obj | Add-Member -type NoteProperty -name IpEnd -value $IpEnd

return $Obj

}

catch

{

Write-Host $_.Exception.Message

}

}

#EndRegion

#Region Main

####################################################

# Main

####################################################

# Check the CLR version (only version 4 can be used)

if ( ([environment]::Version).Major -ne 4 )

{

Write-Host $Message -Foreground 'Red'

}

else

{

try

{

# Add dll System.Numerics to use the BigInteger structure

Add-Type -Path "C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Numerics.dll"

# Construct the subnet object

$ObjSubnet = New-Object -TypeName PsObject

$ObjSubnet | Add-Member -type NoteProperty -name InputAddress -value ($InputAddress.split("/"))[0]

$ObjSubnet | Add-Member -type NoteProperty -name Prefix -value ($InputAddress.split("/"))[1]

# Compute IP length

[int] $script:IntIPLength = 128 - $ObjSubnet.Prefix

# Returns the number of block-size

[int] $BlockBytes = [Math]::Floor($script:IntIPLength / 8)

# Construct System.Net.IPAddress

$ObjInputAddress = [System.Net.IPAddress] $ObjSubnet.InputAddress

# Check if IP is a IPv6

if ( $ObjInputAddress.AddressFamily -match "InterNetworkV6" )

{

# Compute network address and IP ranges

$ObjSubnet = Compute-IPv6 $ObjSubnet $ObjInputAddress

Return $ObjSubnet

}

else

{

Write-Host "The IP address is not an IPv6."

}

}

catch

{

Write-Host "$($_.Exception.Message)"

}

}

#EndRegion

Normal 0 21 false false false FR X-NONE X-NONE MicrosoftInternetExplorer4

Mise à jour le Dimanche, 21 Avril 2013 20:13