Home > Net >  Validate and compare incoming parameters in powershell script
Validate and compare incoming parameters in powershell script

Time:11-07

I'm just learning the basics of powershell and have a task - create pwsh script which accepts 3 incoming parameters (all are mandatory):

  1. first parameter, value address_1, it's IP address with the format x.x.x.x
  2. second parameter, value address_2, it's IP address with the format x.x.x.x
  3. third parameter, value mask, value in the format x.x.x.x or xx (255.0.0.0 or 8)

This script should check address_1 and address_2 belong to the same network or not. Results in output console, yes or no. As I mentioned before incoming parameters not allow to accept not valid arguments, it should show error.

Can someone explain, how I can do that. I will be very grateful for your help.

CodePudding user response:

Some of the documentation can seem over-whelming on frist read, so here's a working framework to study and get you started. The [ValidatePattern()] and [ValidateScript()] attributes validate IPv4 address format and valid value range and errors will be thrown if the conditions they specify aren't met.

Perform you domain comparision in the Process block and branch conditionally on the result. I leave that to you.

Function AddressTest
{
    Param(
        [Parameter(Mandatory,Position = 0)]
        [ValidatePattern('^(\d{1,3}\.){3}\d{1,3}$')]
        [ValidateScript({[Int[]](($_.Split('.')) -le 255).Count -eq 4})]
        [String]$address_1,

        [Parameter(Mandatory,Position = 1)]
        [ValidatePattern('^(\d{1,3}\.){3}\d{1,3}$')]
        [ValidateScript({[Int[]](($_.Split('.')) -le 255).Count -eq 4})]
        [String]$address_2,

        [Parameter(Mandatory,Position = 2)]
        [ValidatePattern('^((\d{1,3}\.){3})?\d{1,3}$')]
        [ValidateScript({(($_ -match '^\d $') -and ([Int]$_ -le 255)) -or (($_.Split('.') -le 255).Count -eq 4)})]
        [String]$Mask
    )
    Process
    {
        echo $address_1
        echo $address_2
        echo $mask
    }
}

Read the documentation at the links others provided in the commnents while picking apart the code to understand how it works.

CodePudding user response:

I find a answer, script, with strange validation pattern:

param (
    [parameter(Mandatory = $true, Position = 0)]
    [Net.IPAddress]
    $ip1,
     
    [parameter(Mandatory = $true, Position = 1)]
    [Net.IPAddress]
    $ip2,
     
    [parameter(Mandatory = $true, Position = 2)]
    [alias("SubnetMask")]
    [Net.IPAddress]
    $mask
)
     
if (($ip1.address -band $mask.address) -eq ($ip2.address -band $mask.address)) { $true } else { $false }

Working correct:

./script.ps1 -ip1 192.168.228.110 -ip2 192.168.228.190 -mask 255.255.255.128

But when I use network prefix it always give a true.

./script.ps1 -ip1 192.168.228.110 -ip2 192.168.228.190 -mask 30

How I can modify script, to working with prefix?

CodePudding user response:

As per my comment. This stuff already exists for years now, thus no need to try and write this from scratch, unless it's a homework assignment, or you are pushing yourself to learn to do it.

Search is your friend.

'powershell ipv4 address range to cidr'

The first hit in the results...

https://www.kittell.net/code/powershell-ipv4-range

...and the author's examples:

# IPv4 Range
function New-IPRange ($start, $end)
{
    # created by Dr. Tobias Weltner, MVP PowerShell
    $ip1 = ([System.Net.IPAddress]$start).GetAddressBytes()
    [Array]::Reverse($ip1)
    $ip1 = ([System.Net.IPAddress]($ip1 -join '.')).Address
    $ip2 = ([System.Net.IPAddress]$end).GetAddressBytes()
    [Array]::Reverse($ip2)
    $ip2 = ([System.Net.IPAddress]($ip2 -join '.')).Address
  
    for ($x=$ip1; $x -le $ip2; $x  )
        {
            $ip = ([System.Net.IPAddress]$x).GetAddressBytes()
            [Array]::Reverse($ip)
            $ip -join '.'
        }
}


# IPv4 Range - Example
New-IPRange 192.168.10.10 192.168.10.20

# broadcast IPv4 address from a CIDR range
function Get-Broadcast ($addressAndCidr)
{
    $addressAndCidr = $addressAndCidr.Split("/")
    $addressInBin = (New-IPv4toBin $addressAndCidr[0]).ToCharArray()
    for($i=0;$i -lt $addressInBin.length;$i  )
        {
            if($i -ge $addressAndCidr[1])
                {
                    $addressInBin[$i] = "1"
                } 
        }
    [string[]]$addressInInt32 = @()
    for ($i = 0;$i -lt $addressInBin.length;$i  )
        {
            $partAddressInBin  = $addressInBin[$i] 
            if(($i 1)%8 -eq 0)
                {
                    $partAddressInBin = $partAddressInBin -join ""
                    $addressInInt32  = [Convert]::ToInt32($partAddressInBin -join "",2)
                    $partAddressInBin = ""
                }
        }
    $addressInInt32 = $addressInInt32 -join "."
    return $addressInInt32
}

# IPv4 Broadcast - Example
Get-Broadcast 192.168.10.10/27


# detect if a specified IPv4 address is in the range

function Test-IPinIPRange ($Address,$Lower,$Mask)
{
    [Char[]]$a = (New-IPv4toBin $Lower).ToCharArray()
    if($mask -like "*.*")
        {
            [Char[]]$b = (New-IPv4toBin $Mask).ToCharArray()
        }
    else
        {
            [Int[]]$array = (1..32)
            for($i=0;$i -lt $array.length;$i  )
                {
                    if($array[$i] -gt $mask){$array[$i]="0"}else{$array[$i]="1"}
                }
            [string]$mask = $array -join ""
            [Char[]]$b = $mask.ToCharArray()
        }
    [Char[]]$c = (New-IPv4toBin $Address).ToCharArray()
    $res = $true
    for($i=0;$i -le $a.length;$i  )
        {
            if($a[$i] -ne $c[$i] -and $b[$i] -ne "0")
                {
                    $res = $false
                } 
        }
    return $res
}

# IPv4 In Range - Example
Write-Output "`r`nTest If IP In Range - 192.168.23.128/25"
Test-IPinIPRange "192.168.23.200" "192.168.23.12" "255.255.255.128"
Write-Output "`r`nTest If IP In Range - 192.168.23.127/24"
Test-IPinIPRange "192.168.23.127" "192.168.23.12" "24"

# convert an IPv4 address to a Bin
function New-IPv4toBin ($ipv4)
{
    $BinNum = $ipv4 -split '\.' | ForEach-Object {[System.Convert]::ToString($_,2).PadLeft(8,'0')}
    return $binNum -join ""
}

# IPv4 To Bin - Example
Write-Output "`r`nIP To Bin"
New-IPv4toBin 192.168.10.10

# convert a Bin to an IPv4 address
function New-IPv4fromBin($addressInBin)
{
    [string[]]$addressInInt32 = @()
    $addressInBin = $addressInBin.ToCharArray()
    for ($i = 0;$i -lt $addressInBin.length;$i  )
        {
            $partAddressInBin  = $addressInBin[$i]
            if(($i 1)%8 -eq 0)
                {
                    $partAddressInBin = $partAddressInBin -join ""
                    $addressInInt32  = [Convert]::ToInt32($partAddressInBin -join "",2)
                    $partAddressInBin = ""
                }
        }
    $addressInInt32 = $addressInInt32 -join "."
    return $addressInInt32
}

# IPv4 From Bin - Example
Write-Output "`r`nIP From Bin - 192.168.23.250"
New-IPv4fromBin "11000000101010000001011111111010"
 
Write-Output "`r`nIP From Bin - 192.168.10.10"
New-IPv4fromBin "11000000101010000000101000001010"

# CIDR To IPv4 Range - Example
Write-Output "`r`nIP CIDR to Range"
New-IPRange "192.168.23.120" (Get-Broadcast "192.168.23.120/25")

You of course can refactor the above with the Validate code already provided to you by the others.

  • Related