IP Calculator in PowerShell...with IP exclusion
Hola
todos... que pasa?
It
has been a while since i post i was really busy with so many stuff, bottom
line, i had this strange requirement at work where i had to create a script to
calculate the IP address from a subnet, now normally this means we have to
create a bunch of scopes or subnets in the DHCP server, which was my case, i
had to create more than 4 thousand scopes on Linux DHCP server.
now
I was thinking how in the hell I am going to insert all these scopes in the
configuration file, of course the first things I came up with was to provide
the mandatory information (First IP, last IP, broadcast IP and number of hosts)
which was not a big problem, I found this link :
This
guy did a very good job and save my ass, but this was not the issue, in my
situation, I had to exclude the first 48 IP addresses from each scope. Now in
Linux DHCP configuration file, each scope was represented as a string, for example:
subnet
10.69.113.192 netmask 255.255.255.192
{
option
routers 10.69.113.252;
#Default
Gateway
option
subnet-mask 255.255.255.192;
option
Broadcast-address 10.69.113.255;
option
option-150 10.75.192.10;
#TFTP
Custom Option
next-server
10.75.192.10;
#
TFTP Boot
range
dynamic-bootp 10.69.113.193 10.69.113.241;
}
Now
I am not gonna speak about Linux here because that's a different story, to
generate the above string i had to create a script to read from a CSV file and
put thing in the correct order.
In
the last line "range dynamic-bootp" this option provides IP addresses for PXE-compliant
network cards BEFORE any operating system starts. For more info, dig this link:
Now this is where my work comes i had to modify the script
a little bit to provide my requirements.
The original script looked like this:
<#
.SYNOPSIS
ipcalc calculates the IP subnet information based
upon the entered IP address and subnet.
.DESCRIPTION
ipcalc calculates the IP subnet information based
upon the entered IP address and subnet. It can accept
both CIDR and dotted decimal formats.
By: Jason Wasser
Date: 10/29/2013
.PARAMETER IPAddress
Enter the IP address by itself or with CIDR notation.
.PARAMETER Netmask
Enter the subnet mask information in dotted decimal
form.
.EXAMPLE
ipcalc.ps1 -IPAddress 10.100.100.1 -NetMask 255.255.255.0
.EXAMPLE
ipcalc.ps1 10.10.100.5/24
#>
param (
[Parameter(Mandatory=$True,Position=1)]
[string]$IPAddress,
[Parameter(Mandatory=$False,Position=2)]
[string]$Netmask
)
function toBinary ($dottedDecimal){
$dottedDecimal.split(".") | %{$binary=$binary + $([convert]::toString($_,2).padleft(8,"0"))}
return $binary
}
function toDottedDecimal ($binary){
do {$dottedDecimal += "." + [string]$([convert]::toInt32($binary.substring($i,8),2)); $i+=8 } while ($i -le 24)
return $dottedDecimal.substring(1)
}
function CidrToBin ($cidr){
if($cidr -le 32){
[Int[]]$array = (1..32)
for($i=0;$i -lt $array.length;$i++){
if($array[$i] -gt $cidr){$array[$i]="0"}else{$array[$i]="1"}
}
$cidr =$array -join ""
}
return $cidr
}
function NetMasktoWildcard ($wildcard) {
foreach ($bit in [char[]]$wildcard) {
if ($bit -eq "1") {
$wildcardmask += "0"
}
elseif ($bit -eq "0") {
$wildcardmask += "1"
}
}
return $wildcardmask
}
# Check to see if the IP Address was entered in CIDR format
if ($IPAddress -like "*/*") {
$CIDRIPAddress = $IPAddress
$IPAddress = $CIDRIPAddress.Split("/")[0]
$cidr = [convert]::ToInt32($CIDRIPAddress.Split("/")[1])
if ($cidr -le 32 -and $cidr -ne 0) {
$ipBinary = toBinary $IPAddress
$smBinary = CidrToBin($cidr)
$Netmask = toDottedDecimal($smBinary)
$wildcardbinary = NetMasktoWildcard ($smBinary)
}
else {
Write-Warning "Subnet Mask is invalid!"
Exit
}
}
else {
if (!$Netmask) {
$Netmask = Read-Host "Netmask"
}
$ipBinary = toBinary $IPAddress
if ($Netmask -eq "0.0.0.0") {
Write-Warning "Subnet Mask is invalid!"
Exit
}
else {
$smBinary = toBinary $Netmask
$wildcardbinary = NetMasktoWildcard ($smBinary)
}
}
#how many bits are the network ID
$netBits=$smBinary.indexOf("0")
if ($netBits -ne -1) {
$cidr = $netBits
#validate the subnet mask
if(($smBinary.length -ne 32) -or ($smBinary.substring($netBits).contains("1") -eq $true)) {
Write-Warning "Subnet Mask is invalid!"
Exit
}
#validate that the IP address
if(($ipBinary.length -ne 32) -or ($ipBinary.substring($netBits) -eq "00000000") -or ($ipBinary.substring($netBits) -eq "11111111")) {
Write-Warning "IP Address is invalid!"
Exit
}
#identify subnet boundaries
$networkID = toDottedDecimal $($ipBinary.substring(0,$netBits).padright(32,"0"))
$firstAddress = toDottedDecimal $($ipBinary.substring(0,$netBits).padright(31,"0") + "1")
$lastAddress = toDottedDecimal $($ipBinary.substring(0,$netBits).padright(31,"1") + "0")
$broadCast = toDottedDecimal $($ipBinary.substring(0,$netBits).padright(32,"1"))
$wildcard = toDottedDecimal ($wildcardbinary)
$networkIDbinary = $ipBinary.substring(0,$netBits).padright(32,"0")
$broadCastbinary = $ipBinary.substring(0,$netBits).padright(32,"1")
$Hostspernet = ([convert]::ToInt32($broadCastbinary,2) - [convert]::ToInt32($networkIDbinary,2)) - 1
}
else {
#identify subnet boundaries
$networkID = toDottedDecimal $($ipBinary)
$firstAddress = toDottedDecimal $($ipBinary)
$lastAddress = toDottedDecimal $($ipBinary)
$broadCast = toDottedDecimal $($ipBinary)
$wildcard = toDottedDecimal ($wildcardbinary)
$Hostspernet = 1
}
#Results
Write-Host "`nAddress:`t`t$IPAddress"
Write-Host "Netmask:`t`t$Netmask = $cidr"
Write-Host "Wildcard:`t`t$wildcard"
Write-Host "=>"
Write-Host "Network:`t`t$networkID/$cidr"
Write-Host "Broadcast:`t`t$broadCast"
Write-Host "HostMin:`t`t$firstAddress"
Write-Host "HostMax:`t`t$lastAddress"
Write-Host "Hosts/Net:`t`t$Hostspernet`n"
The output should be something like this :
Address:
10.10.100.5
Netmask:
255.255.255.0 = 24
Wildcard:
0.0.0.255
=>
Network:
10.10.100.0/24
Broadcast:
10.10.100.255
HostMin:
10.10.100.1
HostMax:
10.10.100.254
Hosts/Net:
254
In my situation i did some modification on the script to
look like this :
param
(
[Parameter(Mandatory=$True,Position=1)]
[string]$IPAddress,
[Parameter(Mandatory=$False,Position=2)]
[string]$Netmask
)
function
toBinary ($dottedDecimal){
$dottedDecimal.split(".")
| %{$binary=$binary + $([convert]::toString($_,2).padleft(8,"0"))}
return
$binary
}
function
toDottedDecimal ($binary){
do
{$dottedDecimal += "." +
[string]$([convert]::toInt32($binary.substring($i,8),2)); $i+=8 } while ($i -le
24)
return
$dottedDecimal.substring(1)
}
function
CidrToBin ($cidr){
if($cidr -le 32){
[Int[]]$array = (1..32)
for($i=0;$i -lt $array.length;$i++){
if($array[$i] -gt
$cidr){$array[$i]="0"}else{$array[$i]="1"}
}
$cidr =$array -join ""
}
return $cidr
}
function
NetMasktoWildcard ($wildcard) {
foreach ($bit in [char[]]$wildcard) {
if ($bit -eq "1") {
$wildcardmask += "0"
}
elseif ($bit -eq "0") {
$wildcardmask += "1"
}
}
return $wildcardmask
}
#
Check to see if the IP Address was entered in CIDR format
if
($IPAddress -like "*/*") {
$CIDRIPAddress = $IPAddress
$IPAddress = $CIDRIPAddress.Split("/")[0]
$cidr = [convert]::ToInt32($CIDRIPAddress.Split("/")[1])
if ($cidr -le 32 -and $cidr -ne 0) {
$ipBinary = toBinary $IPAddress
$smBinary = CidrToBin($cidr)
$Netmask = toDottedDecimal($smBinary)
$wildcardbinary = NetMasktoWildcard ($smBinary)
}
else {
Write-Warning "Subnet Mask is invalid!"
Exit
}
}
else
{
if (!$Netmask) {
$Netmask = Read-Host "Netmask"
}
$ipBinary = toBinary $IPAddress
if ($Netmask -eq "0.0.0.0") {
Write-Warning "Subnet Mask is invalid!"
Exit
}
else {
$smBinary = toBinary $Netmask
$wildcardbinary = NetMasktoWildcard ($smBinary)
}
}
#how
many bits are the network ID
$netBits=$smBinary.indexOf("0")
if
($netBits -ne -1) {
$cidr = $netBits
#validate the subnet mask
if(($smBinary.length -ne 32) -or
($smBinary.substring($netBits).contains("1") -eq $true)) {
Write-Warning "Subnet Mask is invalid!"
Exit
}
#validate that the IP address
if(($ipBinary.length -ne 32) -or ($ipBinary.substring($netBits) -eq
"00000000") -or ($ipBinary.substring($netBits) -eq
"11111111")) {
Write-Warning "IP Address is invalid!"
Exit
}
#identify subnet boundaries
$networkID = toDottedDecimal
$($ipBinary.substring(0,$netBits).padright(32,"0"))
$firstAddress = toDottedDecimal $($ipBinary.substring(0,$netBits).padright(31,"0")
+ "1")
$lastAddress = toDottedDecimal
$($ipBinary.substring(0,$netBits).padright(31,"1") + "0")
$broadCast = toDottedDecimal
$($ipBinary.substring(0,$netBits).padright(32,"1"))
$wildcard = toDottedDecimal ($wildcardbinary)
$networkIDbinary =
$ipBinary.substring(0,$netBits).padright(32,"0")
$broadCastbinary =
$ipBinary.substring(0,$netBits).padright(32,"1")
$Hostspernet = ([convert]::ToInt32($broadCastbinary,2) -
[convert]::ToInt32($networkIDbinary,2)) – 1
# I added these lines
$exclusionfirstAddresssep =
$firstAddress.Split(".")[3].split(" ")
$ipstart1 =
$firstAddress.Split(".")[0].split("").trim()
$ipstart2 =
$firstAddress.Split(".")[1].split("").trim()
$ipstart3 =
$firstAddress.Split(".")[2].split("").trim()
$excludelastip =
[Convert]::ToInt32($exclusionfirstAddresssep,10) +
[convert]::ToInt32("48",10)
$startip =
[Convert]::ToInt32($excludelastip,10) + [Convert]::ToInt32("1",10)
$ipstart4 = $ipstart1 + "." +
$ipstart2 + "." + $ipstart3 + "." + $startip
}
else
{
#identify subnet boundaries
$networkID = toDottedDecimal $($ipBinary)
$firstAddress = toDottedDecimal $($ipBinary)
$lastAddress = toDottedDecimal $($ipBinary)
$broadCast = toDottedDecimal $($ipBinary)
$wildcard = toDottedDecimal ($wildcardbinary)
$Hostspernet = 1
}
#Results
Write-Host
"`nAddress:`t`t$IPAddress"
Write-Host
"Netmask:`t`t$Netmask = $cidr"
Write-Host
"Wildcard:`t`t$wildcard"
Write-Host
"=>"
Write-Host
"Network:`t`t$networkID/$cidr"
Write-Host
"Broadcast:`t`t$broadCast"
Write-Host
"HostMin:`t`t$firstAddress"
Write-Host
"HostMax:`t`t$lastAddress"
Write-Host
"Hosts/Net:`t`t$Hostspernet`n"
Write-Host
"excluding from : $exclusionfirstAddresssep to $excludelastip `n"
Write-Host
"boottp-Exclusion:`t$ipstart4 $lastAddress"
#
show as csv file :
WriteHost
"$IPAddress,$Netmask,$cidr,$wildcard,$networkID/$cidr,$broadCast,$firstAddress,$lastAddress,$Hostspernet,$ipstart4
$lastAddress"
Now my output looked something like this :
Address:
10.10.100.5
Netmask:
255.255.255.0 = 24
Wildcard:
0.0.0.255
=>
Network:
10.10.100.0/24
Broadcast:
10.10.100.255
HostMin:
10.10.100.1
HostMax:
10.10.100.254
Hosts/Net: 254
excluding from : 1 to 49
boottp-Exclusion:
10.10.100.50 10.10.100.254
10.10.100.5,255.255.255.0,24,0.0.0.255,10.10.100.0/24,10.10.100.255,10.10.100.1,10.10.100.254,254,10.10.100.50
10.10.100.254
The part in the yellow was the added result after my
modification, to make the first 48 IP addresses PXE.
This same way can be used to also exclude the
IP addresses in DHCP, the exclusion will ask the DHCP not to provide these
IP's to other devices.
The last line of the result can be copied and
pasted in a CSV file, and from excel you can use the text to columns option to
segregate each value in a separate column, this can help
in creating the scopes in microsoft or linux based DHCP.
Sadly I gotta go now, anyway saludos
todos, hasta pronto todos....
Comments
Post a Comment