next up previous Back to Operating Systems Home Page
Next: strtok(3) blues Up: 1996 term messages Previous: Yet again getpeername(2)

IP addresses-names-quads blues

  > I can get the machine name by gethostname(2), but I still can't get the 
  > internet address. 

  >     I got the machine name like 'idefix'
  >     But I can't get the internet address such as 
  > 'idefix@ee.mcgill.ca'   even though I try to use gethostbyname(2)...

Yell to your sysadmin: it means that the machine name in /etc/hosts
is not the full qualified hostname. However, since it might take ages
before that gets changed to the RightThing(tm), you may want to use
a more bulletproof method.

To understand how it works, you need to remember the following:

(a) An IP address is a 32 bit number, represented as by the following struct
    defined in <netinet/in.h>

        struct in_addr {u_long s_addr;};   

    An "u_long" is the same as an "unsigned long" of C, but it's language
    independent.

(b) The name service (gethostbyname(2), gethostbyaddr(2), etc.) represents
    addresses as character strings that *still* encode 32 bit integers in
    their characters bytes. More precisely, gethostbyname(2) returns a
    pointer to a struct defined in <netdb.h>

        struct hostent { 
           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 from name server */
       };
       #define   h_addr  h_addr_list[0]

    and each member of h_addr_list is a pointer to a string of h_length bytes
    encoding an address. Do *not* assume that these are '\0' terminated
    strings, since 0 is a valid byte inside an IP address, hence do not even
    think of processing these strings with the <string.h> functions (strcpy,
    strlen, etc.). 

(c) The h_name field of an hostent, however, is a nice "regular",
    human-readable, 0-terminated string representing the "official" inet host
    name. Same for the aliases.

(d) Both the alias and the address lists are terminated by a (char*)NULL.
    They must be, since the struct does not contain the numner of their
    elements. 

(e) We humans like to write IP addresses in the so-called "dotted quad"
    notation, i.e. with strings like "132.206.8.5", where each number
    represents one byte of the 4-byte long inet address. A nice library
    function, called inet_ntoa(3) can be used to convert an in_addr into a
    dotted quad string. See also inet(3) for other useful library functions
    that manipulate addresses.

(f) Last but not least, the gethostname(2) routine can be used to get the name
    of the local host. However, as your colleague noticed, this may not be the
    full qualified inet name, so you have to pass it through gethostbyname to
    fix it.

The following program is as an example of the above techniques. It gets
the local host name via gethostname(2), then address and full qualified name
via gethostbyname, and eventually translates the address in a dotted quad.

Ciao
Franco

#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int 
main(int argc, char *argv[]) {
    char hname[MAXHOSTNAMELEN];
    char *quad;
    struct hostent *hent;
    struct in_addr adr;
    
    if (-1==gethostname(hname, MAXHOSTNAMELEN)) {
        perror("gethostname");
        exit(1);
    }    
    printf("gethostname: %s\n",hname);

    if (NULL==(hent=gethostbyname(hname))) {
        perror("gethostent");
        exit(1);
    } else  if (AF_INET!=hent->h_addrtype) {
        fprintf(stderr,"gethostbyname: not an AF_INET address\n");
        exit(1);
    }
    printf("gethostbyname: %s\n", hent->h_name);
     
    /* 
    // inet_ntoa(2) needs an in_addr, which we get from the hostent 
    */
    bcopy(hent->h_addr, &adr.s_addr, hent->h_length);
    quad=inet_ntoa(adr);
    printf("hostaddr %s\n", quad);

    return 0;
}



\ Franco Callari