and gethostbyname

Team-FLY

C.2 Name Resolution Implementations

The socket functions are both standardized and generally available. Unfortunately, several options are available for converting between host name and address, and none is optimal for all situations. The functions that are robust and thread-safe are not yet readily available on all systems. We offer several options controlled by compile-time definitions. The two UICI name resolution functions are addr2name and name2addr . Prototypes for these are in uiciname.h , shown in Program C.3.

Program C.3 uiciname.h

The header file for the UICI name resolution functions .

 /* uiciname.h name resolution functions */ #include <netinet/in.h> #define REENTRANT_NONE 0 #define REENTRANT_R 1 #define REENTRANT_MUTEX 2 #define REENTRANT_POSIX 3 int name2addr(char *name, in_addr_t *addrp); void addr2name(struct in_addr addr, char *name, int namelen); 

The addr2name function never returns an error. If the name cannot be resolved, the address is converted to a dotted -decimal notation format. The name2addr function returns 0 on success and “1 on failure. The UICI TCP and UDP functions that call the name resolution functions handle this error by returning “1 and setting errno to EINVAL .

Program C.4 contains four implementations of the name resolution functions addr2name and name2addr . Conditional compilation enables the constant REENTRANCY to determine which implementation is picked. If this constant is not defined, the default value of REENTRANT_NONE is used, giving an implementation with gethostbyname and gethostbyaddr . The value of REENTRANCY can be set either by adding a #define in the uiciname.h file or with a compile-time option.

C.2.1 Implementation with gethostbyaddr and gethostbyname

The first implementation of name resolution presented here uses gethostbyname and gethostbyaddr . These functions should be available on all UNIX implementations. Their main drawback is that they are not thread-safe, so they cannot be directly used by more than one thread. These implementations are used by default or when the constant REENTRANCY is set to REENTRANT_NONE .

C.2.2 Reentrant versions of name resolution functions

If REENTRANCY is equal to REENTRANT_R , the implementations use gethostbyaddr_r and gethostbyname_r . These functions were part of the X/OPEN standard, but when this standard was merged with POSIX, these functions were omitted. However, they are still available on some systems. These functions require a user -supplied buffer, but the documentation does not specify how large this buffer should be. Stevens [115] suggests 8192 for this value, since that is what is commonly used in the implementations of the non-thread-safe forms.

If REENTRANCY is equal to REENTRANT_POSIX , then the implementation uses the newer getnameinfo and getaddrinfo functions. These thread-safe functions can also be used with IPv6. Unfortunately, they are not yet available on many systems. Section 18.8 describes getnameinfo and getaddrinfo .

C.2.3 Reentrant name resolution with mutex locks

If neither group of reentrant name resolution functions is available, you can use gethostbyname and gethostbyaddr by protecting them with mutex locks. Set REENTRANCY to REENTRANT_MUTEX to use this implementation. The implementation uses a single mutex lock to protect calls to gethostbyname and gethostbyaddr .

Program C.4 uiciname.c

Four implementations of the UICI name resolution functions .

 /* uiciname.c  name resolution functions */ #include <ctype.h> #include <netdb.h> #include <string.h> #include <arpa/inet.h> #include <sys/socket.h> #include "uiciname.h" #ifndef REENTRANCY #define REENTRANCY REENTRANT_NONE #endif #if REENTRANCY==REENTRANT_MUTEX #include <pthread.h> static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #endif #if REENTRANCY==REENTRANT_NONE /* Convert struct in_addr to a host name */ void addr2name(struct in_addr addr, char *name, int namelen) {    struct hostent *hostptr;    hostptr = gethostbyaddr((char *)&addr, 4, AF_INET);    if (hostptr == NULL)       strncpy(name, inet_ntoa(addr), namelen-1);    else       strncpy(name, hostptr->h_name, namelen-1);    name[namelen-1] = 0; } /* Return -1 on error, 0 on success */ int name2addr(char *name, in_addr_t *addrp) {    struct hostent *hp;    if (isdigit((int)(*name)))       *addrp = inet_addr(name);    else {       hp = gethostbyname(name);       if (hp == NULL)          return -1;       memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length);    }    return 0; } #elif REENTRANCY==REENTRANT_R #define GETHOST_BUFSIZE 8192 void addr2name(struct in_addr addr, char *name, int namelen) {    char buf[GETHOST_BUFSIZE];    int h_error;    struct hostent *hp;    struct hostent result;    hp = gethostbyaddr_r((char *)&addr, 4, AF_INET, &result, buf,                          GETHOST_BUFSIZE, &h_error);    if (hp == NULL)       strncpy(name, inet_ntoa(addr), namelen-1);    else       strncpy(name, hp->h_name, namelen-1);    name[namelen-1] = 0; } /* Return -1 on error, 0 on success */ int name2addr(char *name, in_addr_t *addrp) {    char buf[GETHOST_BUFSIZE];    int h_error;    struct hostent *hp;    struct hostent result;    if (isdigit((int)(*name)))       *addrp = inet_addr(name);    else {       hp = gethostbyname_r(name, &result, buf, GETHOST_BUFSIZE, &h_error);       if (hp == NULL)          return -1;       memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length);    }    return 0; } #elif REENTRANCY==REENTRANT_MUTEX /* Convert struct in_addr to a host name */ void addr2name(struct in_addr addr, char *name, int namelen) {    struct hostent *hostptr;    if (pthread_mutex_lock(&mutex) == -1) {       strncpy(name, inet_ntoa(addr), namelen-1);       name[namelen-1] = 0;       return;    }    hostptr = gethostbyaddr((char *)&addr, 4, AF_INET);    if (hostptr == NULL)       strncpy(name, inet_ntoa(addr), namelen-1);    else       strncpy(name, hostptr->h_name, namelen-1);    pthread_mutex_unlock(&mutex);    name[namelen-1] = 0; } /* Return -1 on error, 0 on success */ int name2addr(char *name, in_addr_t *addrp) {    struct hostent *hp;    if (isdigit((int)(*name)))       *addrp = inet_addr(name);    else {       if (pthread_mutex_lock(&mutex) == -1)          return -1;       hp = gethostbyname(name);       if (hp == NULL) {          pthread_mutex_unlock(&mutex);          return -1;       }       memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length);       pthread_mutex_unlock(&mutex);    }    return 0; } #elif REENTRANCY==REENTRANT_POSIX /* Convert struct in_addr to a host name */ void addr2name(struct in_addr addr, char *name, int namelen) {    struct sockaddr_in saddr;    saddr.sin_family = AF_INET;    saddr.sin_port = 0;    saddr.sin_addr = addr;    if (getnameinfo((struct sockaddr *)&saddr, sizeof(saddr), name, namelen,          NULL, 0, 0) != 0) {       strncpy(name, inet_ntoa(addr), namelen-1);       name[namelen-1] = 0;    } } /* Return -1 on error, 0 on success */ int name2addr(char *name, in_addr_t *addrp) {    struct addrinfo hints;    struct addrinfo *res;    struct sockaddr_in *saddrp;    hints.ai_flags = AI_PASSIVE;    hints.ai_family = PF_INET;    hints.ai_socktype = SOCK_STREAM;    hints.ai_protocol = 0;    hints.ai_addrlen = 0;    hints.ai_canonname = NULL;    hints.ai_addr = NULL;    hints.ai_next = NULL;    if (getaddrinfo(name, NULL, &hints, &res) != 0)       return -1;    saddrp = (struct sockaddr_in *)(res->ai_addr);    memcpy(addrp, &saddrp->sin_addr.s_addr, 4);    freeaddrinfo(res);    return 0; } #endif 
Team-FLY


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net