Manipulating IP addresses

the 'lazy sysadmin' method

Once upon a time, I redesigned a LAN : merge two LAN's together after we replaced a slow leased line with modems and routers by a fast optic fiber link. This of course involved some changes to the hosts' network configuration, which we did by DHCP. While we were at it, we redefined address scopes, scope options (default router, prefered DNS servers, etc), new exclusion ranges etc.

This should have worked, except that it did not. Apparently some hosts tended to keep their old addresses, some of which were now in excluded ranges we wanted to use for devices that are better of with fixed addresses (such as servers, routers, printers, ...). Presumably, this was due to the fact that the previous networt admin had set 'infinite' leases. Added to the mix : apparently the dynamic update mechanism between DHCP, WINS and DNS did not behave correctly, resulting in hosts with netbios hostnames different from DNS hostnames.

Whatever the reason, it was getting messy. So, what we wanted was, for each PC on the LAN, to check its IP address, see if it was in the range we wanted it to be in, and have it replaced if it was not, and see if the hostnames for netbios and DNS matched. Not to hard, but quite repetitive, and boring.

Any good sysadmin is a lazy sysadmin. Lazy meaning unwilling to do tasks a computer can do - especially repetitive and boring tasks. The obvious sollution : run a script.
The following script will

  1. get the computer's IP address
  2. check if it is in (one of) the correct range(s)
  3. if it is not : request a new address from the DHCP server
  4. log the change in case the hostname:ipaddress needs to be known
  5. get FQDN to check against hostname for discrepancies. We use a separate script and logfile for clarity

Running such a script at logon/logoff/startup/shutdown or make it a scheduled job will ensure that it is run without user or sysadmin intervention. Only changing the wrong addresses - in stead of renewing all by default - and logging the changes was included to avoid additional headaches, i.e. allow quick diagnostics and troubleshooting if it turned out that changing the IP address had unforeseen consequences (- we're not very well documented -).

'  Koen Noens, January 2006
'  Read IP addresses and issue DHCP request when address deemed incorrect. 

' main
	logfile="D:\modifiedIP.txt"		'replace by UNC to shared file for LAN-wide log
	hostname = gethostname
	strIPAddress = getIPAddress				
	set fso = createObject("scripting.filesystemobject")

	'this is the main test
	'we're using a class C network, so all we need is ceck if the last octet is in one or more given ranges

	if	IsInRange ( getLastOctet(strIPAddress) , 0 , 100 ) OR _ 
		IsInRange ( getLastOctet(strIPAddress) , 200 , 255 ) _ 
		strResult = "modified:" & vbTab & hostname & vbTab & "to " & getIPAddress
		'log it
		set oLog = fso.OpenTextFile(logfile, 8, True)		'append, create if needed
		oLog.WriteLine strResult
		set oLog = Nothing
	end if
	set fso = Nothing

Function getHostName()
	'returns computername of computer where script runs
	Set WshNetwork = WScript.CreateObject("WScript.Network")
	getHostName = WshNetwork.ComputerName
End Function

Function GetIPAddress
	strComputer = "."
	Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
	Set IPConfigSet = objWMIService.ExecQuery _
    		("Select IPAddress from Win32_NetworkAdapterConfiguration" _
        			& " where IPEnabled=TRUE")
	For Each IPConfig in IPConfigSet
		If Not IsNull(IPConfig.IPAddress) Then 
			For i=LBound(IPConfig.IPAddress) to UBound(IPConfig.IPAddress)
            			GetIPAddress =  IPConfig.IPAddress(i)
				Exit For
    		End If

End Function

Sub resetDHCPlease
'	renew DHCP lease by using ipconfig command
 	set shell = createobject("")
	shell.Exec "%comspec% /c ipconfig /release "
	wscript.sleep 2000
	shell.Exec "%comspec% /c ipconfig /renew "
	wscript.sleep 2000
	set shell = nothing
End Sub

Function IsInRange(strNumber,intLow,intHigh)

	'to see if a given number is within a given range, you'd compare the number to the limits (lesser than, greater than)
	'this does not work for 'numeric' strings, i.e. if the numbers you want to compare are in fact strings  - "123" rather than 123
	'we could either try to convert strings to integers or so - but i can't remember what that function was ...
	' workaround : loop through the range and see if anything matches. 

	For i = intLow to intHigh
		If strNumber = Cstr(i) Then
			IsInRange = True
			Exit Function
		End If
	IsInRange = False

End Function

Function getLastOctet (dottedString)
	'returns the final octet of a dotted string ipadress, eg returns 45

	For p = Len(dottedString) to 1 step -1
		If Mid( dottedString, p, 1) = "." Then
			getLastOctet = Right(dottedString, (Len(dottedString)-p))
			Exit Function
		End If
End Function