Private/Lsa.ps1
|
function Read-OspfLsaHeader { param([byte[]]$Data, [int]$Offset = 0) if ($Data.Length - $Offset -lt 20) { throw 'Truncated LSA header' } $type = [int]$Data[$Offset + 3] $id = Get-OspfIp $Data ($Offset + 4) $adv = Get-OspfIp $Data ($Offset + 8) $seq = Get-OspfUInt $Data ($Offset + 12) 4 [pscustomobject]@{ Age = [int](Get-OspfUInt $Data $Offset 2) Options = [int]$Data[$Offset + 2] Type = $type TypeName = $script:LsaTypeNames[$type] LinkStateId = $id AdvertisingRouter = $adv Sequence = $seq SequenceHex = '0x{0:X8}' -f $seq Checksum = [int](Get-OspfUInt $Data ($Offset + 16) 2) Length = [int](Get-OspfUInt $Data ($Offset + 18) 2) Key = "$type|$id|$adv" } } function Read-OspfLsa { param([byte[]]$Data, [int]$Offset = 0) $h = Read-OspfLsaHeader $Data $Offset $len = $h.Length if ($len -lt 20 -or $Offset + $len -gt $Data.Length) { throw "Invalid LSA length $len" } $b = [byte[]]$Data[$Offset..($Offset + $len - 1)] $extra = [ordered]@{ ChecksumValid = (Test-OspfLsaChecksum $b); Bytes = $b } switch ($h.Type) { 1 { $links = [System.Collections.Generic.List[object]]::new() $extra.Flags = if ($len -ge 24) { [int]$b[20] } else { 0 } $n = if ($len -ge 24) { [int](Get-OspfUInt $b 22 2) } else { 0 } $o = 24 $linkTypes = @{ 1 = 'PointToPoint'; 2 = 'Transit'; 3 = 'Stub'; 4 = 'Virtual' } for ($i = 0; $i -lt $n -and $o + 12 -le $len; $i++) { $lt = [int]$b[$o + 8] $links.Add([pscustomobject]@{ Type = $lt; TypeName = $linkTypes[$lt] LinkId = (Get-OspfIp $b $o); LinkData = (Get-OspfIp $b ($o + 4)) Metric = [int](Get-OspfUInt $b ($o + 10) 2) }) $o += 12 + 4 * [int]$b[$o + 9] } $extra.Links = $links.ToArray() } 2 { if ($len -ge 24) { $extra.NetworkMask = Get-OspfIp $b 20 $r = for ($o = 24; $o + 4 -le $len; $o += 4) { Get-OspfIp $b $o } $extra.AttachedRouters = @($r) } } { $_ -in 3, 4 } { if ($len -ge 28) { $extra.NetworkMask = Get-OspfIp $b 20 $extra.Metric = [int](Get-OspfUInt $b 25 3) } } 5 { if ($len -ge 36) { $extra.NetworkMask = Get-OspfIp $b 20 $extra.ExternalType = if (($b[24] -band 0x80) -ne 0) { 2 } else { 1 } $extra.Metric = [int](Get-OspfUInt $b 25 3) $extra.ForwardingAddress = Get-OspfIp $b 28 $extra.Tag = Get-OspfUInt $b 32 4 } } } Add-Member -InputObject $h -NotePropertyMembers $extra -Force $h } function Compare-OspfLsaInstance { # 1 if A is the more recent instance, -1 if B, 0 if identical (RFC 2328 13.1). param($A, $B) $sa = if ($A.Sequence -ge 2147483648) { $A.Sequence - 4294967296 } else { $A.Sequence } $sb = if ($B.Sequence -ge 2147483648) { $B.Sequence - 4294967296 } else { $B.Sequence } if ($sa -ne $sb) { return $(if ($sa -gt $sb) { 1 } else { -1 }) } if ($A.Checksum -ne $B.Checksum) { return $(if ($A.Checksum -gt $B.Checksum) { 1 } else { -1 }) } $aMax = $A.Age -ge $script:OspfMaxAge $bMax = $B.Age -ge $script:OspfMaxAge if ($aMax -and -not $bMax) { return 1 } if ($bMax -and -not $aMax) { return -1 } if ([math]::Abs($A.Age - $B.Age) -gt 900) { return $(if ($A.Age -lt $B.Age) { 1 } else { -1 }) } 0 } |