Jump to content
Tuts 4 You

Question about hostent struct


LCF-AT

Recommended Posts

Hi guys,

today I check some of my windows sockets codes and wanted to update & optimze it a little writing some clean code without to be messy to have also a better view on it.Now I came to the hostent struct which returns a pointer to this struct after calling gethostbyname / gethostbyaddr.Now in the MSDN description I can read that this struct is only used once for each call to this function and  getting overwritten by another call.Now they say I should copy the struct into other buffer.

Quote

The returned hostent structure must be copied to an application buffer if additional calls are to be made to the gethostbyaddr or gethostbyname functions on the same thread. Otherwise, the return value will be overwritten by subsequent gethostbyaddr or gethostbyname calls on the same thread.

So does it mean I dont need to copy it into extra buffer if I call the function from diffrent created threads?Just if I use same thread = copy to buffer?So normaly I call requests using that functions by  new  created threads.Just asking.But also if I would copy the struct into buffer that I also need to copy everything in the whole struct too (whole content) which is a little bad.

Next question about this struct.The struct is declared like this...

hostent STRUCT
  h_name      DWORD      ?
  h_alias     DWORD      ?
  h_addr      WORD       ?
  h_len       WORD       ?
  h_list      DWORD      ?
hostent ENDS

...and now I would like to access the sub contents of each entrys also via another structs but I dont see any more structs into windows.inc file like getting the entry of the array in h_list for example.So in this case I have  to use asm commands like....

    mov     eax, [eax].hostent.h_list 
    mov     eax, [eax]
    mov     eax, [eax]

...without any structs anymore.So,is there any structs I can use go on to access the end content / arrays in windows.inc I didnt seen yet or have I to write any custom struct for that?

Structure
Address    Name                              Type      Value        Hex Dump
015C91E8   h_name                            DWORD     015C9208
015C91EC   h_alias                           DWORD     015C91F8
015C91F0   h_addr                            WORD      0002
015C91F2   h_len                             WORD      0004
015C91F4   h_list                            DWORD     015C91FC

$ ==>    015C91E8 <h_name>    015C9208  ASCII "google.com"
$+4      015C91EC <h_alias>   015C91F8
$+8      015C91F0 <h_addr>    00040002  ASCII "tx "
$+C      015C91F4 <h_list>    015C91FC


h_list   A NULL-terminated list of addresses for the host...
$+14     015C91FC             015C9204  <-- One entry
$+18     015C9200             00000000  <-- End List

One entry
$+1C     015C9204             4E16D9AC  <-- Addresses are returned in network byte order

On the MSDN I found example like this..

remoteHost = gethostbyaddr((char *) &addr, 4, AF_INET);
....

        printf("Function returned:\n");
        printf("\tOfficial name: %s\n", remoteHost->h_name);
        for (pAlias = remoteHost->h_aliases; *pAlias != 0; pAlias++) {
            printf("\tAlternate name #%d: %s\n", ++i, *pAlias);

...remoteHost = hostent pointer / access h_alias *pAlias (what is * with what value?) / checking if not 0 / pAlias++.Somehow it checks whether something is in the h_alias array and then it does print it.So why is there a * sign?Dont check that example not complete.Also that with ++ too.Just asking again of course.

greetz

Link to comment

Ive not looked at directly, but i imagine h_alias (h_aliases) is a pointer to a sequence of dwords (an array). Last dword entry is null to indicate array end. Each dword in array is a pointer to a null terminated string.

So roughly you could do something like the following (havent tested the code btw):
 

LOCAL remoteHost:DWORD ; pointer to hostent structure
LOCAL pAlias:DWORD
LOCAL pAliasCurrent:DWORD
LOCAL pName:DWORD

Invoke gethostbyaddr, Addr szAddress, 4, AF_NET
mov remoteHost, eax

mov ebx, eax ; remote Host is ebx now
mov eax, [ebx].hostent.h_name ; get name
mov pName, eax ; save name
mov eax, [ebx].hostent.h_alias; get pointer to array of pointers (each to a string)
mov pAlias, eax ; save alias


mov pAliasCurrent, eax ; use temp var instead of messing with pAlias directly
mov eax, [eax] ; get first pointer in array
.WHILE eax != 0 ; if pointer is NULL then no more strings

    ; eax contains a pointer to the null terminated string
    ; print it here maybe?
    
    ; increment array to next pointer
    add pAliasCurrent, SIZEOF DWORD ; pAlias++
    mov ebx, pAliasCurrent
    mov eax, [ebx] ; get next dword pointer, to see if we should continue or not
.ENDW

 

  • Like 1
Link to comment

Hi fearless,

thanks for your answer.Good ok so it seems I need to handle that as you said without any extra struct. :)

One more small question about website names & direct IP addresses.Which function I could use to check whether its a name or IP if I dont know it before?

Websitename: 123.456.789.com

IP: 123.456.789.4

Just wanna know how to check if its an NUMERICHOST or not before I use some functions with right flags.

greetz

Link to comment

something like this maybe:

IsNumericHost PROC USES ESI lpszHostAddress:DWORD
    LOCAL RetValue:DWORD
    
    mov RetValue, TRUE ; set to initially be true
    mov esi, lpszHostAddress
    movzx eax, byte ptr [esi]
    .WHILE al != 0
    
        .IF al == '.' || ( al >= '0' && al <= '9' ) ; dots or numerics ok
        .ELSE ; must have encountered a character or other symbol
            mov RetValue, FALSE
            .BREAK ; fall out of loop
        .ENDIF
        
        inc esi
        movzx eax, byte ptr [esi]
    .ENDW
    ; if we got to end of string and fell out of loop then all is good
    ; otherwise if we used break to get here then we got a char
    mov eax, RetValue
    ret
