1
votes

Problem

I am trying to figure out the most reliable way to determine the workstation name of a computer that is connected over a winsock connection in vb6.

Specifics

A server hosts a windows service written in vb6. Other computers on the same network connect to this service, and the service needs to determine the machine name of computers that are connected to it.

Possible Code

The vb6 winsock control has a .RemoteHostIP property that I can use to get the IP.

I found this winapi code to use that IP to get the remote machine name:

  Private mbInitialized As Boolean
  Const WSADescription_Len = 256
  Const WSASYS_Status_Len = 128
  Const AF_INET = 4&


  Private Type HOSTENT
      hName As Long
      hAliases As Long
      hAddrType As Integer
      hLength As Integer
      hAddrList As Long
  End Type


  Private Type WSADATA
      wversion As Integer
      wHighVersion As Integer
      szDescription(0 To WSADescription_Len) As Byte
      szSystemStatus(0 To WSASYS_Status_Len) As Byte
      iMaxSockets As Integer
      iMaxUdpDg As Integer
      lpszVendorInfo As Long
  End Type

  Private Declare Function WSAStartup Lib "wsock32" (ByVal VersionReq As Long, WSADataReturn As WSADATA) As Long
  Private Declare Function WSACleanup Lib "wsock32" () As Long
  Private Declare Function WSAGetLastError Lib "wsock32" () As Long
  Private Declare Function gethostbyaddr Lib "wsock32" (addr As Long, addrLen As Long, addrType As Long) As Long
  Private Declare Function gethostbyname Lib "wsock32" (ByVal hostname As String) As Long
  Private Declare Sub RtlMoveMemory Lib "kernel32" (hpvDest As Any, ByVal hpvSource As Long, ByVal cbCopy As Long)

  Private Sub Class_Initialize()
      Dim wsa As WSADATA
      mbInitialized = (WSAStartup(257, wsa) = 0)
  End Sub
  Private Sub Class_Terminate()
      If mbInitialized Then
       WSACleanup
      End If
  End Sub

  'checks if string is valid IP address

  Private Function CheckIP(IPToCheck As String) As Boolean
      Dim TempValues
      Dim iLoop As Long
      Dim TempByte As Byte
      On Error GoTo CheckIPError

      TempValues = Split(IPToCheck, ".")
      If UBound(TempValues) < 3 Then
          Exit Function
      End If
      For iLoop = LBound(TempValues) To UBound(TempValues)
          TempByte = TempValues(iLoop)
      Next iLoop

      CheckIP = True

CheckIPError:

  End Function

  'converts IP address from string to sin_addr

  Private Function MakeIP(strIP As String) As Long

      Dim vTemp
      Dim lngTemp As Long
      Dim iLoop As Long
      On Error GoTo MakeIPError

      vTemp = Split(strIP, ".")
      For iLoop = 0 To (UBound(vTemp) - 1)
          lngTemp = lngTemp + (vTemp(iLoop) * (256 ^ iLoop))
      Next iLoop
      If vTemp(UBound(vTemp)) < 128 Then
       lngTemp = lngTemp + (vTemp(UBound(vTemp)) * (256 ^ 3))

      Else

          lngTemp = lngTemp + ((vTemp(UBound(vTemp)) - 256) * (256 ^ 3))
      End If

      MakeIP = lngTemp

MakeIPError:
   End Function

  'resolves IP address to host name

  Private Function AddrToName(strAddr As String) As String

      Dim heEntry As HOSTENT
      Dim strHost As String * 255
      Dim strTemp As String
      Dim lngRet As Long
      Dim lngIP As Long

      On Error GoTo AddrToNameError

      If CheckIP(strAddr) Then
          lngIP = MakeIP(strAddr)
          lngRet = gethostbyaddr(lngIP, 4, AF_INET)
          If lngRet = 0 Then
              Exit Function
          End If

          RtlMoveMemory heEntry, lngRet, Len(heEntry)
          RtlMoveMemory ByVal strHost, heEntry.hName, 255
          strTemp = TrimNull(strHost)
          AddrToName = strTemp

      End If

AddrToNameError:

  End Function

  'resolves host name to IP address

  Private Function NameToAddr(ByVal strHost As String)

      Dim ip_list() As Byte
      Dim heEntry As HOSTENT
      Dim strIPAddr As String
      Dim lp_HostEnt As Long

      Dim lp_HostIP As Long
      Dim iLoop As Integer
      On Error GoTo NameToAddrError

      lp_HostEnt = gethostbyname(strHost)
      If lp_HostEnt = 0 Then
          Exit Function
      End If

      RtlMoveMemory heEntry, lp_HostEnt, LenB(heEntry)
      RtlMoveMemory lp_HostIP, heEntry.hAddrList, 4
      ReDim ip_list(1 To heEntry.hLength)

      RtlMoveMemory ip_list(1), lp_HostIP, heEntry.hLength
      For iLoop = 1 To heEntry.hLength
          strIPAddr = strIPAddr & ip_list(iLoop) & "."
      Next

      strIPAddr = Mid(strIPAddr, 1, Len(strIPAddr) - 1)
      NameToAddr = strIPAddr

NameToAddrError:

  End Function

  Public Function AddressToName(strIP As String) As String

      If mbInitialized Then AddressToName = AddrToName(strIP)

  End Function

  Public Function NameToAddress(strName As String) As String

      If mbInitialized Then NameToAddress = NameToAddr(strName)

  End Function

  Private Function TrimNull(sTrim As String) As String

      Dim iFind As Long

      iFind = InStr(1, sTrim, Chr(0))
      If iFind > 0 Then
          TrimNull = Left(sTrim, iFind - 1)
      Else
          TrimNull = sTrim
      End If
  End Function

Which can be called like this:

Dim obj As clsIPResolve
Set obj = New clsIPResolve

msgbox obj.AddressToName(frmMain.sckClient(i).RemoteHostIP)
Set obj = Nothing

Questions:

  1. Does anyone know if this is the best way to do it in vb6? I got it to work in my test environment, but I'm a little nervous to rely on it in 'the real world'.

  2. How does this work exactly? It is obviously doing some sort of reverse DNS using the IP address of the remote machines. Where is it getting this information? The router? Somewhere else?

Thanks for any help in advance!

1

1 Answers

0
votes

1) That code does a simple DNS lookup so by definition will be the network name. If the machine does not have a reverse DNS name, you won't get any meaningful name back and you should use the IP.
Note that the reverse DNS name is NOT the same as the workstation name that the machine has for itself. To get this, you will either need to be part of a domain (I can't provide any code, but the WNet API should get that info, look for NetBios name), or pass it in the socket connection as part of the protocol/initial handshake.

2) It is doing a reverse DNS lookup so will query your local name server to try and get the details. This will then recurse and find an authorative server that can give an answer based on how it's configured or the machines name on the domain.
If the machines are both on the same (Windows) domain, it will also try and do a NetBios lookup on the address.