UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

#1 2002-07-25 06:34 PM

HectorLasso
Administrator
From: Colombia
Registered: 2002-06-12
Posts: 353

Re: 3.1 - How do I convert a string into an internet address?

6

If you are reading a host's address from the command line, you may not know if you have an aaa.bbb.ccc.ddd style address, or a host.domain.com style address. What I do with these, is first try to use it as a aaa.bbb.ccc.ddd type address, and if that fails, then do a name lookup on it. Here is an example:

/* Converts ascii text to in_addr struct.  NULL is returned if the 
   address can not be found. */
struct in_addr *atoaddr(char *address) {
  struct hostent *host;
  static struct in_addr saddr;

  /* First try it as aaa.bbb.ccc.ddd. */
  saddr.s_addr = inet_addr(address);
  if (saddr.s_addr != -1) {
    return &saddr;
  }
  host = gethostbyname(address);
  if (host != NULL) {
    return (struct in_addr *) *host->h_addr_list;
  }
  return NULL;
}

From: Rob Seace

Actually, I wouldn't recommend inet_addr() or the
gethostby*() functions anymore... The latter aren't
thread-safe, and both will only work with IPv4... (Plus,
inet_addr() has an ambiguous error return, since -1 is a
valid IP: 255.255.255.255...) I would recommend inet_pton()
for IP translation (or inet_aton(), if you ONLY care about
IPv4; but, why design only for IPv4 in this day and age??),
and getaddrinfo() for hostname translation (in fact, you
can just use getaddrinfo(), and it'll handle IPs, too)...

From: Screwtape

I don't know what you're programming with, but here on
Linux 2.2, neither inet_pton() nor getaddrinfo() exist.

From: JR

getaddrinfo also doesn't exist on SunOS 5.5.1 or winsock 2 (or any BSD variant I think).

IMO it is better to use only BSD sockets. Or at least specify your platform.

From: Rob Seace

Screwtape, you're wrong: I'm sitting at a "Linux 2.2" system right now, and I can assure you it has both inet_pton() and getaddrinfo()... And, in fact, I've got software sitting right here on the machine, which USES both of those functions, and works quite well... (To be more specific, the system is running Red Hat 6.2... But, I've used the functions since at least RH 6.0... But, really, all that matters is the version of glibc, since THAT is what is implementing them; the version of the kernel is not really relevent...) You'll find getaddrinfo() defined in "/usr/include/netdb.h", along with the standard gethostby*() functions... And, you'll find inet_pton() defined in "/usr/include/arpa/inet.h", along with inet_addr(), and all the various other similar functions...

But, more than just being available under Linux (or any other platform glibc is available on), those functions are defined as part of the POSIX.1g standard, now... So, any OS that is POSIX complaint SHOULD be implementing them... But, given that the standards are fairly new still (and, last I heard, were still in flux), I'm sure many still don't support them... Regardless, I still maintain that IF they are available to you, you should use them... If they just aren't available on the platform you need to write code for, then obviously you can't use them... (Well, actually, you COULD, because there are available source code implementations, which you could borrow... If you don't want to dig the code out of glibc, I believe the late, great, and dearly missed W. Richard Stevens made available implementations in the source code for his wonderful "Unix Network Programming" book... Yep, you can get the code right here... Then, after extracting it, you'll find the getaddrinfo() implementation under "unpv12e/libgai/", and inet_pton() under "unpv12e/libfree/"...)

From: Rob Seace

Oh, and if you're interested in more info on the use of getaddrinfo(), inet_pton(), and various other relatively new (and, better) socket functions, I would recommend reading RFC-2553, which details various socket API changes necessary for dealing with IPv6, and mentions both getaddrinfo() and inet_pton()...

From: Bob Kamins
Added on: 2002-02-20 19:51:57

If it is your objective to get a v4 32-bit address from the command line reliably and
painlessly, try something like:

struct sockaddr_in sin; 
   struct hostent *hp; 

   if (!inet_isaddr (argv[1], &sin.sin_addr.s_addr)) { 
      if ((hp = gethostbyname (argv[1])) == NULL) { 
         perror ("gethostbyname"); 
         exit (1); 
      } 
      sin.sin_addr = *(struct in_addr *)*hp->h_host_name; 
   }

The beauty of inet_isaddr() is that it looks for a "valid" dotted-decimal address, and if found,
converts it to its 32-bit equivalent. If the input string is not dotted-decimal,
you can go ahead and call gethostbyname().


From: Michael M Lampkin
Added on: 2006-12-16 02:58:01

Some updates / revisions:

The function gethostbyname is not required to resolve dotted decimal internet addresses and the full specification says that the behaviour when passed an address in that format is undefined.  This means that if you need to use gethostbyname instead of one of the newer functions and it doesn't resolve, you should follow up with ( at least ) an inet_addr or similar call.

Concerning Windows and the availability of getaddrinfo( ... ) in WinSock2:  it is available on Windows XP and later if you include the winsock2.h and ws2tcpip.h headers.

Concerning BSD implementations and the availability of getaddrinfo( ).  This platform has had it available for some time ( 5.n + ) but be warned that the earlier versions had issues with internal memory leaks which cannot be resolved by application level code.

Offline

Board footer

Powered by FluxBB