Collect CDP informations with SCCM

Did you ever need to know, to wich network switch a computer is connected? When you are a system administrator in a large company with tousends of users, this can be difficult. But when you use SCCM for OS or Software deployment, you have a good inventory tool integreated. Unfortunately SCCM by default only collect datas which the client operating system knows. Your Windows computers doesn’t known to which switch or port they are connected, but if you have Cisco switches the computers would be able to collect this information. Fact is that switches from Cisco are spreading all 60 seconds a lot of information about them to the connected ports (you can disable this, but by default it’s enabled). So you need only a tool to gather this information an write it to the SCCM.

In my case i wrote a vb-script, which runs a little capture tool tcpdump.exe (http://www.microolap.com/products/network/tcpdump/) and wait for the CDP informations. As soon the CDP informations are gathered, they would be writen to a MIF-file. SCCM collect this files frequently and writes the datas to his Database, where you can use it in an Query or an Report.

This is the script, which i tested with Windows XP SP3 and Windows 7 SP1:

' ===========================================================================================
'
'   Script Information
'
'   Filename:           getCDPinformations.vbs
'   Author:             Josh Burkard
'   Date:               25.05.2011
'   Description:        get CDP informations from all enabled network adapters
'                       - writes the information to SCCM MIF file
'
' ===========================================================================================
' Constants
' ===========================================================================================

Const NETWORK_CONNECTIONS = &H31&
Const ForAppending        = 8

strScriptPath             = "\\domain.local\netlogon"         ' Path where TCPdump.exe is
strMifFile                = "\CDP.mif"
strComputer               = "."  

' ===========================================================================================
' Check Script is being run with CSCRIPT rather than WSCRIPT due to using stdout
' ===========================================================================================

If UCase(Right(Wscript.FullName, 11)) = "WSCRIPT.EXE" Then
    strPath = Wscript.ScriptFullName
    ' Wscript.Echo "This script must be run under CScript." & vbCrLf & vbCrLf & "Re-Starting Under CScript"
    strCommand = "%comspec% /K cscript //NOLOGO " & Chr(34) & strPath & chr(34)
    Set objShell = CreateObject("Wscript.Shell")
    objShell.Run(strCommand)
    Wscript.Quit
End If  

Set objShell = CreateObject("Wscript.Shell")
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objShellApp = CreateObject("Shell.Application")
Set objFSO = CreateObject("Scripting.FileSystemObject")

' ===========================================================================================
' Get Temporary and MIF-file directory
' ===========================================================================================

strTempDir = objShell.ExpandEnvironmentStrings("%TEMP%")
strWinDir = objShell.ExpandEnvironmentStrings("%WINDIR%")
strComputerName = objShell.ExpandEnvironmentStrings("%COMPUTERNAME%")
strProcessorArchitecture = objShell.RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE")
If strProcessorArchitecture = "AMD64" Then
	strNoIDMifRegLocation = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\SMS\Client\Configuration\Client Properties\NOIDMIF Directory"
Else
	strNoIDMifRegLocation = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SMS\Client\Configuration\Client Properties\NOIDMIF Directory"
End If

strNoIDMifDir = objShell.RegRead(strNoIDMifRegLocation)
If objFSO.FileExists(strTempDir & strMifFile) Then
	objFSO.DeleteFile(strTempDir & strMifFile)
End If
' ===========================================================================================
' Get Datas and write it to the MIF-file
' ===========================================================================================

Set objFolder = objShellApp.Namespace(NETWORK_CONNECTIONS)
Set oAdapters = objWMIService.ExecQuery ("Select * from Win32_NetworkAdapterConfiguration where (IPenabled = True)")

i = 0	' Counter of detected CDP-Informations

' Enumerate the results (list of NICS). "
For Each oAdapter In oAdapters
	strCommand = strScriptPath & "\tcpdump -nn -v -s 1500 -i \Device\" & oAdapter.SettingID & " -c 1 ether[20:2] == 0x2000"    

	Wscript.echo "Executing TCP Dump for Adapter " & chr(34) & oAdapter.SettingID & chr(34) & VbCrLF
	Wscript.echo strCommand & VbCrLF

	Set objExec = objShell.Exec(strCommand)

	count = 0

	Do Until objExec.Status
		count = count +1
		'Timeout to Deal with Non CDP Enabled Devices
		If count = 1200 then
			objExec.terminate
			wscript.quit
		End If
		Wscript.Sleep 250
	Loop    

	' Loop through the output of TCPDUMP stored in stdout and retrieve required fields
	' Namely switch name, IP and Port

	While Not objExec.StdOut.AtEndOfStream
		strLine = objExec.StdOut.ReadLine
		If Instr(UCASE(strLine),"DEVICE-ID") > 0 Then
			strDeviceID = Mid(strLine,(Instr(strLine,chr(39))+1),(Len(StrLine) - (Instr(strLine,chr(39))+1)))
		End If
		If Instr(UCASE(strLine),"ADDRESS ") > 0 Then
			strDeviceIP = Right(strLine,(Len(strLine) - (Instrrev(strLine,")")+1)))
		End If
		If Instr(UCASE(strLine),"PORT-ID") > 0 Then
			strPort = Mid(strLine,(Instr(strLine,chr(39))+1),(Len(StrLine) - (Instr(strLine,chr(39))+1)))
		End If
	Wend   

	If strPort <> "" AND strDeviceIP <> "" Then
		i = i + 1	' Counter of detected CDP-Informations
		if i = 1 then
			Set objMifFile = objFSO.OpenTextFile(strTempDir & strMifFile, ForAppending, True)

			objMifFile.Writeline "Start Component"
			objMifFile.Writeline "    Name = " & Chr(34) & "WORKSTATION" & Chr(34)
		end if
		objMifFile.Writeline "    Start Group"
		objMifFile.Writeline "        Name = " & Chr(34) & "Cisco Discovery Protocol" & Chr(34)
		objMifFile.Writeline "        ID = " & i
		objMifFile.Writeline "        Class = " & Chr(34) & "CiscoDiscoveryProtocol" & Chr(34)
		objMifFile.Writeline "        Start Attribute"
		objMifFile.Writeline "            Name = " & Chr(34) & "SwitchName" & Chr(34)
		objMifFile.Writeline "            ID = 1"
		objMifFile.Writeline "            ACCESS = READ-ONLY"
		objMifFile.Writeline "            Storage = Specific"
		objMifFile.Writeline "            Type = String(100)"
		objMifFile.Writeline "            Value = " & Chr(34) & strDeviceID & Chr(34)
		objMifFile.Writeline "        End Attribute"
		objMifFile.Writeline "        Start Attribute"
		objMifFile.Writeline "            Name = " & Chr(34) & "SwitchIP" & Chr(34)
		objMifFile.Writeline "            ID = 2"
		objMifFile.Writeline "            ACCESS = READ-ONLY"
		objMifFile.Writeline "            Storage = Specific"
		objMifFile.Writeline "            Type = String(100)"
		objMifFile.Writeline "            Value = " & Chr(34) & strDeviceIP & Chr(34)
		objMifFile.Writeline "        End Attribute"
		objMifFile.Writeline "        Start Attribute"
		objMifFile.Writeline "            Name = " & Chr(34) & "SwitchPort" & Chr(34)
		objMifFile.Writeline "            ID = 3"
		objMifFile.Writeline "            ACCESS = READ-ONLY"
		objMifFile.Writeline "            Storage = Specific"
		objMifFile.Writeline "            Type = String(100)"
		objMifFile.Writeline "            Value = " & Chr(34) & strPort & Chr(34)
		objMifFile.Writeline "        End Attribute"
		objMifFile.Writeline "    End Group"
	End If
Next 'oAdapter  

If i > 0 Then
	objMifFile.Writeline "End Component"
	objMifFile.Close

	If objFSO.FileExists(strNoIDMifDir & strMifFile) Then
		objFSO.DeleteFile(strNoIDMifDir & strMifFile)
	End If

	objFSO.MoveFile strTempDir & strMifFile, strNoIDMifDir & strMifFile
End If

Cause the script need’s elevated user rights, i integrated the script in group policy to run at computer startup.

Comments are closed.