0

I have been developing VM provision script. My question is : I have here-string like below. now , I want to add route based on ip address range. I am using CSV file with BACKUPIP column.

if an BACKUPIP is in range 10.10.104.1 to 10.10.107.254 it will work route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p

if an BACKUPIP is in range 10.10.180.1 to 10.10.185.254 it will work route add yy.yy.yy.yy mask 255.255.255.0 yy.yy.yy.yy -p

Here is my script:

Import-Csv -Path .\vm.csv -UseCulture -PipelineVariable row |

ForEach-Object -Process {


    # Create the VM, store result in $vm


    if($($row.IP) -eq '???'){
            route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p
            }
    else{
            
            route add yy.yy.yy.yy mask 255.255.255.0 yy.yy.yy.yy -p
            
            }


}

LAST UPDATE :

$rangeFrom104 = '10.10.104.1'
$rangeTo107 = '10.10.107.254'

$rangeFrom180 = '10.10.180.1'
$rangeTo185 = '10.10.185.254'

     

if (([version]$rangeFrom104) -lt ([version]$($row.IP)) -and ([version]$($row.IP)) -lt ([version]$rangeTo107) )
{

route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p

}

elseif (([version]$rangeFrom180) -lt ([version]$($row.IP)) -and ([version]$($row.IP)) -lt ([version]$rangeTo185) )
{

route add yy.yy.yy.yy mask 255.255.255.0 yy.yy.yy.yy -p

}
2
  • 2
    What is the question or an error are you getting? Commented Jun 27, 2020 at 11:25
  • 4
    use the [version] type accelerator. [grin] yes, really! this works ... >>> [version]'172.25.104.1' -le [version]'172.25.106.99' -ge [version]'172.25.107.254' <<< and gives $True as the result. Commented Jun 27, 2020 at 13:36

2 Answers 2

2

Really like the [Version] approach Lee_Dailey suggested.

Here's another approach that converts the IP addresses to their numeric values:

function Convert-IPv4ToDecimal ([string]$IpAddress){
    # helper function to return the numeric value (uint32) of a dotted IP
    # address string used for testing if an IP address is in range.
    $n = [uint32[]]$IpAddress.Split('.')
    # or use: $n = [uint32[]]([IpAddress]$IpAddress).GetAddressBytes()

    # to get the obsolete property ([IpAddress]$IpAddress).Address
    # you need to do the math in reversed order.
    # return [uint32] ($n[3] -shl 24) + ($n[2] -shl 16) + ($n[1] -shl 8) + $n[0]

    # for comparing different ranges as in this question, do not reverse the byte order
    return [uint32] ($n[0] -shl 24) + ($n[1] -shl 16) + ($n[2] -shl 8) + $n[3]
}



$startRange1 = Convert-IPv4ToDecimal '172.25.104.1'
$endRange1   = Convert-IPv4ToDecimal '172.25.107.254'

$startRange2 = Convert-IPv4ToDecimal '172.25.112.1'
$endRange2   = Convert-IPv4ToDecimal '172.25.115.254'

Import-Csv -Path .\vm.csv -UseCulture | ForEach-Object {
    # Create the VM, store result in $vm

    # convert the .BACKUPIP to numeric value
    $backupIp = Convert-IPv4ToDecimal $_.BACKUPIP
    # test the IP range
    if ($backupIp -ge $startRange1 -and $backupIp -le $endRange1) {
        Write-Host "BACKUPIP '$($_.BACKUPIP)' is in Range 1"
        route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p
    }
    elseif ($backupIp -ge $startRange2 -and $backupIp -le $endRange2) {
        Write-Host "BACKUPIP '$($_.BACKUPIP)' is in Range 2"
        route add yy.yy.yy.yy mask 255.255.255.0 yy.yy.yy.yy -p
    }
    else {
        Write-Warning "No range defined for IP address '$($_.BACKUPIP)'"
    }
}
Sign up to request clarification or add additional context in comments.