IsNumericHost ENDP

 

  • Like 1
Link to comment

Hi again,

ok.So what about IPv6 addresses?

fe80::cdff:9f34:d69:7323%11

Just checking for any ":" sign or any double "::"?Just asking so maybe I dont need to handle that IPv6 later.

greetz

Link to comment

Hi,

I checked a little more some other windows socket functions I didnt used yet and found 2 functions called getaddrinfo & getnameinfo which can handle ipv4 and ipv6 and I dont need to use the other functions I used before.I made some tests and they seems to work pretty well so far and I also save to write more codes if I use them and I get the sockaddr_in & SOCKADDR_IN6 filled already into ADDRINFO struct.

Now I have a small questions about function just to be sure whether I can use it as I think at the moment and before disabling my old functions code.

Q: getaddrinfo.So at the moment I use this function without to set pHints (filled addrinfo to request) paramter = 0 to get what I can all get back.If the function succeed then I get a filled addrinfo struct back with one or more possible entrys (ai_next) I can check.I did checked the function with some domain names / Ipv4 & Ipv6 strings.In case of google for example I get 2 results back.First is a ai_family IPv6  AF_INET6 and the next one ai_family AF_INET for IPv4.Inside of both are the filled SOCKADDR_IN6 and sockaddr_in struct which I now just use with the socket & connect functions.My code looks like this of both functions...

invoke socket,ADDRINFO.ai_family[edi],ADDRINFO.ai_socktype[edi],ADDRINFO.ai_protocol[edi]
mov s,eax
invoke connect,s,ADDRINFO.ai_addr[edi],ADDRINFO.ai_addrlen[edi]

...all working so far and I get response back later with both anyway whether I use IPv4 or IPv6.The only diffrent I see to the functions paramters of socket & connect is that I used before static values for socket function...

invoke socket,AF_INET,SOCK_STREAM,NULL

...only to handle IPv4 and SOCK_STREAM & NULL for protocol.If I use the new functions then I dont get anything into the ai_socktype back just zero.In the description of the socket function is nothing to find about a 0 socket type only from 1 SOCK_STREAM till 5 SOCK_SEQPACKET.Now I call it with zero as type and it works so far.I just wanna know in this case whether its fine or should I better set the type to SOCK_STREAM if the ai_socktype it zero?Or should I keep it original / untouched?Just aksing to prevent possible issues later and also because I dont see any info about a type NULL in socket function.I thought it should fail but it didnt and works also with 0 paramter.

greetz

  • Like 1
Link to comment

Hi again,

today I checked again some functions to parse URLs and found 3 functions.

http://microsoft.public.win32.programmer.networks.narkive.com/k0t7DFyC/is-there-api-for-parsing-http-addresses-in-ipv6-format

CoInternetParseUrl(IPv4): 1.2.3.4
CoInternetParseUrl(IPv6): [FEDC
InternetCrackUrl(IPv4): 1.2.3.4
InternetCrackUrl(IPv6): FAILED
UrlGetPart(IPv4): 1.2.3.4
UrlGetPart(IPv6): [FEDC

Normaly I do use a modded InternetCrackUrl function.Not sure whether there is any function or custom code what can handle all URLs / shemes / protocls etc.Now I have just a tiny question about the definations of paramters of some functions.So in my case I dont have them all into windows inc file and need to write them by myself.Now in the case of this UrlGetPart function I did checked the header file of (shlwapi.h) to find the right values for the paramters like URL_PART_HOSTNAME for this function.On internet I found some and see this as definition...

typedef enum {
    URL_PART_NONE = 0,
    URL_PART_SCHEME = 1,
    URL_PART_HOSTNAME,
    URL_PART_USERNAME,
    URL_PART_PASSWORD,
    URL_PART_PORT,
    URL_PART_QUERY,
} URL_PART;

typedef enum {
    URLIS_URL,
    URLIS_OPAQUE,
    URLIS_NOHISTORY,
    URLIS_FILEURL,
    URLIS_APPLIABLE,
    URLIS_DIRECTORY,
    URLIS_HASQUERY,
} URLIS;

....URL_PART_NONE has value 0 and URL_PART_SCHEME value 1.Clear so far,but why have the others nothing?In the definition below there have all nothing!Why this?Where to know what value they have?Is that any kind of logic what means something like..."If nothing is there after , = start indexing with 0 then 1 then 2 then 3 etc"?Or what is if for example there is something like this....

typedef enum {
    URL_PART_NONE,
    URL_PART_SCHEME,
    URL_PART_HOSTNAME = 100
    URL_PART_USERNAME,
    URL_PART_PASSWORD,
    URL_PART_PORT,
    URL_PART_QUERY,
} URL_PART;

=
0,1,100,101,102,103,104

?Just wanna know what is right to be sure not to use any wrong values if nothing is declared like in this examples you know.

Thank you

Link to comment

Is that any kind of logic what means something like..."If nothing is there after , = start indexing with 0 then 1 then 2 then 3 etc"?Or what is if for example there is something like this....

 

Yes, you have it right. It starts at 0 by default and increases sequentially by one. if you say ... = 100, it continues from 100, just as you said.

  • Like 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...