[dba-VB] Syslogs

Gustav Brock Gustav at cactus.dk
Tue Jun 30 06:50:55 CDT 2009


Hi John (and Max)

If you download the code, a whole module is for resolving IP address and hostname. Nothing rocket science but refined for the purpose.
It even features a static collection inspired by your sales talk on collections.

The key function is this:

<code>
Private Function GetIPFromHostName( _
  ByVal strHostname As String) _
  As String

' Converts a host name to its IP address.
'
' If strHostname
'   - is zero length, local IP address is returned.
'   - is "localhost", IP address 127.0.0.1 is returned.
'   - cannot be resolved, unknown IP address 0.0.0.0 is returned.

  Const clngAddressNone   As Long = 0
  ' The Address is offset 12 bytes from the
  ' start of the HOSENT structure.
  Const clngAddressOffset As Long = 12
  ' Size of address part.
  Const clngAddressChunk  As Long = 4
  ' Address to return if none found.
  Const cstrAddressZero   As String = "0.0.0.0"

  ' Address of HOSENT structure.
  Dim ptrHosent           As Long
  ' Address of name pointer.
  Dim ptrName             As Long
  ' Address of address pointer.
  Dim ptrAddress          As Long
  Dim ptrIPAddress        As Long
  Dim ptrIPAddress2       As Long
  Dim stzHostName         As String
  Dim strAddress          As String

  stzHostName = strHostname & vbNullChar
  ptrHosent = GetHostByName(stzHostName)

  If ptrHosent = clngAddressNone Then
    ' Return address zero.
    strAddress = cstrAddressZero
  Else
    ' Assign pointer addresses and offset Null-terminated list
    ' of addresses for the host.
    ' Note:
    ' We are retrieving only the first address returned.
    ' To return more than one, define strAddress as a string array
    ' and loop through the 4-byte ptrIPAddress members returned.
    ' The last item is a terminating null.
    ' All addresses are returned in network byte order.
    ptrAddress = ptrHosent + clngAddressOffset
    
    ' Get the IP address.
    CopyMemory ptrAddress, ByVal ptrAddress, clngAddressChunk
    CopyMemory ptrIPAddress, ByVal ptrAddress, clngAddressChunk
    CopyMemory ptrIPAddress2, ByVal ptrIPAddress, clngAddressChunk
    
    strAddress = GetInetStrFromPtr(ptrIPAddress2)
  End If
  
  GetIPFromHostName = strAddress
  
End Function
</code>

Problem is that you may have more than one adapter. As stated, this function lists only one which typically is the NIC for your LAN.
Another function reads this out:

<code>
Public Function MachineHostAddress( _
  Optional ByVal strHostname As String) _
  As String
  
' Retrieves IP address of the machine with the host name
' strHostname.
' If a zero length host name or no host name is passed, the
' address of this machine is returned.
' If host name localhost is passed, 127.0.0.1 is returned.
' If the host name cannot be resolved, 0.0.0.0 is returned.
'
' The host addresses are preserved in a static collection to
' reduce look up time for repeated calls.

  ' If strHostname is an empty string, the local host address
  ' will be looked up.
  ' However, an empty string cannot be a key in a collection.
  ' Use this key to store the local host address.
  Const cstrKeyThisHost As String = " "
  
  Static colAddress     As New Collection
  
  Dim strIpAddress      As String
  
  ' Ignore error when looking up a key in collection
  ' colAddress that does not exist.
  On Error Resume Next
  
  If Len(strHostname) = 0 Then
    strHostname = cstrKeyThisHost
  End If
  strIpAddress = colAddress.Item(strHostname)
  ' If strHostname is not found, an error is raised.
  If Err.Number <> 0 Then
    ' This host name has not been looked up previously.
    If WinSocketsStart() = True Then
      ' Obtain the host address.
      ' Trim strHostname to pass a zero length string when
      ' looking up the address of the local host.
      strIpAddress = GetIPFromHostName(Trim(strHostname))
      ' Store the host address.
      colAddress.Add strIpAddress, strHostname
      
      Call WinSocketsClean
    End If
  End If
  
  MachineHostAddress = strIpAddress
  
End Function
</code>

For the helper functions, download the full code.

However, no function is included to reveal the subnet mask. The only "human" method I can locate for this purpose is to look up the registry:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces

Browse these for the key DhcpIPAddress - or, if this is not found, IPAddress - to locate the interface that matches the IP address you retrieved.
When matched, look up the key DhcpSubnetMask - or SubnetMask - to obtain the current subnet mask.

Armed with this - your IP address and subnet mask - you can easily calculate the list of possible IP address on the current LAN.

/gustav


>>> Gustav at cactus.dk 29-06-2009 20:34 >>>
Hi John

As explained in the article on how to create a kind of confirmation system, you could set up a simple two-way system with a single syslog app broadcasting at low frequency "Here I am, and if you are an app from JC, record my address and report back". Your app, when running at the user, would pick up that message and send back a message for the syslog app to collect the addresses of currently running application copies. When a user signs off, after a time-out the syslog app realizes that this copy is off and removes it from the list. Thus, a current list of active applications can be maintained and they can communicate for whatever reason you decide.

Note that communication between machines can really be done in many ways, it is just that syslog is an established standard for simple text messages of about 1K, and if that fits, why reinvent the wheel?

/gustav


>>> jwcolby at colbyconsulting.com 29-06-2009 20:05 >>>
Gustav,

As I mentioned, I have been looking for something like this for years, however everyone has to have 
a list of IPs that can be used with it to make it useful.

I suppose I could kind of bootstrap this thing.  The server address could be found by manual 
observation, then logged in a table along with the machine name.  Each application FE instance looks 
and sends a message that it is logged in.  The RECEIVER grabs the IP address and looks it up in the 
table.  If not there it stores the IP in the table.  Of course then the machine name has to be 
included in the message.

I suppose that I could develop a message library, such that every time an application it fires a 
LOGIN message to everyone already in the table.  The login message has a machine name as the data 
and apparently this widget automatically gets the IP address.  My clients rarely have more than 25 
or so workstations running the application so this shouldn't cause too much grief.  Thus anyone 
listening logs the new person's data into the table if it isn't already there.

Kind of crude but that allows any single running application (that you can manually get the IP for) 
to bootstrap the system and build the list of IPs and machine names.

John W. Colby
www.ColbyConsulting.com 





More information about the dba-VB mailing list