Results 1 to 7 of 7

Thread: ntohs not working?

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,708

    ntohs not working?

    ntohs, what MSDN says to use for GetTcpTable2 MIB_TCPROW2.dwRemotePort,
    Public Declare Function ntohs Lib "wsock32" (ByVal Addr As Long) As Long,

    does not work. Lots of examples suggest it works (including this VB6 one with GetTcpTable, which doesn't seem to use a different byte order), and I tried using an Integer instead where I copied the first 2 bytes manually, but still, it came out incorrect (per ProcessHacker and TCPView).

    Swapping the byte order manually, however, does work. What's going on here?

  2. #2
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: ntohs not working?

    The "s" means unsigned short. In VB6 an Integer is as close as we can easily get. It only has two bytes.

    Are you sure you don't want to use ntohl() instead?

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,708

    Re: ntohs not working?

    I'm aware, but MIB_TCPROW2.dwRemotePort is a Long (DWORD); I was presuming the VBNET example worked because the function looked at the first two bytes and placed them into the first two bytes of the return, since it didn't error (or return null, just the wrong positive whole number); which as long as it's not doing size checks should theoretically work-- a Long can hold an unsigned Integer.

    Consider,
    Dim lVal As Long
    lVal = 40000&
    ...

    This will be laid out in memory as

    0x 40 9C 00 00

    And the unsigned integer would be 0x 40 9C.

    However, changing it to Integer and copying the first 2 bytes (since the highest port possible is 65,535, it will never use the second two bytes of the DWORD), does give the right port at least for ports under the signed limit, I'll have to open some higher ones to test later.

    ntohl does not return the correct port.

    Also consider how I'm getting the correct port...

    Code:
    Public Function ntohsvb(PT As Long) As Long
    CopyMemory ntohsvb, ByVal VarPtr(PT) + 1&, 1&
    CopyMemory ByVal VarPtr(ntohsvb) + 1&, ByVal VarPtr(PT), 1&
    End Function
    Bypassing any unsigned short concerns.

    I'll have to run the vbnet example, but it would be highly unusual for Randy's examples to be totally wrong like that.

    Edit: It does appear the vbnet example doesn't work and retuns invalid ports... now I'm curious if it worked under XP and earlier... the screenshot suggests yes
    Last edited by fafalone; May 19th, 2022 at 02:06 AM.

  4. #4
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,152

    Re: ntohs not working?

    Quote Originally Posted by fafalone View Post
    Edit: It does appear the vbnet example doesn't work and retuns invalid ports... now I'm curious if it worked under XP and earlier... the screenshot suggests yes
    The vbnet sample works ok on Win7 but is still buggy the same.

    The trouble with ntohs result data-type is that it's not As Long but it's not As Integer too because it's unsigned 16-bit value. Declaring it As Long instead of As Integer saves the sample fiddling with negative ports (everything above port 32768 would come up as negative in the column with local/remote ports).

    When declared As Integer the result is returned in 16-bit AX register while for As Long the result in returned 32-bit EAX register. Changing the declare to As Long implicitly relied on upper half of EAX being all zeroes i.e. the AX is being zero-extended "for free" by the implementation. This worked in 32-bit editions of XP and Win7 but back-fired in recent 64-bit releases so on Win10/Win11 the sample displays whatever garbage is left in upper half of EAX for local/remote ports.

    Fixing this is as simple as using ntohs(.dwLocalPort) And &HFFFF& instead which manually "zero-extends" the returned value from 16-bit to 32-bit.

    cheers,
    </wqw>

  5. #5
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,476

    Re: ntohs not working?

    I got around the issue by declaring the following structures:
    Code:
    'Basic IPv4 addressing structures.
    Private Type in_addr
       s_addr   As Long
    End Type
    Private Type sockaddr_in
        sin_family          As Integer  '2 bytes
        sin_port            As Integer  '2 bytes
        sin_addr            As in_addr  '4 bytes
        sin_zero(0 To 7)    As Byte     '8 bytes
    End Type                            'Total 16 bytes
    
    'Basic IPv6 addressing structures.
    Private Type in6_addr
        s6_addr(0 To 15)      As Byte
    End Type
    Private Type sockaddr_in6
        sin6_family         As Integer  '2 bytes
        sin6_port           As Integer  '2 bytes
        sin6_flowinfo       As Long     '4 bytes
        sin6_addr           As in6_addr '16 bytes
        sin6_scope_id       As Long     '4 bytes
    End Type                            'Total 28 bytes
    
        Dim Sin4 As sockaddr_in
        Dim Sin6 As sockaddr_in6
    Then ntohs(Sin4.sin_port) and ntohs(Sin6.sin6_port) always worked.

    J.A. Coutts

  6. #6
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,152

    Re: ntohs not working?

    Quote Originally Posted by couttsj View Post
    Then ntohs(Sin4.sin_port) and ntohs(Sin6.sin6_port) always worked.
    What exact Declare do you use for ntohs API?

    cheers,
    </wqw>

  7. #7
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,476

    Re: ntohs not working?

    Quote Originally Posted by wqweto View Post
    What exact Declare do you use for ntohs API?

    cheers,
    </wqw>
    Code:
    Private Declare Function ntohs Lib "ws2_32.dll" (ByVal netshort As Long) As Integer
    J.A. Coutts

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width