NetUtils.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
00003  *      The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that: (1) source code distributions
00007  * retain the above copyright notice and this paragraph in its entirety, (2)
00008  * distributions including binary code include the above copyright notice and
00009  * this paragraph in its entirety in the documentation or other materials
00010  * provided with the distribution, and (3) all advertising materials mentioning
00011  * features or use of this software display the following acknowledgement:
00012  * ``This product includes software developed by the University of California,
00013  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
00014  * the University nor the names of its contributors may be used to endorse
00015  * or promote products derived from this software without specific prior
00016  * written permission.
00017  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
00018  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00020  *
00021  */
00022 
00023 #include "config.h"
00024 #include "NetUtils.h"
00025 #include "compat/inet_aton.h"
00026 #include "debug/DebugUtils.h"
00027 #include "debug/Log.h"
00028 #include "thread/SpinLock.h"
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <sys/socket.h>
00032 #include <netdb.h>
00033 
00034 namespace oasys {
00035 
00036 /*
00037  * A faster replacement for inet_ntoa().
00038  * (Copied from the tcpdump source ).
00039  *
00040  * Modified to take the buffer as an argument.
00041  * Returns a pointer within buf where the string starts
00042  *
00043  */
00044 const char *
00045 _intoa(u_int32_t addr, char* buf, size_t bufsize)
00046 {
00047         register char *cp;
00048         register u_int byte;
00049         register int n;
00050         
00051         addr = ntohl(addr);
00052         cp = &buf[bufsize];
00053         *--cp = '\0';
00054 
00055         n = 4;
00056         do {
00057                 byte = addr & 0xff;
00058                 *--cp = byte % 10 + '0';
00059                 byte /= 10;
00060                 if (byte > 0) {
00061                         *--cp = byte % 10 + '0';
00062                         byte /= 10;
00063                         if (byte > 0)
00064                                 *--cp = byte + '0';
00065                 }
00066                 *--cp = '.';
00067                 addr >>= 8;
00068         } while (--n > 0);
00069 
00070         return cp + 1;
00071 }
00072 
00073 int
00074 gethostbyname(const char* name, in_addr_t* addr)
00075 {
00076     ASSERT(addr);
00077 
00078     // name is a numerical address
00079     if (inet_aton(name, (struct in_addr*)addr) != 0) {
00080         return 0;
00081     }
00082 
00083 #if defined(HAVE_GETHOSTBYNAME_R)
00084     
00085     struct hostent h;
00086     char buf[2048];
00087     struct hostent* ret = 0;
00088     (void)ret;
00089     int h_err;
00090 
00091     
00092 #if defined(__sun__) // solaris has different args
00093     if (::gethostbyname_r(name, &h, buf, sizeof(buf), &h_err) < 0) {
00094         log_err("/oasys/net", "error return from gethostbyname_r(%s): %s",
00095                   name, strerror(h_err));
00096         return -1;
00097     }
00098 #else
00099     if (::gethostbyname_r(name, &h, buf, sizeof(buf), &ret, &h_err) < 0) {
00100         log_err("/oasys/net", "error return from gethostbyname_r(%s): %s",
00101                 name, strerror(h_err));
00102         return -1;
00103     }
00104     if (ret == NULL) {
00105         return -1;
00106     }
00107 #endif
00108 
00109     *addr = ((struct in_addr**)h.h_addr_list)[0]->s_addr;
00110 
00111     if (*addr == INADDR_NONE) {
00112         log_err("/oasys/net", "gethostbyname_r(%s) returned INADDR_NONE", name);
00113         return -1;
00114     }
00115     return 0;
00116 
00117 #elif defined(HAVE_GETADDRINFO)
00118 
00119     struct addrinfo hints;
00120     struct addrinfo *res;
00121     int              err;
00122 
00123     memset(&hints, 0, sizeof(hints));
00124     hints.ai_family = PF_INET;
00125     
00126     err = getaddrinfo(name, 0, &hints, &res);
00127     if(err != 0) 
00128         return -1;
00129     
00130     ASSERT(res != 0);
00131     ASSERT(res->ai_family == PF_INET);
00132     *addr = ((struct sockaddr_in*) res->ai_addr)->sin_addr.s_addr;
00133     
00134     freeaddrinfo(res);
00135 
00136     if (*addr == INADDR_NONE) {
00137         log_err("/oasys/net", "getaddrinfo(%s) returned INADDR_NONE", name);
00138         return -1;
00139     }
00140     return 0;
00141     
00142 #elif defined(HAVE_GETHOSTBYNAME)
00143     // make it thread-safe by using a global lock
00144     static SpinLock gethostbyname_lock;
00145     ScopeLock l(&gethostbyname_lock, "gethostbyname");
00146     
00147     struct hostent *hent;
00148     hent = ::gethostbyname(name);
00149     if (hent == NULL) {
00150         logf("/net", LOG_ERR, "error return from gethostbyname(%s): %s",
00151              name, strerror(h_errno));
00152         return -1;
00153     }
00154 
00155     *addr = ((struct in_addr**)hent->h_addr_list)[0]->s_addr;
00156     
00157     if (*addr == INADDR_NONE) {
00158         log_err("/oasys/net", "gethostbyname(%s) returned INADDR_NONE", name);
00159         return -1;
00160     }
00161 
00162     return 0;
00163     
00164 #else
00165 #error No gethostbyname equivalent available for this platform
00166 #endif    
00167 }
00168 
00169 } // namespace oasys

Generated on Fri Dec 22 14:47:59 2006 for DTN Reference Implementation by  doxygen 1.5.1