Figure 5 shows a brief summary of the new name resolution interfaces.
|
|
The getaddrinfo() and getnameinfo() functions provide a protocol-independent way of mapping names to addresses information and of mapping address information back to names. Given a host name, a service name, and other information to constrain the lookup, getaddrinfo() returns either an integer error or a list of filled in addrinfo structures. Each contains the information that needs to be passed to socket() to open a socket as well as the information that needs to be passed to connect() or sendmsg() to reach the named endpoint.
Many programs can simply take the returned list and iterate through it, executing socket() and connect() calls with the information in each list element, until one attempt succeeds completely or the list has been exhausted. Figure 6 gives an example of how to do this. Notice how the program never needs to manipulate addresses directly. The program only needs to take information out of the addrinfo structure and feed it into other functions. This simple block of code is capable of obtaining a connected socket with any stream protocol that is supported in both the kernel and in the runtime library. If the runtime library does not support a protocol, it will not be returned by getaddrinfo(). If the kernel does not support a protocol, this function will print an error for those sockets and skip that protocol. This is especially important for binaries to be shipped on systems where the protocols available in the runtime library and/or kernel can be configured by the end user; one binary will be able to work as long as the system is configured so that there is one protocol that the entire system supports.
Note that getaddrinfo() and getnameinfo() handle both host names and printable numeric addresses, as appropriate. One historical problem with functions like gethostbyname() and gethostbyaddr() is that on some systems they handle printable numeric addresses and on some systems they do not. Portable programs must be written to attempt printable-numeric conversion separately, just in case - programs that assume the system handles these have encountered portability problems. Some programs have bugs caused by the old printable numeric conversion functions, making this even more of a problem. These new functions should hopefully put these problem to rest.
As shown in the example, the gai_strerror() function converts the errors returned by getaddrinfo() and getnameinfo() into human-printable form. There are also constants for the error values, but few programs need to distinguish between the types of failures beyond giving an appropriate error message. The freeaddrinfo() function releases the memory used by the result list, and must be called when the result is no longer needed.
The functions nrl_afnametonum() and nrl_afnumtoname() convert address family names (inet, inet6, local, etc.) to numbers and back. This is needed in order to support user entry of an address family to constrain getaddrinfo() lookups. For example, many NRL IPv6-enabled applications support a command line flag that the user can use to specify a family, such as ``inet'' or ``inet6,'' that selects what protocol to use. The number-to-name function is also helpful for diagnostic output. Similarly, the functions nrl_socktypenametonum() and nrl_socktypenumtoname convert socket type names (stream, dgram, seqpacket, etc.) to numbers and back. These are less useful for user input, but are still useful for diagnostic purposes.
|