12 Comments

:) At the sametime with you , I have updated my script. compared to your script my script was amateur.
@Arbelac Nice! I see you have adopted the [version] idea. Never thought of that myself. Pity Lee_Dailey didn't post that as answer, I would have upvoted it for sure.
compared to your script my script was amateur. :)
@Arbelac Not amateur at all. I'm keeping this as alternative.
@Theo - you can get the decimal value of the ip address with this >>> ([ipaddress]'172.25.104.1').Address <<< that gives the same 23599532 that your function gives.
|
0

There exists a IPAddress class in .Net:

$MyIPAddress  = [System.Net.IPAddress]'10.10.105.7'
$rangeFrom104 = [System.Net.IPAddress]'10.10.104.1'
$rangeTo107   = [System.Net.IPAddress]'10.10.107.254'

If ($rangeFrom104.Address -lt $MyIPAddress.Address -and $MyIPAddress.Address -lt $rangeTo107.Address) {
    # route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p
}

As @Theo commented, the Address property is obsolete:

This property has been deprecated. It is address family dependent.
Please use IPAddress.Equals method to perform comparisons.

I guess this is due to compliance with IPv6 (but I presume that the property won't easily cease to exist as that would probably break some legacy programs). Anyways, that doesn't mean that the whole [System.Net.IPAddress] class is deprecated. Meaning that you might also use the GetAddressBytes method which I think better than a custom function or relying on a (smart! [version]) type but also are both limited to IPv4 (~4 bytes).

With using the GetAddressBytes method, you might simple convert the bytes to a hexadecimal string, which format is comparable (e.g. '10' -gt '0A') as long as the byte arrays are of the same size (e.g. both IPv4):

function Convert-IPAddressToHexadecimal ([Net.IPAddress]$IPAddress, [Switch]$IPv6) {
    If ($IPv6) {$IPAddress = $IPAddress.MapToIPv6()}
    [BitConverter]::ToString($IPAddress.GetAddressBytes())
}; Set-Alias IP2Hex Convert-IPAddressToHexadecimal

$MyIPAddress  = IP2Hex '10.10.105.7'   # 0A-0A-69-07
$rangeFrom104 = IP2Hex '10.10.104.1'   # 0A-0A-68-01
$rangeTo107   = IP2Hex '10.10.107.254' # 0A-0A-6B-FE

If ($rangeFrom104 -lt $MyIPAddress -and $MyIPAddress -lt $rangeTo107) {
    # route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p
}

If you do need to make your script IPv6 compliant and comparing IP addresses to both IPv4 ranges and IPv6 ranges, you might consider to map all IP addresses to an IPv6 address: using: $MyIPAddress.MapToIPv6().GetAddressBytes() (the -IPv6 switch):

IP2Hex -IPv6 '10.10.105.7' # 00-00-00-00-00-00-00-00-00-00-FF-FF-0A-0A-69-07

Update 2020-09-06:
It is unclear whether the Address property is really obsolete. See: Avoid byte[] allocations once IPAddress.Address is back #18966.
Anyhow, there is a pitfall in using the Address property for comparison as it appears that the address is stored as Big-Endian read from memory as Little-Endian format, see: System.Net.IPAddress returning weird addresses, causing the last byte in 10.10.104.1 (1) to become most significant. This means that comparing the Address property might give an incorrect result if there are differences between multiple bytes in the concerned IP Addressed:

([IPAddress]'0.0.0.1').Address -lt ([IPAddress]'0.0.1.0').Address
False

3 Comments

Unfortunatelyyes that is marked obsolete, although still works.
@Theo, you are right. I guess this is due to compliancy with IPv6 (which is not in scope here) but you might of cause also use the GetAddressBytes method which I think still better than a homemade function (which likely has the same limitation) or relying on a ([version]) type that is not designed for it.
@iRon Hi, I have a script. But , I want to improve a little. can you help me? stackoverflow.com/questions/67150840/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.