Manipulate IPv6 with PowerShell

 

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:

{codecitation style= »brush: PowerShell »}

 

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

# 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

 

{/codecitation}

 

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