Once upon a time, I used to hard code my user authentication mechanism of choice against an Active Directory Primary Domain Controller (PDC). These were applications in a Microsoft environment (No Apache, Linux, or Firefox). The problem was that the PDC was not correctly maintained. It failed to failover (ironic). Now, I realize that the structure of PDCs and BDCs is not the same in an Active Directory as it was a thousand years ago under Windows NT, but the premise of a primary being automatically replaced by secondary controllers is essentially the same.
Anyway, when the PDC would flake out or become too slow to be useful, the user authentication mechanism would be unusable because it had been hard coded for that bad server. I've used CFEXECUTE to determine the machine name of the current PDC in the domain by calling the JoeWare program called FindPDC. This helped when the fix for the bad server was for the technicians to rush another box into production with a seemingly random machine name. Times have changed, and the servers are under different management and there are about seven pre-named omnipresent domain controllers.
To drop using the FindPDC call through CFEXECUTE, the list of domain controllers is just added to a database and the query cached for 30 days. To determine if the first machine in the query was available, the PING command is issued through CFEXECUTE and the result examined. If the machine fails to be contacted, the next is contacted and so on through the list.
GetPDC is the name chosen for the query, DomainController is the record containing the predefined domain controller machine name. Before this loop, the NamePDC variable is defined as an empty string.
<cfloop index="LoopIndex" list="#ValueList(GetPDC.DomainController)#">
<cfexecute name="ping.exe" arguments="-n 1 -4 -f #LoopIndex#" timeout="10" variable="GetResultPDC" />
<cfif FindNoCase("Request timed out", GetResultPDC) EQ 0 AND FindNoCase("Ping request could not find host", GetResultPDC) EQ 0>
<cfset NamePDC=LoopIndex>
<cfbreak>
<cfelse>
<cfset NamePDC="FAIL">
</cfif>
</cfloop>
The loop goes through the query result, converted to a list in this case and issued a PING command through CFEXECUTE. I've limited the PING echo results to just 1, this is much faster than waiting for the default 4 results. It may make little difference, but I only want IPV4 communication in this example so the -4 and -f options were added.
The GetResultPDC result from the commanded PING may contain the result of timing out or not finding the server being tested, in this example if the results are zero (0) (did not contain those error messages) then CFBREAK out of the loop, we have a server that is answering. This doesn't mean it's guaranteed to do its job as a domain controller, but that its on, has an operating system, is connected to the network and is responding. The NamePDC string is assigned to the current list result called LoopIndex.
If the machine being tested fails, we reassign the string NamePDC. It receives a FAIL value and the loop continues through. If all results of the GetPDC query return PING errors, then the last NamePDC result will contain the FAIL value. If you check for this condition before calling the CFLDAP, or any other authentication mechanism requiring a call against a network server, then the call should not timeout when the server is unreachable.
If you find this post useful please leave a comment and let me know how you used the information.