Created
October 20, 2017 16:58
-
-
Save austind/359dca1217aacf28c16812663270f364 to your computer and use it in GitHub Desktop.
Parses CAM table output from a Cisco switch, adding IP address, hostname, and OUI vendor info from a Windows DHCP server (2012 R2+)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Show all dynamic MACs, excluding the uplink trunk port | |
# Don't includer any header ouptput, only actual entries | |
# e.g., show mac address-table dynamic | ex Gi0/24 | |
$ShMacAddrOutput = @" | |
1 0023.ae57.3df2 DYNAMIC Gi0/7 | |
1 0023.aeaf.77b2 DYNAMIC Gi0/6 | |
1 14b3.1f01.00e4 DYNAMIC Gi0/2 | |
1 28b2.bd8e.5459 DYNAMIC Gi0/3 | |
1 28f1.0e32.a204 DYNAMIC Gi0/1 | |
1 2c76.8ac4.f7e5 DYNAMIC Gi0/3 | |
1 30cd.a73a.a0fe DYNAMIC Gi0/12 | |
1 4c57.ca63.0b5e DYNAMIC Gi0/3 | |
1 8843.e104.1246 DYNAMIC Gi0/3 | |
1 a48d.3b56.b085 DYNAMIC Gi0/3 | |
1 accc.8e49.b7a6 DYNAMIC Gi0/18 | |
1 accc.8e49.b7ac DYNAMIC Gi0/16 | |
1 accc.8e49.b7c0 DYNAMIC Gi0/17 | |
1 accc.8e55.b913 DYNAMIC Gi0/15 | |
1 accc.8e5d.1ab1 DYNAMIC Gi0/19 | |
1 accc.8e76.4716 DYNAMIC Gi0/20 | |
1 b083.fe8f.86a3 DYNAMIC Gi0/11 | |
1 b083.fe9b.5abc DYNAMIC Gi0/13 | |
1 b083.fe9b.5b47 DYNAMIC Gi0/8 | |
1 e4a7.a04f.3689 DYNAMIC Gi0/3 | |
1 f430.b92b.ffc0 DYNAMIC Gi0/14 | |
1 f48e.38dd.6f63 DYNAMIC Gi0/4 | |
5 0010.4948.856d DYNAMIC Gi0/13 | |
5 0010.4948.8576 DYNAMIC Gi0/11 | |
5 0010.4948.85a3 DYNAMIC Gi0/8 | |
5 0010.4949.2777 DYNAMIC Gi0/2 | |
5 0010.4949.2780 DYNAMIC Gi0/4 | |
5 0010.4949.d5ad DYNAMIC Gi0/22 | |
5 0010.4949.d5b1 DYNAMIC Gi0/23 | |
"@ | |
# The command changed column layout. If you're on anything like | |
# modern gear, leave it on $new. If you have a very old IOS that uses | |
# show mac-address-table, change this to $old | |
$ShMacAddrCmd = $new | |
# show mac-address-table (old style) | |
$old = @('mac','type','vlan','port') | |
# show mac address-table (new style) | |
$new = @('vlan','mac','type','port') | |
# http://standards.ieee.org/develop/regauth/oui/oui.txt | |
# this file is huge or else I would pull it with Invoke-WebRequest | |
$OuiDb = 'oui.txt' | |
# Takes FastEthernet0/1 and returns Fa0/1 | |
# Currently not used for anything | |
Function Truncate-PortName { | |
Param ($FullPortName) | |
$PortAbbreviation = $FullPortName.Substring(0,2) | |
$PortID = $FullPortName -replace '[a-zA-Z]', '' | |
return "${PortAbbreviation}${PortId}" | |
} | |
# Takes a MAC in the form of 0011.2233.4455 | |
# Returns 00-11-22-33-44-55 | |
Function Convert-DottedToDashedMac { | |
Param ($MacAddress) | |
$MacAddress = $MacAddress.Replace('.', '') | |
$DashIndices = @(2,5,8,11,14) | |
ForEach($Index in $DashIndices) { | |
$MacAddress = $MacAddress.Insert($Index, '-') | |
} | |
Return $MacAddress | |
} | |
# Split on newline ('\r'), trim leading or trailing whitespace, | |
# then replace any run of one or more spaces with a comma. | |
# Finally, convert to an object array with ConvertFrom-Csv | |
$ParsedCamTable = ($ShMacAddrOutput -split '\r').trim() -replace '[ ]+', ',' | ConvertFrom-Csv -Header $ShMacAddrCmd | |
# Pull all DHCP scopes on the server | |
$Scopes = Get-DhcpServerv4Scope | |
# Resolve scope IDs (which are the subnet IDs) to VLANs | |
# Requires the scope have "VLAN X" in the description field, | |
# or else resolving DHCP IP addresses and hostnames will fail. | |
$ScopeList = @{} | |
$Scopes | % { | |
If ($_.Description -like '*vlan*') { | |
[int]$ScopeVlan = $_.Description -replace '[a-zA-Z]', '' | |
$ScopeList[$ScopeVlan] += $_.ScopeId.IPAddressToString | |
} | |
} | |
$output = @() | |
ForEach ($Entry in $ParsedCamTable) { | |
# Convert MAC from 0011.2233.4455 to 00-11-22-33-44-55, as required for Get-DhcpServerv4Lease | |
$mac = Convert-DottedToDashedMac $entry.mac | |
# Obtain lease if we can. If not found, don't worry about it | |
$Lease = Get-DhcpServerv4Lease -ClientId $mac -ScopeId $ScopeList[[int]$Entry.vlan] -ErrorAction SilentlyContinue | |
# Yank OUI from MAC | |
$Oui = $mac.substring(0,8) | |
# Look up manufacturer from OUI database | |
# This is pretty slow, probably some low-hanging fruit to optimize | |
$Mfgr = ((Select-String $oui $ouidb | Select -exp line) -split '\t{2}')[1] | |
# If we got lease info, add it to output. Otherwise leave blank. | |
If ($Lease) { | |
$IpAddress = $Lease.IPAddress.IPAddressToString | |
$HostName = $Lease.HostName.split('.')[0] | |
} Else { | |
$IpAddress = '' | |
$HostName = '' | |
} | |
# Append result object to output array | |
$output += [PsCustomObject]@{ | |
Port = $Entry.port | |
Mac = $entry.mac | |
DhcpAddress = $IpAddress | |
Vlan = $Entry.vlan | |
DhcpHostName = $HostName | |
Mfgr = $Mfgr | |
} | |
} | |
# You can do whatever you want with $output which is an object array, but | |
# this construct is nice because it sorts output in a neat table, | |
# ordered by the numeric port value. If you just did $(sort -property Port), | |
# you'd get Gi0/2 and Gi0/20 next to each other, since it sorts as a [string] | |
# instead of an [int]. | |
$Output | Sort-Object -Property {[int]($_.port -replace '[a-zA-Z/]', '')},Mac | Format-Table -AutoSize |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment