Skip to content

Instantly share code, notes, and snippets.

@earthdiver
Created April 29, 2024 07:00
Show Gist options
  • Select an option

  • Save earthdiver/c0bff1946aa35b29fd142fc99589b559 to your computer and use it in GitHub Desktop.

Select an option

Save earthdiver/c0bff1946aa35b29fd142fc99589b559 to your computer and use it in GitHub Desktop.
An arping tool for Windows. ( Use the function inside on Powershell console. )
@Powershell -NoP -C "&([ScriptBlock]::Create((gc '%~f0'|?{$_.ReadCount -gt 1}|Out-String)))" %* & exit/b
# by earthdiver1
[CmdletBinding(PositionalBinding=$False)]
Param(
[parameter(Position=0)][String]$Target, # IP address of the target host
[String]$Source, # if you have multiple interfaces (optional, default value: 0 (all interfaces))
[Alias("n")][Int]$Count=4, # the number of ARP requests to send (optional, default value: 4)
[Int]$Interval=1 # the interval between ARP requests, in seconds (optional, default value: 1)
)
Function arping {
[CmdletBinding(PositionalBinding=$False)]
Param(
[parameter(Position=0)][String]$Target, # IP address of the target host
[String]$Source, # if you have multiple interfaces (optional, default value: 0 (all interfaces))
[Alias("n")][Int]$Count=4, # the number of ARP requests to send (optional, default value: 4)
[Int]$Interval=1 # the interval between ARP requests, in seconds (optional, default value: 1)
)
if (-not $Target) {
Write-Output "Usage: arping <target IP address> [-Source <source IP address>]"
Write-Output " [-Count/-n <number of ARP requests>] [-Interval <interval between ARP requests>]"
exit
}
if ($Count -lt 1) { exit }
$code = '[DllImport("iphlpapi.dll")]public static extern int SendARP(UInt32 DestIP,UInt32 SrcIP,byte[] pMacAddr,ref UInt32 PhyAddrLen);'
$type = Add-Type -MemberDefinition $code -Name Win32SendARP -PassThru
try {
$DstIP = [UInt32][System.Net.IPAddress]::Parse($Target).Address
} catch {
Write-Output "Target IP address $Target is invalid. Please check it and try again."
exit
}
if ($Source) {
try {
$SrcIP = [UInt32][System.Net.IPAddress]::Parse($Source).Address
} catch {
Write-Output "Source IP address $Source is invalid. Please check it and try again."
exit
}
} else {
$SrcIP = [UInt32]0
}
$MacAddr = New-Object Byte[] 6
$n_sent = 0
$n_received = 0
$maxT = 0.
$minT = 9999.
$sumT = 0.
Write-Output ""
Write-Output "ARPING ${Target}:"
for($i=1; $i -le $Count; $i++) {
$n_sent++
$t = (Measure-Command { $result = $type::SendARP($DstIP, $SrcIP, $MacAddr, [ref][UInt32]$MacAddr.Length) }).TotalMilliseconds
if ($result -eq 0) { # NO_ERROR
$n_received++
if ($t -gt $maxT) { $maxT = $t }
if ($t -lt $minT) { $minT = $t }
$sumT += $t
Write-Output "Reply from $(($MacAddr | %{ '{0:x2}' -F $_ }) -Join '-') (as $Target): index=$i, time=$(($t).ToString('0'))ms"
} elseif ($result -eq 67) { # ERROR_BAD_NET_NAME
Write-Output "Request timed out."
} else {
Write-Output "SendARP failed with error: $result"
}
if ($i -lt $Count) { Start-Sleep -Milliseconds ([Math]::Max(($Interval*1000 - [Int]$t), 0)) }
}
Write-Output ""
Write-Output "Ping statistics for $Target/arp:"
Write-Output " Packets: Sent=$n_sent, Received=$n_received, Lost=$($n_sent-$n_received) ($((($n_sent-$n_received)/$n_sent*100).ToString('0'))% loss)"
if ($n_received -gt 0) {
Write-Output "Approximate round trip times in milli-seconds:"
Write-Output " Minimum = $(($minT).ToString('0'))ms, Maximum = $(($maxT).ToString('0'))ms, Average = $(($sumT/$n_received).ToString('0'))ms"
}
}
# update $PSBoundParameters with default parameter values
foreach ($p in $MyInvocation.MyCommand.ScriptBlock.Ast.ParamBlock.Parameters) {
$key = $p.Name.VariablePath.UserPath
if ($PSBoundParameters.ContainsKey($key)) { Continue }
$value = (Get-Variable $key).Value
if ($value) { $PSBoundParameters.Add($key, $value) }
}
arping @PSBoundParameters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment