As you will know from my previous post, I have been paired with writing up a detailed design document for an AD Migration from 2003 to 2012. This also includes migrating the DHCP Server roles from Server 2003 to 2012 and introducing load balancing and failover.
In order for me to document the approach (to be uploaded shortly), I first needed to understand what scopes, options and details each server is hosting.
This is a simple task using the netsh command. From the DHCP server in question, launch a command prompt and execute the following command:
[sourcecode language=”shell”]
netsh dhcp server dump
[/sourcecode]
This will give you the list of scopes and details related to each. However… this is an enterprise network and host multiple DHCP servers across the network!
So first we need to find a list of all DHCP servers across the estate. Another easy task… execute the following command:
[sourcecode language=”shell”]
netsh dhcp show server
[/sourcecode]
Now I know what you might be thinking… netsh is great! Wrong! Unfortunately, there is no way (correct me If i am wrong) to pipe the output from the show server command into the dump server command. Not to mention the fact that it is almost impossible to dump the output from within the netsh command into a file.
So I did what we all do and searched around for a solution and stumbled across the following TechNet site – Enumerate All Authorized DHCP Servers in Active Directory.
This is a VB script that uses SQL commands to extract a list of Authorised DHCP Servers from within Active Directory and spits out the IP Address, Server Name and Ping Result. I amended this script as all I needed was the IP address.
This is a rather lengthy script so I have cut out the sections not required – Hit expand to view.
[sourcecode language=”vb” collapse=”true”]
Option Explicit
On Error Resume Next
Const ADS_SCOPE_SUBTREE = 2
‘used for the returned Array
Const IPADDRESS = 0
Const SERVERNAME = 1
Const PINGRESULT = 2
‘ Dim objects
Dim objDSE, objConnection, objCommand, objRecordSet, objDHCPSrv
‘ Dim strings
Dim strConfigDN, strDHCPServer
‘ Dim Arrays no brackets are used because it’s being return from a function. If you use
‘ brackets to define this array all data will be lost.
‘ [0] = IP Address
‘ [1] = Server Name
‘ [2] = Ping result
Dim arrReturn
‘Determines the domains configuration partition name
Set objDSE = GetObject("LDAP://rootDSE")
strConfigDN = objDSE.Get("configurationNamingContext")
‘creates some connection objects and define needed settings
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
‘Defines SQL Query to AD
objCommand.CommandText = _
"SELECT cn,distinguishedName FROM ‘LDAP://CN=NetServices,CN=Services," & strConfigDN & "’ "
‘Executes the SQL query
Set objRecordSet = objCommand.Execute
‘Sets to the begining of the recordsets returned
objRecordSet.MoveFirst
‘loops through each record set to parse data
Do Until objRecordSet.EOF
‘Ignores the root key NetServices as it does not contain data need
If objRecordSet.Fields("cn").Value <> "NetServices" Then
‘ Ignores DHCP LDAP key as it does not contain data needed
If objRecordSet.Fields("cn").Value <> "DhcpRoot" Then
‘Opens and object to the Authorized dhcp server to expose it’s attributes
Set objDHCPSrv = GetObject("LDAP://" & objRecordSet.Fields("distinguishedName").Value)
‘In some cases the value can be an array and in other cases it’s just a value
If isArray(objDHCPSrv.dhcpServers) Then
For Each strDHCPServer In objDHCPSrv.dhcpservers
arrReturn = fncReturnSrvIP(strDHCPServer)
WScript.Echo arrReturn(SERVERNAME)
Next
Else
arrReturn = fncReturnSrvIP (objDHCPSrv.dhcpservers)
WScript.Echo arrReturn(SERVERNAME)
End If
End If
End If
objRecordSet.MoveNext
Loop
‘Close out created objects
Set objDSE = Nothing
Set objConnection = Nothing
Set objCommand = Nothing
Set objRecordSet = Nothing
Set objDHCPSrv = Nothing
Function fncPingHost (strHostName)
‘ Function pings hostname or ip address and returns a success or failure either 0 for success
‘ or 1 failure
On Error Resume Next
Dim objShell
Dim bPing
Set objShell = CreateObject("WScript.Shell")
bPing = objShell.Run ("ping -n 1 " & strHostName, 0, True)
fncPingHost = bPing
Set objShell = Nothing
End Function
Function fncReturnSrvIP (strDHCPServers)
‘ Function Parses dhcpServers Attribute to pull out server IP and Hostname and returns an Array
‘ with IP, Hostname, Ping results
On Error Resume Next
Dim arrTmpReturn(3), arrTemp
Dim strDHCPSrvIP, strDHCPSrvName
arrTemp = Split(strDHCPServers,"$")
strDHCPSrvIP = Right (arrTemp(0), Len(arrTemp(0)) – 1)
strDHCPSrvName = Right (arrTemp(3), Len(arrTemp(3)) – 1)
arrTmpReturn(IPADDRESS) = strDHCPSrvIP
arrTmpReturn(SERVERNAME) = strDHCPSrvName
arrTmpReturn(PINGRESULT) = fncPingHost (strDHCPSrvName)
fncReturnSrvIP = arrTmpReturn
End Function
[/sourcecode]
Paired up with the dump server script above this works perfectly – below is the final script that was stuck into a batch file and executed.
[sourcecode language=”shell”]
@echo off
cscript //nologo C:\Scripts\Tools\finddhcp.vbs > C:\Scripts\Output\DhcpServerList.txt
for /f %%i in (C:\Scripts\Output\DHCPServerList.txt) do netsh dhcp server \\%%i dump > C:\Scripts\Output\%%i.txt
[/sourcecode]
Enjoy!
Comments