code in C, url = inet_ntoa (* (struct in_addr *) ip-h_addr); I do not understand what is happening.

1

I was studying sockets for this material link and I came across a code that I do not understand what is going on. The code part is this:

struct hostent *ip;
...
// função da lib netdb.h para converter ai nosso host para IP
  ip = gethostbyname(host);
  url=inet_ntoa(*(struct in_addr *)ip->h_addr);
  strcat(getpage,page);
  printf("%s",getpage);

The line that starts with 'url' is that I do not understand what's going on. From what I've researched so far I've found that:   the struct hostent has the fields

char  *h_name;            /* official name of host */
char **h_aliases;         /* alias list */
int    h_addrtype;        /* host address type */
int    h_length;          /* length of address */
char **h_addr_list; /* list of addresses */

and the h_addr field equals     char **h_addr_list[0]; //primeira posiçao do vetor h_addr_list .      gethostbyname() returns a hostent (struct!) for the 'ip' variable, then accessing ip-> h_addr I'm accessing a pointer that is of type char , but is being cast for pointer of struct in_addr :

url=inet_ntoa(*(struct in_addr *)ip->h_addr); but h_addr is not a struct in_addr (which has an unsigned long) and to complete, this asterisk * that comes before (struct in_addr *) what are you doing? I did not understand this syntax ... I researched a lot but still did not understand.

    
asked by anonymous 20.07.2018 / 12:31

1 answer

1

Hey, man! Is that okay?

  

but h_addr is not a struct in_addr (which has an unsigned long)

Exactly, as gethostbyname() can return a hostent.h_addr_list containing addrs of type in_addr or in6_addr and for that reason hostent.h_addr_list is **char . so casting is required.

obs. to check which type of addr, you can cast% to sockaddr and check the sa_family field and cast the corresponding cast.


sockaddr *addr = (struct sockaddr *)ip->h_addr;

if(addr.sa_family == INET_ADDR)
{
  in_addr* ipv4 = (struct in_addr*)addr;
}
else if(addr.sa_family == INET6_ADDR)
{
  in6_addr* ipv6 = (struct in_addr*)addr;
}
else
{
  // erro
}

  

To complete, this asterisk * that comes before (struct in_addr *) what are you doing?

According to the statement char *inet_ntoa(struct in_addr in); the in parameter is not a pointer and that is why * is used in the pointer, to get the object instance and the object to be copied and not referenced.

I hope I have been clear.

    
21.07.2018 / 01:31