Friday 15 April 2011

Update to Finding Server's Network Port Programatically

As I posted yesterday I said I may update the batch file to do a little more, well I've been sat around awaiting an engineer so I made a start on doing some improvements.

The following scripts attempts to find the physical adapters in a server that are enabled and arent the HP Teaming Adapter (we are a HP house, so tough if  your not!! :)

Once it has found the adapters it builds the interface name dynamically using the GUID as this is supported by TCPDUMP and then listens for a CDP packet (This is a cisco function that could have been disabled by your network administrators)

After the packet has been recieved it does some pretty messy string manipulation, because I couldnt be bothered to pull my hair out with RegEx. After I have pulled out the information I want I check to see if the Adapter description has the switch port information and update the description if it doesn't.

The script can be ammended to not update the NIC description and just output the details to screen by commenting and uncommenting a few lines.

** Update 21-04-11 - Added code to swap to cscript rather than wscript. **

' ******************************************************************
' NameAdapters.vbs
' ******************************************************************
' Determine Pysical NIC Adapters for Team
' David Wallis - 15/04/11
' ******************************************************************

' ******************************************************************
' 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")
End If

strComputer = "."


Set objShell = CreateObject("Wscript.Shell")
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objShellApp = CreateObject("Shell.Application")
Set objFolder = objShellApp.Namespace(NETWORK_CONNECTIONS)

' NetEnabled is -1 when Enabled and 0 When the NIC is disabled

Set oAdapters = objWMIService.ExecQuery _
   ("Select * from Win32_NetworkAdapter where (NetEnabled = -1)")

' Enumerate the results (list of NICS). "
For Each oAdapter In oAdapters
 If oAdapter.ProductName = "HP Network Teaming Virtual Miniport Driver" Then
  'Teamed Adapter
  'Physical Nic - Execute TCPDUMP
  strCommand = "tcpdump -nn -v -s 1500 -i \Device\" & oAdapter.GUID & " -c 1 ether[20:2] == 0x2000" 

  Wscript.echo "Executing TCP Dump for Adapter " & chr(34) & oAdapter.NetConnectionID & chr(34) & " GUID:" & oAdapter.GUID & 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
    wscript.echo "TCPDUMP Execution Timeout Exceeded, Script Quiting"
   End If
       Wscript.Sleep 250
  ' 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)))
   If Instr(UCASE(strLine),"ADDRESS ") > 0 Then strDeviceIP = Right(strLine,(Len(strLine) - (Instrrev(strLine,")")+1)))
   If Instr(UCASE(strLine),"PORT-ID") > 0 Then strPort = Mid(strLine,(Instr(strLine,chr(39))+1),(Len(StrLine) - (Instr(strLine,chr(39))+1)))

  ' Rename Nic to Contain Switch Name and Port
  ' NetConnectionID Is readonly on some versions of Windows.
  strName = oAdapter.NetConnectionID
  Set colItems = objFolder.Items
  For Each objItem in colItems

       If objItem.Name = strName Then

    'Build Description to Append to Port Name 
    ' Windows doesn't like the / Character, so Replace it with a -

    strDescription = " (" & strDeviceID & " " & strDeviceIP &  " " & Replace(strPort,"/","-") & ")"

    ' If the port doesn't contain the switchport details then add them.
    If Instr(objItem.Name,strDescription) = 0 then
     wscript.echo "Ammending Adapter Description." & vbCrLf
     objItem.Name = strName & strDescription
     wscript.echo "Skipping Adapter Description Ammendment."
    End If
       End If
  Next ' objItem

  'wscript.echo "Details for Adapter " & chr(34) & oAdapter.NetConnectionID & Chr(34)
  'wscript.echo "MAC Addr: " & oAdapter.MACAddress & " Switch: " & strDeviceID & " " & strDeviceIP & " Port: " & strPort & vbCrLf

 End If

Next 'oAdapter

Wednesday 13 April 2011

Finding Server's Network Port Programatically

A while ago using info available on the net I knocked together a batch file that uses a windows port of TCPDUMP that doesn't need winpcap installed.

This worked fine and was great in our environment where CDP is enabled, Some advise disabling for security though.

Well all worked fine until I started trying it on windows 2008 and was receiving the following error message:

tcpdump.exe: PacketGetAdapterNames: The operation completed successfully. (0)

I looked around and 3.9.8 seemed to be the latest version, and doesn't offer support for windows 2008 r2 however I downloaded the trial of version 4 from here

Which still doesn't state it works on windows 2008.. :(  -- however my batch file now works again.. :)

Anyway my rough and ready batch file contains the following:

tcpdump -D
set Interface=
set /P Interface=Enter Interface Number: %=%
tcpdump -nn -v -s 1500 -i %Interface% -c 1 ether[20:2] == 0x2000 >c:\out.txt
Echo "Port Details Are" |Echo.
type c:\out.txt |findstr /R "\Device-ID \Address.[(] \Management.Addresses \Port-ID"
del c:\ out.txt >nul

I will eventually re-write this as powershell or VBS so I can deploy it via SCCM to get a view of ports the servers are patched into.