Sock_Connect.cpp

Go to the documentation of this file.
00001 // $Id: Sock_Connect.cpp 79134 2007-07-31 18:23:50Z johnnyw $
00002 
00003 #include "ace/Sock_Connect.h"
00004 #include "ace/INET_Addr.h"
00005 #include "ace/Log_Msg.h"
00006 #include "ace/Handle_Set.h"
00007 #include "ace/Auto_Ptr.h"
00008 #include "ace/SString.h"
00009 #include "ace/OS_Memory.h"
00010 #include "ace/OS_NS_stdio.h"
00011 
00012 #if defined (sparc)
00013 #  include "ace/OS_NS_fcntl.h"
00014 #endif  // sparc
00015 
00016 #include "ace/OS_NS_stdlib.h"
00017 #include "ace/OS_NS_string.h"
00018 #include "ace/OS_NS_sys_socket.h"
00019 #include "ace/OS_NS_netdb.h"
00020 #include "ace/OS_NS_unistd.h"
00021 #include "ace/os_include/net/os_if.h"
00022 
00023 #if defined (ACE_HAS_IPV6)
00024 #  include "ace/Guard_T.h"
00025 #  include "ace/Recursive_Thread_Mutex.h"
00026 # if defined (_AIX)
00027 #  include /**/ <netinet/in6_var.h>
00028 # endif /* _AIX */
00029 #endif /* ACE_HAS_IPV6 */
00030 
00031 # if defined (ACE_HAS_GETIFADDRS)
00032 #   if defined (ACE_VXWORKS)
00033 #     include /**/ <net/ifaddrs.h>
00034 #   else
00035 #     include /**/ <ifaddrs.h>
00036 #   endif /*ACE_VXWORKS */
00037 # endif /* ACE_HAS_GETIFADDRS */
00038 
00039 #if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
00040 #include /**/ <inetLib.h>
00041 #include /**/ <netinet/in_var.h>
00042 #if defined (ACE_HAS_IPV6)
00043 #include /**/ <ifLib.h>
00044 extern "C" {
00045   extern struct in_ifaddr* in_ifaddr;
00046   extern LIST_HEAD(in_ifaddrhashhead, in_ifaddr) *in_ifaddrhashtbl;
00047 }
00048 #endif /* ACE_HAS_IPV6 */
00049 #include "ace/OS_NS_stdio.h"
00050 #endif /* ACE_VXWORKS < 0x600 */
00051 
00052 #if defined (ACE_VXWORKS) && ((ACE_VXWORKS == 0x630) || (ACE_VXWORKS == 0x640)) && defined (__RTP__) && defined (ACE_HAS_IPV6)
00053 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
00054 const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
00055 const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
00056 const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
00057 #endif /* ACE_VXWORKS == 0x630 && __RTP__ && ACE_HAS_IPV6 */
00058 
00059 #if defined (ACE_HAS_WINCE)
00060 #include /**/ <Iphlpapi.h>
00061 // The following code is suggested by microsoft as a workaround to the fact
00062 // that on Windows CE, these constants are exported as function addresses
00063 // rather than simply values.
00064 #  include /**/ <ws2tcpip.h>
00065 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
00066 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
00067 #endif  // ACE_HAS_WINCE
00068 
00069 #if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
00070 # include "ace/OS_NS_stdio.h"
00071 #endif
00072 
00073 #if defined (ACE_HAS_IPV6)
00074 
00075 // These defines support a generic usage based on
00076 // the various SIGCF*IF ioctl implementations
00077 
00078 # if defined (SIOCGLIFCONF)
00079 #  define SIOCGIFCONF_CMD SIOCGLIFCONF
00080 #  if defined (__hpux)
00081 #   define IFREQ if_laddrreq
00082 #   define IFCONF if_laddrconf
00083 #   define IFC_REQ iflc_req
00084 #   define IFC_LEN iflc_len
00085 #   define IFC_BUF iflc_buf
00086 #   define IFR_ADDR iflr_addr
00087 #   define IFR_NAME iflr_name
00088 #   define IFR_FLAGS iflr_flags
00089 #   undef SETFAMILY
00090 #   define SA_FAMILY sa_family
00091 #  else
00092 #   define IFREQ lifreq
00093 #   define IFCONF lifconf
00094 #   define IFC_REQ lifc_req
00095 #   define IFC_LEN lifc_len
00096 #   define IFC_BUF lifc_buf
00097 #   define IFR_ADDR lifr_addr
00098 #   define IFR_NAME lifr_name
00099 #   define IFR_FLAGS lifr_flags
00100 #   define SETFAMILY
00101 #   define IFC_FAMILY lifc_family
00102 #   define IFC_FLAGS lifc_flags
00103 #   define SA_FAMILY ss_family
00104 #  endif
00105 # else
00106 #  define SIOCGIFCONF_CMD SIOCGIFCONF
00107 #  define IFREQ ifreq
00108 #  define IFCONF ifconf
00109 #  define IFC_REQ ifc_req
00110 #  define IFC_LEN ifc_len
00111 #  define IFC_BUF ifc_buf
00112 #  define IFR_ADDR ifr_addr
00113 #  define IFR_NAME ifr_name
00114 #  define IFR_FLAGS ifr_flags
00115 #  undef SETFAMILY
00116 #  define SA_FAMILY sa_family
00117 # endif /* SIOCGLIFCONF */
00118 
00119 # if defined (ACE_HAS_THREADS)
00120 #  include "ace/Object_Manager.h"
00121 # endif /* ACE_HAS_THREADS */
00122 
00123 namespace
00124 {
00125   // private:
00126   //  Used internally so not exported.
00127 
00128   // Does this box have ipv4 turned on?
00129   int ace_ipv4_enabled = -1;
00130 
00131   // Does this box have ipv6 turned on?
00132   int ace_ipv6_enabled = -1;
00133 
00134 }
00135 #else /* ACE_HAS_IPV6 */
00136 # define SIOCGIFCONF_CMD SIOCGIFCONF
00137 # define IFREQ ifreq
00138 # define IFCONF ifconf
00139 # define IFC_REQ ifc_req
00140 # define IFC_LEN ifc_len
00141 # define IFC_BUF ifc_buf
00142 # define IFR_ADDR ifr_addr
00143 # define IFR_NAME ifr_name
00144 # define IFR_FLAGS ifr_flags
00145 # undef SETFAMILY
00146 # define SA_FAMILY sa_family
00147 #endif /* ACE_HAS_IPV6 */
00148 
00149 // This is a hack to work around a problem with Visual Age C++ 5 and 6 on AIX.
00150 // Without this, the compiler auto-instantiates the ACE_Auto_Array_Ptr for
00151 // ifreq (contained in this module) but only adds the #include for <net/if.h>
00152 // and not the one for <sys/socket.h> which is also needed.  Although we
00153 // don't need the template defined here, it makes the compiler pull in
00154 // <sys/socket.h> and the build runs clean.
00155 #if defined (AIX) && defined (__IBMCPP__) && (__IBMCPP__ >= 500) && (__IBMCPP__ < 700)
00156 static ACE_Auto_Array_Ptr<sockaddr> force_compiler_to_include_socket_h;
00157 #endif /* AIX && __IBMCPP__ >= 500 */
00158 
00159 
00160 ACE_RCSID (ace,
00161            Sock_Connect,
00162            "$Id: Sock_Connect.cpp 79134 2007-07-31 18:23:50Z johnnyw $")
00163 
00164 
00165 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00166 
00167 // Bind socket to an unused port.
00168 
00169 int
00170 ACE::bind_port (ACE_HANDLE handle, ACE_UINT32 ip_addr, int address_family)
00171 {
00172   ACE_TRACE ("ACE::bind_port");
00173 
00174   ACE_INET_Addr addr;
00175 
00176 #if defined (ACE_HAS_IPV6)
00177   if (address_family != PF_INET6)
00178     // What do we do if it is PF_"INET6?  Since it's 4 bytes, it must be an
00179     // IPV4 address. Is there a difference?  Why is this test done? dhinton
00180 #else /* ACE_HAS_IPV6 */
00181     ACE_UNUSED_ARG (address_family);
00182 #endif /* !ACE_HAS_IPV6 */
00183     addr = ACE_INET_Addr ((u_short)0, ip_addr);
00184 #if defined (ACE_HAS_IPV6)
00185  else if (ip_addr != INADDR_ANY)
00186  // address_family == PF_INET6 and a non default IP address means to bind
00187  // to the IPv4-mapped IPv6 address
00188    addr.set ((u_short)0, ip_addr, 1, 1);
00189 #endif /* ACE_HAS_IPV6 */
00190 
00191 #if !defined (ACE_LACKS_WILDCARD_BIND)
00192   // The OS kernel should select a free port for us.
00193   return ACE_OS::bind (handle,
00194                        (sockaddr*)addr.get_addr(),
00195                        addr.get_size());
00196 #else
00197   static u_short upper_limit = ACE_MAX_DEFAULT_PORT;
00198   int round_trip = upper_limit;
00199   int lower_limit = IPPORT_RESERVED;
00200 
00201   // We have to select the port explicitly.
00202 
00203   for (;;)
00204     {
00205       addr.set((u_short)upper_limit,ip_addr);
00206 
00207       if (ACE_OS::bind (handle,
00208                         (sockaddr*)addr.get_addr()
00209                         addr.get_size()) >= 0)
00210         {
00211 #if defined (ACE_WIN32)
00212           upper_limit--;
00213 #endif /* ACE_WIN32 */
00214           return 0;
00215         }
00216       else if (errno != EADDRINUSE)
00217         return -1;
00218       else
00219         {
00220           upper_limit--;
00221 
00222           // Wrap back around when we reach the bottom.
00223           if (upper_limit <= lower_limit)
00224             upper_limit = ACE_MAX_DEFAULT_PORT;
00225 
00226           // See if we have already gone around once!
00227           if (upper_limit == round_trip)
00228             {
00229               errno = EAGAIN;
00230               return -1;
00231             }
00232         }
00233     }
00234 #endif /* ACE_HAS_WILDCARD_BIND */
00235 }
00236 
00237 int
00238 ACE::get_bcast_addr (ACE_UINT32 &bcast_addr,
00239                      const ACE_TCHAR *host_name,
00240                      ACE_UINT32 host_addr,
00241                      ACE_HANDLE handle)
00242 {
00243   ACE_TRACE ("ACE::get_bcast_addr");
00244 
00245 #if defined (ACE_LACKS_GET_BCAST_ADDR)
00246   ACE_UNUSED_ARG (bcast_addr);
00247   ACE_UNUSED_ARG (host_name);
00248   ACE_UNUSED_ARG (host_addr);
00249   ACE_UNUSED_ARG (handle);
00250   ACE_NOTSUP_RETURN (-1);
00251 #elif !defined(ACE_WIN32) && !defined(__INTERIX)
00252   ACE_HANDLE s = handle;
00253 
00254   if (s == ACE_INVALID_HANDLE)
00255     s = ACE_OS::socket (AF_INET, SOCK_STREAM, 0);
00256 
00257   if (s == ACE_INVALID_HANDLE)
00258     ACE_ERROR_RETURN ((LM_ERROR,
00259                        ACE_TEXT ("%p\n"),
00260                        ACE_TEXT ("ACE_OS::socket")),
00261                       -1);
00262 
00263   struct ifconf ifc;
00264   char buf[BUFSIZ];
00265 
00266   ifc.ifc_len = sizeof buf;
00267   ifc.ifc_buf = buf;
00268 
00269   // Get interface structure and initialize the addresses using UNIX
00270   // techniques
00271   if (ACE_OS::ioctl (s, SIOCGIFCONF_CMD, (char *) &ifc) == -1)
00272     ACE_ERROR_RETURN ((LM_ERROR,
00273                        ACE_TEXT ("%p\n"),
00274                        ACE_TEXT ("ACE::get_bcast_addr:")
00275                        ACE_TEXT ("ioctl (get interface configuration)")),
00276                       -1);
00277 
00278   struct ifreq *ifr = ifc.ifc_req;
00279 
00280   struct sockaddr_in ip_addr;
00281 
00282   // Get host ip address if necessary.
00283   if (host_name)
00284     {
00285       hostent *hp = ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name));
00286 
00287       if (hp == 0)
00288         return -1;
00289       else
00290 #if !defined(_UNICOS)
00291         ACE_OS::memcpy ((char *) &ip_addr.sin_addr.s_addr,
00292                         (char *) hp->h_addr,
00293                         hp->h_length);
00294 #else /* _UNICOS */
00295       {
00296         ACE_UINT64 haddr;  // a place to put the address
00297         char * haddrp = (char *) &haddr;  // convert to char pointer
00298         ACE_OS::memcpy(haddrp,(char *) hp->h_addr,hp->h_length);
00299         ip_addr.sin_addr.s_addr = haddr;
00300       }
00301 #endif /* ! _UNICOS */
00302     }
00303   else
00304     {
00305       ACE_OS::memset ((void *) &ip_addr, 0, sizeof ip_addr);
00306 #if !defined(_UNICOS)
00307       ACE_OS::memcpy ((void *) &ip_addr.sin_addr,
00308                       (void*) &host_addr,
00309                       sizeof ip_addr.sin_addr);
00310 #else /* _UNICOS */
00311       ip_addr.sin_addr.s_addr = host_addr;   // just copy to the bitfield
00312 #endif /* ! _UNICOS */
00313     }
00314 
00315 #if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
00316   for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
00317        n--, ifr++)
00318 #else
00319   // see mk_broadcast@SOCK_Dgram_Bcast.cpp
00320   for (int nbytes = ifc.ifc_len; nbytes >= (int) sizeof (struct ifreq) &&
00321         ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
00322           (nbytes >= (int) sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len) : 1);
00323         ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
00324           (nbytes -= sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len,
00325             ifr = (struct ifreq *)
00326               ((caddr_t) &ifr->ifr_addr + ifr->ifr_addr.sa_len)) :
00327           (nbytes -= sizeof (struct ifreq), ifr++)))
00328 #endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
00329     {
00330       struct sockaddr_in if_addr;
00331 
00332       // Compare host ip address with interface ip address.
00333       ACE_OS::memcpy (&if_addr,
00334                       &ifr->ifr_addr,
00335                       sizeof if_addr);
00336 
00337       if (ip_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
00338         continue;
00339 
00340       if (ifr->ifr_addr.sa_family != AF_INET)
00341         {
00342           ACE_ERROR ((LM_ERROR,
00343                       ACE_TEXT ("%p\n"),
00344                       ACE_TEXT ("ACE::get_bcast_addr:")
00345                       ACE_TEXT ("Not AF_INET")));
00346           continue;
00347         }
00348 
00349       struct ifreq flags = *ifr;
00350       struct ifreq if_req = *ifr;
00351 
00352       if (ACE_OS::ioctl (s, SIOCGIFFLAGS, (char *) &flags) == -1)
00353         {
00354           ACE_ERROR ((LM_ERROR,
00355                       ACE_TEXT ("%p\n"),
00356                       ACE_TEXT ("ACE::get_bcast_addr:")
00357                       ACE_TEXT (" ioctl (get interface flags)")));
00358           continue;
00359         }
00360 
00361       if (ACE_BIT_DISABLED (flags.ifr_flags, IFF_UP))
00362         {
00363           ACE_ERROR ((LM_ERROR,
00364                       ACE_TEXT ("%p\n"),
00365                       ACE_TEXT ("ACE::get_bcast_addr:")
00366                       ACE_TEXT ("Network interface is not up")));
00367           continue;
00368         }
00369 
00370       if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_LOOPBACK))
00371         continue;
00372 
00373       if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_BROADCAST))
00374         {
00375           if (ACE_OS::ioctl (s,
00376                              SIOCGIFBRDADDR,
00377                              (char *) &if_req) == -1)
00378             ACE_ERROR ((LM_ERROR,
00379                         ACE_TEXT ("%p\n"),
00380                         ACE_TEXT ("ACE::get_bcast_addr:")
00381                         ACE_TEXT ("ioctl (get broadaddr)")));
00382           else
00383             {
00384               ACE_OS::memcpy (&ip_addr,
00385                               &if_req.ifr_broadaddr,
00386                               sizeof if_req.ifr_broadaddr);
00387 
00388               ACE_OS::memcpy ((void *) &host_addr,
00389                               (void *) &ip_addr.sin_addr,
00390                               sizeof host_addr);
00391 
00392               if (handle == ACE_INVALID_HANDLE)
00393                 ACE_OS::close (s);
00394 
00395               bcast_addr = host_addr;
00396               return 0;
00397             }
00398         }
00399       else
00400         ACE_ERROR ((LM_ERROR,
00401                     ACE_TEXT ("%p\n"),
00402                     ACE_TEXT ("ACE::get_bcast_addr:")
00403                     ACE_TEXT ("Broadcast is not enable for this interface.")));
00404 
00405       if (handle == ACE_INVALID_HANDLE)
00406         ACE_OS::close (s);
00407 
00408       bcast_addr = host_addr;
00409       return 0;
00410     }
00411 
00412   return 0;
00413 #else
00414   ACE_UNUSED_ARG (handle);
00415   ACE_UNUSED_ARG (host_addr);
00416   ACE_UNUSED_ARG (host_name);
00417   bcast_addr = (ACE_UINT32 (INADDR_BROADCAST));
00418   return 0;
00419 #endif /* !ACE_WIN32 && !__INTERIX */
00420 }
00421 
00422 int
00423 ACE::get_fqdn (ACE_INET_Addr const & addr,
00424                char hostname[],
00425                size_t len)
00426 {
00427   int h_error;  // Not the same as errno!
00428   hostent hentry;
00429   ACE_HOSTENT_DATA buf;
00430 
00431   char * ip_addr = 0;
00432   int ip_addr_size = 0;
00433   if (addr.get_type () == AF_INET)
00434     {
00435       sockaddr_in * const sock_addr =
00436         reinterpret_cast<sockaddr_in *> (addr.get_addr ());
00437       ip_addr_size = sizeof sock_addr->sin_addr;
00438       ip_addr = (char*) &sock_addr->sin_addr;
00439     }
00440 #ifdef ACE_HAS_IPV6
00441   else
00442     {
00443       sockaddr_in6 * sock_addr =
00444         reinterpret_cast<sockaddr_in6 *> (addr.get_addr ());
00445 
00446       ip_addr_size = sizeof sock_addr->sin6_addr;
00447       ip_addr = (char*) &sock_addr->sin6_addr;
00448     }
00449 #endif  /* ACE_HAS_IPV6 */
00450 
00451    // get the host entry for the address in question
00452    hostent * const hp = ACE_OS::gethostbyaddr_r (ip_addr,
00453                                                  ip_addr_size,
00454                                                  addr.get_type (),
00455                                                  &hentry,
00456                                                  buf,
00457                                                  &h_error);
00458 
00459    // if it's not found in the host file or the DNS datase, there is nothing
00460    // much we can do. embed the IP address
00461    if (hp == 0 || hp->h_name == 0)
00462      return -1;
00463 
00464    if (ACE::debug())
00465      ACE_DEBUG ((LM_DEBUG,
00466                  ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
00467                  ACE_TEXT ("canonical host name is %s\n"),
00468                  ACE_TEXT_CHAR_TO_TCHAR (hp->h_name)));
00469 
00470    // check if the canonical name is the FQDN
00471    if (!ACE_OS::strchr(hp->h_name, '.'))
00472      {
00473        // list of address
00474        char** p;
00475        // list of aliases
00476        char** q;
00477 
00478        // for every address and for every alias within the address, check and
00479        // see if we can locate a FQDN
00480        for (p = hp->h_addr_list; *p != 0; ++p)
00481          {
00482            for (q = hp->h_aliases; *q != 0; ++q)
00483              {
00484                if (ACE_OS::strchr(*q, '.'))
00485                  {
00486                    // we got an FQDN from an alias. use this
00487                    if (ACE_OS::strlen (*q) >= len)
00488                      // the hostname is too huge to fit into a
00489                      // buffer of size MAXHOSTNAMELEN
00490                      // should we check other aliases as well
00491                      // before bailing out prematurely?
00492                      // for right now, let's do it. this (short name)
00493                      // is atleast better than embedding the IP
00494                      // address in the profile
00495                      continue;
00496 
00497                    if (ACE::debug ())
00498                      ACE_DEBUG ((LM_DEBUG,
00499                                  ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
00500                                  ACE_TEXT ("found fqdn within alias as %s\n"),
00501                                  ACE_TEXT_CHAR_TO_TCHAR(*q)));
00502                    ACE_OS::strcpy (hostname, *q);
00503 
00504                    return 0;
00505                  }
00506              }
00507          }
00508      }
00509 
00510    // The canonical name may be an FQDN when we reach here.
00511    // Alternatively, the canonical name (a non FQDN) may be the best
00512    // we can do.
00513    if (ACE_OS::strlen (hp->h_name) >= len)
00514      {
00515        // The hostname is too large to fit into a buffer of size
00516        // MAXHOSTNAMELEN.
00517        return -2;
00518      }
00519    else
00520      {
00521        ACE_OS::strcpy (hostname, hp->h_name);
00522      }
00523 
00524    return 0;
00525 }
00526 
00527 #if defined (ACE_WIN32)
00528 
00529 static int
00530 get_ip_interfaces_win32 (size_t &count,
00531                          ACE_INET_Addr *&addrs)
00532 {
00533 # if defined (ACE_HAS_WINCE)
00534   // moved the ACE_HAS_WINCE impl ahaid of ACE_HAS_WINSOCK2 because
00535   // WINCE in fact has winsock2, but doesn't properly support the
00536   // WSAIoctl for obtaining IPv6 address info.
00537   PIP_ADAPTER_ADDRESSES AdapterAddresses = 0;
00538   ULONG OutBufferLength = 0;
00539   ULONG RetVal = 0;
00540   unsigned char *octet_buffer = 0;
00541 
00542   RetVal =
00543     GetAdaptersAddresses(AF_UNSPEC,
00544                          0,
00545                          0,
00546                          AdapterAddresses,
00547                          &OutBufferLength);
00548 
00549   if (RetVal != ERROR_BUFFER_OVERFLOW)
00550     {
00551       return -1;
00552     }
00553 
00554   ACE_NEW_RETURN (octet_buffer, unsigned char[OutBufferLength],-1);
00555   AdapterAddresses = (IP_ADAPTER_ADDRESSES *)octet_buffer;
00556 
00557   RetVal =
00558     GetAdaptersAddresses(AF_UNSPEC,
00559                          0,
00560                          0,
00561                          AdapterAddresses,
00562                          &OutBufferLength);
00563 
00564   if (RetVal != NO_ERROR)
00565     {
00566       delete [] octet_buffer;
00567       return -1;
00568      }
00569 
00570   // If successful, output some information from the data we received
00571   PIP_ADAPTER_ADDRESSES AdapterList = AdapterAddresses;
00572   while (AdapterList)
00573     {
00574       if (AdapterList->OperStatus == IfOperStatusUp)
00575         {
00576           if (AdapterList->IfIndex != 0)
00577             ++count;
00578           if (AdapterList->Ipv6IfIndex != 0)
00579             ++count;
00580         }
00581       AdapterList = AdapterList->Next;
00582     }
00583 
00584   AdapterList = AdapterAddresses;
00585 
00586   ACE_NEW_RETURN (addrs, ACE_INET_Addr[count],-1);
00587   count = 0;
00588   for (AdapterList =  AdapterAddresses;
00589        AdapterList != 0;
00590        AdapterList = AdapterList->Next)
00591     {
00592       if (AdapterList->OperStatus != IfOperStatusUp)
00593         continue;
00594 
00595       IP_ADAPTER_UNICAST_ADDRESS *uni = 0;
00596       if (AdapterList->IfIndex != 0)
00597         for (uni = AdapterList->FirstUnicastAddress;
00598              uni != 0;
00599              uni = uni->Next)
00600           {
00601             SOCKET_ADDRESS *sa_addr = &uni->Address;
00602             if (sa_addr->lpSockaddr->sa_family == AF_INET)
00603               {
00604                 sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
00605                 addrs[count].set(sin,sa_addr->iSockaddrLength);
00606                 ++count;
00607                 break;
00608               }
00609           }
00610       if (AdapterList->Ipv6IfIndex != 0)
00611         {
00612         for (uni = AdapterList->FirstUnicastAddress;
00613              uni != 0;
00614              uni = uni->Next)
00615             {
00616               SOCKET_ADDRESS *sa_addr = &uni->Address;
00617               if (sa_addr->lpSockaddr->sa_family == AF_INET6)
00618                 {
00619                   sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
00620                   addrs[count].set(sin,sa_addr->iSockaddrLength);
00621                   ++count;
00622                   break;
00623                 }
00624             }
00625         }
00626     }
00627 
00628   delete [] octet_buffer;
00629   return 0;
00630 
00631 # elif defined (ACE_HAS_PHARLAP)
00632   // PharLap ETS has its own kernel routines to rummage through the device
00633   // configs and extract the interface info, but only for Pharlap RT.
00634 #   if !defined (ACE_HAS_PHARLAP_RT)
00635   ACE_NOTSUP_RETURN (-1);
00636 #   endif /* ACE_HAS_PHARLAP_RT */
00637 
00638   // Locate all of the IP devices in the system, saving a DEVHANDLE
00639   // for each. Then allocate the ACE_INET_Addrs needed and fetch all
00640   // the IP addresses.  To locate the devices, try the available
00641   // device name roots and increment the device number until the
00642   // kernel says there are no more of that type.
00643   const size_t ACE_MAX_ETS_DEVICES = 64;  // Arbitrary, but should be enough.
00644   DEVHANDLE ip_dev[ACE_MAX_ETS_DEVICES];
00645   EK_TCPIPCFG *devp;
00646   size_t i, j;
00647   ACE_TCHAR dev_name[16];
00648 
00649   count = 0;
00650   for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
00651     {
00652       // Ethernet.
00653       ACE_OS::sprintf (dev_name,
00654                        "ether%d",
00655                        i);
00656       ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
00657       if (ip_dev[count] == 0)
00658         break;
00659     }
00660   for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
00661     {
00662       // SLIP.
00663       ACE_OS::sprintf (dev_name,
00664                        "sl%d",
00665                        i);
00666       ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
00667       if (ip_dev[count] == 0)
00668         break;
00669     }
00670   for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
00671     {
00672       // PPP.
00673       ACE_OS::sprintf (dev_name,
00674                        "ppp%d",
00675                        i);
00676       ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
00677       if (ip_dev[count] == 0)
00678         break;
00679     }
00680 
00681   if (count > 0)
00682     ACE_NEW_RETURN (addrs,
00683                     ACE_INET_Addr[count],
00684                     -1);
00685   else
00686     addrs = 0;
00687 
00688   for (i = 0, j = 0; i < count; i++)
00689     {
00690       devp = EtsTCPGetDeviceCfg (ip_dev[i]);
00691       if (devp != 0)
00692         {
00693           addrs[j].set (0,
00694                         devp->nwIPAddress,
00695                         0); // Already in net order.
00696           ++j;
00697         }
00698       // There's no call to close the DEVHANDLE.
00699     }
00700 
00701   count = j;
00702   if (count == 0 && addrs != 0)
00703     {
00704       delete [] addrs;
00705       addrs = 0;
00706     }
00707 
00708   return 0;
00709 
00710 
00711 # else
00712   // All non-CE, non-Pharlap Windows. Must support Winsock2.
00713 
00714   int i, n_interfaces, status;
00715 
00716   INTERFACE_INFO info[64];
00717   SOCKET sock;
00718 
00719   // Get an (overlapped) DGRAM socket to test with
00720   sock = socket (AF_INET, SOCK_DGRAM, 0);
00721   if (sock == INVALID_SOCKET)
00722     return -1;
00723 
00724   DWORD bytes;
00725   status = WSAIoctl(sock,
00726                     SIO_GET_INTERFACE_LIST,
00727                     0,
00728                     0,
00729                     info,
00730                     sizeof(info),
00731                     &bytes,
00732                     0,
00733                     0);
00734   closesocket (sock);
00735   if (status == SOCKET_ERROR)
00736     return -1;
00737 
00738   n_interfaces = bytes / sizeof(INTERFACE_INFO);
00739 
00740   // SIO_GET_INTERFACE_LIST does not work for IPv6
00741   // Instead recent versions of Winsock2 add the new opcode
00742   // SIO_ADDRESS_LIST_QUERY.
00743   // If this is not available forget about IPv6 local interfaces:-/
00744   int n_v6_interfaces = 0;
00745 
00746 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
00747 
00748   LPSOCKET_ADDRESS_LIST v6info;
00749   char *buffer;
00750   DWORD buflen = sizeof (SOCKET_ADDRESS_LIST) + (63 * sizeof (SOCKET_ADDRESS));
00751   ACE_NEW_RETURN (buffer,
00752                   char[buflen],
00753                   -1);
00754   v6info = reinterpret_cast<LPSOCKET_ADDRESS_LIST> (buffer);
00755 
00756   // Get an (overlapped) DGRAM socket to test with.
00757   // If it fails only return IPv4 interfaces.
00758   sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
00759   if (sock != INVALID_SOCKET)
00760     {
00761       status = WSAIoctl(sock,
00762                         SIO_ADDRESS_LIST_QUERY,
00763                         0,
00764                         0,
00765                         v6info,
00766                         buflen,
00767                         &bytes,
00768                         0,
00769                         0);
00770       closesocket (sock);
00771       if (status != SOCKET_ERROR)
00772         n_v6_interfaces = v6info->iAddressCount;
00773     }
00774 # endif /* ACE_HAS_IPV6 */
00775 
00776   ACE_NEW_RETURN (addrs,
00777                   ACE_INET_Addr[n_interfaces + n_v6_interfaces],
00778                   -1);
00779 
00780   // Now go through the list and transfer the good ones to the list of
00781   // because they're down or don't have an IP address.
00782   for (count = 0, i = 0; i < n_interfaces; ++i)
00783     {
00784       LPINTERFACE_INFO lpii;
00785       struct sockaddr_in *addrp = 0;
00786 
00787       lpii = &info[i];
00788       if (!(lpii->iiFlags & IFF_UP))
00789         continue;
00790 
00791       // We assume IPv4 addresses here
00792       addrp = reinterpret_cast<struct sockaddr_in *> (&lpii->iiAddress.AddressIn);
00793       if (addrp->sin_addr.s_addr == INADDR_ANY)
00794         continue;
00795 
00796       // Set the address for the caller.
00797       addrs[count].set(addrp, sizeof(sockaddr_in));
00798       ++count;
00799     }
00800 
00801 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
00802   // Now go through the list and transfer the good ones to the list of
00803   // because they're down or don't have an IP address.
00804   for (i = 0; i < n_v6_interfaces; i++)
00805     {
00806       struct sockaddr_in6 *addr6p;
00807 
00808       if (v6info->Address[i].lpSockaddr->sa_family != AF_INET6)
00809         continue;
00810 
00811       addr6p = reinterpret_cast<struct sockaddr_in6 *> (v6info->Address[i].lpSockaddr);
00812       if (IN6_IS_ADDR_UNSPECIFIED(&addr6p->sin6_addr))  // IN6ADDR_ANY?
00813         continue;
00814 
00815       // Set the address for the caller.
00816       addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr6p), sizeof(sockaddr_in6));
00817       ++count;
00818     }
00819 
00820   delete [] buffer; // Clean up
00821 # endif /* ACE_HAS_IPV6 */
00822 
00823   if (count == 0)
00824     {
00825       delete [] addrs;
00826       addrs = 0;
00827     }
00828 
00829   return 0;
00830 
00831 # endif /* ACE_HAS_WINCE */
00832 }
00833 #elif defined (ACE_HAS_GETIFADDRS)
00834 static int
00835 get_ip_interfaces_getifaddrs (size_t &count,
00836                               ACE_INET_Addr *&addrs)
00837 {
00838   // Take advantage of the BSD getifaddrs function that simplifies
00839   // access to connected interfaces.
00840   struct ifaddrs *ifap = 0;
00841   struct ifaddrs *p_if = 0;
00842 
00843   if (::getifaddrs (&ifap) != 0)
00844     return -1;
00845 
00846   // Count number of interfaces.
00847   size_t num_ifs = 0;
00848   for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
00849     ++num_ifs;
00850 
00851   // Now create and initialize output array.
00852   ACE_NEW_RETURN (addrs,
00853                   ACE_INET_Addr[num_ifs],
00854                   -1); // caller must free
00855 
00856   // Pull the address out of each INET interface.  Not every interface
00857   // is for IP, so be careful to count properly.  When setting the
00858   // INET_Addr, note that the 3rd arg (0) says to leave the byte order
00859   // (already in net byte order from the interface structure) as is.
00860   count = 0;
00861 
00862   for (p_if = ifap;
00863        p_if != 0;
00864        p_if = p_if->ifa_next)
00865     {
00866       if (p_if->ifa_addr &&
00867           p_if->ifa_addr->sa_family == AF_INET)
00868         {
00869           struct sockaddr_in *addr =
00870             reinterpret_cast<sockaddr_in *> (p_if->ifa_addr);
00871 
00872           // Sometimes the kernel returns 0.0.0.0 as the interface
00873           // address, skip those...
00874           if (addr->sin_addr.s_addr != INADDR_ANY)
00875             {
00876               addrs[count].set ((u_short) 0,
00877                                 addr->sin_addr.s_addr,
00878                                 0);
00879               ++count;
00880             }
00881         }
00882 # if defined (ACE_HAS_IPV6)
00883       else if (p_if->ifa_addr &&
00884                p_if->ifa_addr->sa_family == AF_INET6)
00885         {
00886           struct sockaddr_in6 *addr =
00887             reinterpret_cast<sockaddr_in6 *> (p_if->ifa_addr);
00888 
00889           // Skip the ANY address
00890           if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr))
00891             {
00892               addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr),
00893                                sizeof(sockaddr_in6));
00894               ++count;
00895             }
00896         }
00897 # endif /* ACE_HAS_IPV6 */
00898     }
00899 
00900   ::freeifaddrs (ifap);
00901 
00902   return 0;
00903 }
00904 #elif defined (__hpux)
00905 static int
00906 get_ip_interfaces_hpux (size_t &count,
00907                         ACE_INET_Addr *&addrs)
00908 {
00909   size_t num_ifs = 0;
00910   size_t num_ifs_found = 0;
00911 
00912   // Call specific routine as necessary.
00913   ACE_HANDLE handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
00914   ACE_HANDLE handle_ipv6 = ACE_INVALID_HANDLE;
00915 
00916   if (handle == ACE_INVALID_HANDLE)
00917     ACE_ERROR_RETURN ((LM_ERROR,
00918                        ACE_TEXT ("%p\n"),
00919                        ACE_TEXT ("ACE::get_ip_interfaces:open")),
00920                       -1);
00921 
00922   int result = 0;
00923   int tmp_how_many = 0;
00924 
00925   result = ACE_OS::ioctl (handle,
00926                           SIOCGIFNUM,
00927                           (caddr_t) &tmp_how_many);
00928   if (result != -1)
00929     num_ifs = (size_t)tmp_how_many;
00930 
00931 # if defined (ACE_HAS_IPV6)
00932   tmp_how_many = 0;
00933   handle_ipv6 = ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0);
00934   result = ACE_OS::ioctl (handle_ipv6,
00935                           SIOCGLIFNUM,
00936                           (caddr_t) &tmp_how_many);
00937   if (result != -1)
00938     num_ifs += (size_t)tmp_how_many;
00939 # endif
00940 
00941   if (num_ifs == 0)
00942     {
00943       ACE_OS::close (handle);
00944       ACE_OS::close (handle_ipv6);
00945       return -1;
00946     }
00947 
00948   // ioctl likes to have an extra IFREQ structure to mark the end of
00949   // what it returned, so increase the num_ifs by one.
00950   ++num_ifs;
00951 
00952   //HPUX requires two passes, First for IPv4, then for IPv6
00953 
00954   struct ifreq *ifs = 0;
00955   ACE_NEW_RETURN (ifs,
00956                   struct ifreq[num_ifs],
00957                   -1);
00958   ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct ifreq));
00959 
00960   ACE_Auto_Array_Ptr<struct ifreq> p_ifs (ifs);
00961 
00962   if (p_ifs.get() == 0)
00963     {
00964       ACE_OS::close (handle);
00965       ACE_OS::close (handle_ipv6);
00966       errno = ENOMEM;
00967       return -1;
00968     }
00969 
00970   struct ifconf ifcfg;
00971   ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
00972 
00973   ifcfg.ifc_req = p_ifs.get ();
00974   ifcfg.ifc_len = num_ifs * sizeof (struct ifreq);
00975 
00976   if (ACE_OS::ioctl (handle,
00977                      SIOCGIFCONF,
00978                      (char *) &ifcfg) == -1)
00979     {
00980       ACE_OS::close (handle);
00981       ACE_ERROR_RETURN ((LM_ERROR,
00982                          ACE_TEXT ("%p\n"),
00983                          ACE_TEXT ("ACE::get_ip_interfaces:")
00984                          ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
00985                         -1);
00986     }
00987 
00988   ACE_OS::close (handle);
00989 
00990   // Now create and initialize output array.
00991 
00992   ACE_NEW_RETURN (addrs,
00993                   ACE_INET_Addr[num_ifs],
00994                   -1); // caller must free
00995 
00996   struct ifreq *pcur = p_ifs.get ();
00997   num_ifs_found = ifcfg.ifc_len / sizeof (struct ifreq); // get the number of returned ifs
00998 
00999   for (size_t i = 0;
01000        i < num_ifs_found;
01001        i++)
01002     {
01003         struct sockaddr_in *addr =
01004             reinterpret_cast<sockaddr_in *> (&pcur->ifr_addr);
01005         if (addr->sin_addr.s_addr != 0)
01006         {
01007             addrs[count].set ((u_short) 0,
01008                               addr->sin_addr.s_addr,
01009                               0);
01010             ++count;
01011         }
01012         ++pcur;
01013     }
01014 
01015 # if defined (ACE_HAS_IPV6)
01016 
01017   if (handle_ipv6 != ACE_INVALID_HANDLE)
01018     {
01019       struct if_laddrreq *lifs = 0;
01020       ACE_NEW_RETURN (lifs,
01021                       struct if_laddrreq[num_ifs],
01022                       -1);
01023       ACE_OS::memset (lifs, 0, num_ifs * sizeof (struct if_laddrreq));
01024 
01025       ACE_Auto_Array_Ptr<struct if_laddrreq> p_lifs (lifs);
01026 
01027       if (p_lifs.get() == 0)
01028         {
01029           ACE_OS::close (handle);
01030           ACE_OS::close (handle_ipv6);
01031           errno = ENOMEM;
01032           return -1;
01033         }
01034 
01035       struct if_laddrconf lifcfg;
01036       ACE_OS::memset (&lifcfg, 0, sizeof (struct if_laddrconf));
01037 
01038       lifcfg.iflc_req = p_lifs.get ();
01039       lifcfg.iflc_len = num_ifs * sizeof (struct if_laddrreq);
01040 
01041       if (ACE_OS::ioctl (handle_ipv6,
01042                          SIOCGLIFCONF,
01043                          (char *) &lifcfg) == -1)
01044         {
01045           ACE_OS::close (handle);
01046           ACE_ERROR_RETURN ((LM_ERROR,
01047                              ACE_TEXT ("%p\n"),
01048                              ACE_TEXT ("ACE::get_ip_interfaces:")
01049                              ACE_TEXT ("ioctl - SIOCGLIFCONF failed")),
01050                             -1);
01051         }
01052 
01053       ACE_OS::close (handle_ipv6);
01054 
01055       struct if_laddrreq *plcur = p_lifs.get ();
01056       num_ifs_found = lifcfg.iflc_len / sizeof (struct if_laddrreq);
01057 
01058       for (size_t i = 0;
01059            i < num_ifs_found;
01060            i++)
01061         {
01062             struct sockaddr_in *addr =
01063                 reinterpret_cast<sockaddr_in *> (&plcur->iflr_addr);
01064             if (!IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
01065             {
01066                 addrs[count].set(addr, sizeof(struct sockaddr_in6));
01067                 ++count;
01068             }
01069             ++plcur;
01070         }
01071     }
01072 # endif /* ACE_HAS_IPV6 */
01073   return 0;
01074 }
01075 #elif defined (_AIX)
01076 static int
01077 get_ip_interfaces_aix (size_t &count,
01078                        ACE_INET_Addr *&addrs)
01079 {
01080   ACE_HANDLE handle = ACE::get_handle();
01081   size_t num_ifs = 0;
01082   struct ifconf ifc;
01083 
01084   if (handle == ACE_INVALID_HANDLE)
01085     ACE_ERROR_RETURN ((LM_ERROR,
01086                        ACE_TEXT ("%p\n"),
01087                        ACE_TEXT ("ACE::get_ip_interfaces_aix:")),
01088                       -1);
01089 
01090   if (ACE_OS::ioctl (handle,
01091                      SIOCGSIZIFCONF,
01092                      (caddr_t)&ifc.ifc_len) == -1)
01093   {
01094       ACE_OS::close (handle);
01095       ACE_ERROR_RETURN((LM_ERROR,
01096                         ACE_TEXT ("%p\n"),
01097                         ACE_TEXT ("get ifconf size")),
01098                        -1);
01099   }
01100 
01101   ACE_NEW_RETURN (ifc.ifc_buf,char [ifc.ifc_len], -1);
01102 
01103   ACE_Auto_Array_Ptr<char> safe_buf (ifc.ifc_buf);
01104   ACE_OS::memset (safe_buf.get(), 0, ifc.ifc_len);
01105 
01106   if (ACE_OS::ioctl(handle, SIOCGIFCONF, (caddr_t)&ifc) == -1)
01107   {
01108       ACE_OS::close (handle);
01109       ACE_ERROR_RETURN((LM_ERROR,
01110                         ACE_TEXT ("%p\n"),
01111                         ACE_TEXT ("get ifconf")),
01112                        -1);
01113   }
01114 
01115   ACE_OS::close (handle);
01116 
01117   char *buf_start = safe_buf.get();
01118   char *buf_end = buf_start + ifc.ifc_len;
01119 
01120   num_ifs = 0;
01121   for (char *ptr = buf_start; ptr < buf_end; )
01122     {
01123       struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
01124       ptr += IFNAMSIZ;
01125       ptr += req->ifr_addr.sa_len;
01126      if (req->ifr_addr.sa_family == AF_INET
01127 # if defined (ACE_HAS_IPV6)
01128         || req->ifr_addr.sa_family == AF_INET6
01129 # endif
01130         )
01131        ++num_ifs;
01132     }
01133   ACE_NEW_RETURN (addrs,ACE_INET_Addr[num_ifs], -1);
01134 
01135   for (char * ptr = buf_start;  ptr < buf_end; )
01136   {
01137     struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
01138     // skip the interface name
01139     ptr += IFNAMSIZ;
01140     if (req->ifr_addr.sa_family == AF_INET
01141 # if defined (ACE_HAS_IPV6)
01142         || req->ifr_addr.sa_family == AF_INET6
01143 # endif
01144         )
01145       {
01146         sockaddr_in *addr = (sockaddr_in*)&req->ifr_addr;
01147         addrs[count++].set(addr, addr->sin_len);
01148       }
01149     ptr += req->ifr_addr.sa_len;
01150   }
01151 
01152   return 0;
01153 }
01154 
01155 #elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
01156 int
01157 get_ip_interfaces_vxworks_lt600 (size_t &count,
01158                                  ACE_INET_Addr *&addrs)
01159 {
01160   count = 0;
01161   // Loop through each address structure
01162 
01163 # if defined (ACE_HAS_IPV6) && defined (TAILQ_ENTRY)
01164 #   define ia_next ia_link.tqe_next
01165 # endif /* TAILQ_ENTRY */
01166 
01167   for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
01168     {
01169       ++count;
01170     }
01171 
01172   // Now create and initialize output array.
01173   ACE_NEW_RETURN (addrs,
01174                   ACE_INET_Addr[count],
01175                   -1); // caller must free
01176   count = 0;
01177   for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
01178     {
01179       struct ifnet* ifp = ia->ia_ifa.ifa_ifp;
01180       if (ifp != 0)
01181         {
01182           // Get the current interface name
01183           char interface[64];
01184           ACE_OS::sprintf(interface, "%s%d", ifp->if_name, ifp->if_unit);
01185 
01186           // Get the address for the current interface
01187           char address [INET_ADDR_LEN];
01188           STATUS status = ifAddrGet(interface, address);
01189 
01190           if (status == OK)
01191             {
01192               // Concatenate a ':' at the end. This is because in
01193               // ACE_INET_Addr::string_to_addr, the ip_address is
01194               // obtained using ':' as the delimiter. Since, using
01195               // ifAddrGet(), we just get the IP address, I am adding
01196               // a ":" to get with the general case.
01197               ACE_OS::strcat (address, ":");
01198               addrs[count].set (address);
01199             }
01200           else
01201             {
01202               ACE_ERROR_RETURN ((LM_ERROR,
01203                                  ACE_TEXT ("ACE::get_ip_interface failed\n")
01204                                  ACE_TEXT ("Couldnt get the IP Address\n")),
01205                                  -1);
01206             }
01207           ++count;
01208         }
01209     }
01210   return 0;
01211 }
01212 #endif // ACE_WIN32 || ACE_HAS_GETIFADDRS || __hpux || _AIX || ACE_VXWORKS < 0x600
01213 
01214 
01215 // return an array of all configured IP interfaces on this host, count
01216 // rc = 0 on success (count == number of interfaces else -1 caller is
01217 // responsible for calling delete [] on parray
01218 
01219 int
01220 ACE::get_ip_interfaces (size_t &count,
01221                         ACE_INET_Addr *&addrs)
01222 {
01223   ACE_TRACE ("ACE::get_ip_interfaces");
01224 
01225   count = 0;
01226   addrs = 0;
01227 
01228 #if defined (ACE_WIN32)
01229   return get_ip_interfaces_win32 (count, addrs);
01230 #elif defined (ACE_HAS_GETIFADDRS)
01231   return get_ip_interfaces_getifaddrs (count, addrs);
01232 #elif defined (__hpux)
01233   return get_ip_interfaces_hpux (count, addrs);
01234 #elif defined (_AIX)
01235   return get_ip_interfaces_aix (count, addrs);
01236 #elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
01237   return get_ip_interfaces_vxworks_lt600 (count, addrs);
01238 #elif (defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (ACE_OPENVMS) || (defined (ACE_VXWORKS) && (ACE_VXWORKS == 0x650)) || defined (ACE_HAS_RTEMS)) && !defined (ACE_LACKS_NETWORKING)
01239   // COMMON (SVR4 and BSD) UNIX CODE
01240 
01241   // Call specific routine as necessary.
01242   ACE_HANDLE handle = ACE::get_handle();
01243 
01244   if (handle == ACE_INVALID_HANDLE)
01245     ACE_ERROR_RETURN ((LM_ERROR,
01246                        ACE_TEXT ("%p\n"),
01247                        ACE_TEXT ("ACE::get_ip_interfaces:open")),
01248                       -1);
01249 
01250   size_t num_ifs, num_ifs_found;
01251 
01252   if (ACE::count_interfaces (handle, num_ifs))
01253     {
01254       ACE_OS::close (handle);
01255       return -1;
01256     }
01257 
01258   // ioctl likes to have an extra ifreq structure to mark the end of
01259   // what it returned, so increase the num_ifs by one.
01260   ++num_ifs;
01261 
01262   struct IFREQ *ifs = 0;
01263   ACE_NEW_RETURN (ifs,
01264                   struct IFREQ[num_ifs],
01265                   -1);
01266   ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct IFREQ));
01267 
01268   ACE_Auto_Array_Ptr<struct IFREQ> p_ifs (ifs);
01269 
01270   if (p_ifs.get() == 0)
01271     {
01272       ACE_OS::close (handle);
01273       errno = ENOMEM;
01274       return -1;
01275     }
01276 
01277   struct IFCONF ifcfg;
01278   ACE_OS::memset (&ifcfg, 0, sizeof (struct IFCONF));
01279 
01280 # ifdef SETFAMILY
01281   ifcfg.IFC_FAMILY = AF_UNSPEC;  // request all families be returned
01282   ifcfg.IFC_FLAGS = 0;
01283 # endif
01284 
01285   ifcfg.IFC_REQ = p_ifs.get ();
01286   ifcfg.IFC_LEN = num_ifs * sizeof (struct IFREQ);
01287 
01288   if (ACE_OS::ioctl (handle,
01289                      SIOCGIFCONF_CMD,
01290                      (caddr_t) &ifcfg) == -1)
01291     {
01292       ACE_OS::close (handle);
01293       ACE_ERROR_RETURN ((LM_ERROR,
01294                          ACE_TEXT ("%p\n"),
01295                          ACE_TEXT ("ACE::get_ip_interfaces:")
01296                          ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
01297                         -1);
01298     }
01299 
01300   ACE_OS::close (handle);
01301 
01302   // Now create and initialize output array.
01303 
01304   ACE_NEW_RETURN (addrs,
01305                   ACE_INET_Addr[num_ifs],
01306                   -1); // caller must free
01307 
01308   struct IFREQ *pcur = p_ifs.get ();
01309   num_ifs_found = ifcfg.IFC_LEN / sizeof (struct IFREQ); // get the number of returned ifs
01310 
01311   // Pull the address out of each INET interface.  Not every interface
01312   // is for IP, so be careful to count properly.  When setting the
01313   // INET_Addr, note that the 3rd arg (0) says to leave the byte order
01314   // (already in net byte order from the interface structure) as is.
01315   count = 0;
01316 
01317   for (size_t i = 0;
01318        i < num_ifs_found;
01319        i++)
01320     {
01321       if (pcur->IFR_ADDR.SA_FAMILY == AF_INET
01322 #  if defined (ACE_HAS_IPV6)
01323           || pcur->IFR_ADDR.SA_FAMILY == AF_INET6
01324 #  endif
01325           )
01326 
01327         {
01328 # if !defined(_UNICOS)
01329           struct sockaddr_in *addr =
01330             reinterpret_cast<sockaddr_in *> (&pcur->IFR_ADDR);
01331 
01332           // Sometimes the kernel returns 0.0.0.0 as an IPv4 interface
01333           // address; skip those...
01334           if (addr->sin_addr.s_addr != 0
01335 #  if defined (ACE_HAS_IPV6)
01336               || (addr->sin_family == AF_INET6 &&
01337                   !IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
01338 #  endif
01339               )
01340             {
01341               int addrlen = static_cast<int> (sizeof (struct sockaddr_in));
01342 #  if defined (ACE_HAS_IPV6)
01343               if (addr->sin_family == AF_INET6)
01344                 addrlen = static_cast<int> (sizeof (struct sockaddr_in6));
01345 #  endif
01346               addrs[count].set (addr, addrlen);
01347               ++count;
01348             }
01349 # else /* ! _UNICOS */
01350           // need to explicitly copy on the Cray, since the bitfields kinda
01351           // screw things up here
01352           struct sockaddr_in inAddr;
01353 
01354           inAddr.sin_len = pcur->IFR_ADDR.sa_len;
01355           inAddr.sin_family = pcur->IFR_ADDR.sa_family;
01356           memcpy((void *)&(inAddr.sin_addr),
01357                  (const void *)&(pcur->IFR_ADDR.sa_data[8]),
01358                  sizeof(struct in_addr));
01359 
01360           if (inAddr.sin_addr.s_addr != 0)
01361             {
01362               addrs[count].set(&inAddr, sizeof(struct sockaddr_in));
01363               ++count;
01364             }
01365 # endif /* ! _UNICOS */
01366         }
01367 
01368 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS)
01369       ++pcur;
01370 #else
01371       if (pcur->ifr_addr.sa_len <= sizeof (struct sockaddr))
01372         {
01373            ++pcur;
01374         }
01375       else
01376         {
01377            pcur = (struct ifreq *)
01378                (pcur->ifr_addr.sa_len + (caddr_t) &pcur->ifr_addr);
01379         }
01380 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
01381     }
01382 
01383 # if defined (ACE_HAS_IPV6)
01384   // Retrieve IPv6 local interfaces by scanning /proc/net/if_inet6 if
01385   // it exists.  If we cannot open it then ignore possible IPv6
01386   // interfaces, we did our best;-)
01387   FILE* fp;
01388   char addr_p[8][5];
01389   char s_ipaddr[64];
01390   int scopeid;
01391   struct addrinfo hints, *res0;
01392   int error;
01393 
01394   ACE_OS::memset (&hints, 0, sizeof (hints));
01395   hints.ai_flags = AI_NUMERICHOST;
01396   hints.ai_family = AF_INET6;
01397 
01398   if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
01399     {
01400       while (fscanf (fp,
01401                      "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*8s\n",
01402                      addr_p[0], addr_p[1], addr_p[2], addr_p[3],
01403                      addr_p[4], addr_p[5], addr_p[6], addr_p[7], &scopeid) != EOF)
01404         {
01405           // Format the address intoa proper IPv6 decimal address specification and
01406           // resolve the resulting text using getaddrinfo().
01407 
01408           const char* ip_fmt = "%s:%s:%s:%s:%s:%s:%s:%s%%%d";
01409           ACE_OS::sprintf (s_ipaddr,
01410                            ip_fmt,
01411                            addr_p[0], addr_p[1], addr_p[2], addr_p[3],
01412                            addr_p[4], addr_p[5], addr_p[6], addr_p[7], scopeid);
01413 
01414           error = getaddrinfo (s_ipaddr, 0, &hints, &res0);
01415           if (error)
01416             continue;
01417 
01418           if (res0->ai_family == AF_INET6 &&
01419                 !IN6_IS_ADDR_UNSPECIFIED (&reinterpret_cast<sockaddr_in6 *> (res0->ai_addr)->sin6_addr))
01420             {
01421               addrs[count].set(reinterpret_cast<sockaddr_in *> (res0->ai_addr), res0->ai_addrlen);
01422               ++count;
01423             }
01424           freeaddrinfo (res0);
01425 
01426         }
01427       ACE_OS::fclose (fp);
01428     }
01429 # endif /* ACE_HAS_IPV6 */
01430 
01431   return 0;
01432 #else
01433   ACE_UNUSED_ARG (count);
01434   ACE_UNUSED_ARG (addrs);
01435   ACE_NOTSUP_RETURN (-1);                      // no implementation
01436 #endif /* ACE_WIN32 */
01437 }
01438 
01439 // Helper routine for get_ip_interfaces, differs by UNIX platform so
01440 // put into own subroutine.  perform some ioctls to retrieve ifconf
01441 // list of ifreq structs.
01442 
01443 int
01444 ACE::count_interfaces (ACE_HANDLE handle,
01445                        size_t &how_many)
01446 {
01447 #if defined (ACE_WIN32) || defined (ACE_HAS_GETIFADDRS) || defined (__hpux) || defined (_AIX) || (defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600))
01448   // none of these platforms make use of count_interfaces
01449   ACE_UNUSED_ARG (handle);
01450   ACE_UNUSED_ARG (how_many);
01451   ACE_NOTSUP_RETURN (-1); // no implementation
01452 
01453 #elif defined (SIOCGIFNUM)
01454 # if defined (SIOCGLIFNUM)
01455   int cmd = SIOCGLIFNUM;
01456   struct lifnum if_num = {AF_UNSPEC,0,0};
01457 # else
01458   int cmd = SIOCGIFNUM;
01459   int if_num = 0;
01460 # endif /* SIOCGLIFNUM */
01461   if (ACE_OS::ioctl (handle, cmd, (caddr_t)&if_num) == -1)
01462     ACE_ERROR_RETURN ((LM_ERROR,
01463                        ACE_TEXT ("%p\n"),
01464                        ACE_TEXT ("ACE::count_interfaces:")
01465                        ACE_TEXT ("ioctl - SIOCGLIFNUM failed")),
01466                       -1);
01467 # if defined (SIOCGLIFNUM)
01468   how_many = if_num.lifn_count;
01469 # else
01470   how_many = if_num;
01471 # endif /* SIOCGLIFNUM */
01472 return 0;
01473 
01474 #elif (defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS)) && !defined (ACE_LACKS_NETWORKING)
01475   // Note: DEC CXX doesn't define "unix".  BSD compatible OS: HP UX,
01476   // AIX, SunOS 4.x perform some ioctls to retrieve ifconf list of
01477   // ifreq structs no SIOCGIFNUM on SunOS 4.x, so use guess and scan
01478   // algorithm
01479 
01480   // Probably hard to put this many ifs in a unix box..
01481   const int MAX_IF = 50;
01482 
01483   // HACK - set to an unreasonable number
01484   int num_ifs = MAX_IF;
01485 
01486   struct ifconf ifcfg;
01487   size_t ifreq_size = num_ifs * sizeof (struct ifreq);
01488   struct ifreq *p_ifs =
01489     (struct ifreq *) ACE_OS::malloc (ifreq_size);
01490 
01491   if (!p_ifs)
01492     {
01493       errno = ENOMEM;
01494       return -1;
01495     }
01496 
01497   ACE_OS::memset (p_ifs, 0, ifreq_size);
01498   ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
01499 
01500   ifcfg.ifc_req = p_ifs;
01501   ifcfg.ifc_len = ifreq_size;
01502 
01503   if (ACE_OS::ioctl (handle,
01504                      SIOCGIFCONF_CMD,
01505                      (caddr_t) &ifcfg) == -1)
01506     {
01507       ACE_OS::free (ifcfg.ifc_req);
01508       ACE_ERROR_RETURN ((LM_ERROR,
01509                          ACE_TEXT ("%p\n"),
01510                          ACE_TEXT ("ACE::count_interfaces:")
01511                          ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
01512                         -1);
01513     }
01514 
01515   int if_count = 0, i;
01516 
01517   // get if address out of ifreq buffers.  ioctl puts a blank-named
01518   // interface to mark the end of the returned interfaces.
01519   for (i = 0;
01520        i < num_ifs;
01521        i++)
01522     {
01523       /* In OpenBSD, the length of the list is returned. */
01524       ifcfg.ifc_len -= sizeof (struct ifreq);
01525       if (ifcfg.ifc_len < 0)
01526         break;
01527 
01528       ++if_count;
01529 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS)
01530       ++p_ifs;
01531 #else
01532      if (p_ifs->ifr_addr.sa_len <= sizeof (struct sockaddr))
01533        {
01534           ++p_ifs;
01535        }
01536        else
01537        {
01538           p_ifs = (struct ifreq *)
01539               (p_ifs->ifr_addr.sa_len + (caddr_t) &p_ifs->ifr_addr);
01540        }
01541 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
01542     }
01543 
01544   ACE_OS::free (ifcfg.ifc_req);
01545 
01546 # if defined (ACE_HAS_IPV6)
01547   FILE* fp = 0;
01548 
01549   if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
01550     {
01551       // Scan the lines according to the expected format but don't really read any input
01552       while (fscanf (fp, "%*32s %*02x %*02x %*02x %*02x %*8s\n") != EOF)
01553         {
01554           ++if_count;
01555         }
01556       ACE_OS::fclose (fp);
01557     }
01558 # endif /* ACE_HAS_IPV6 */
01559 
01560   how_many = if_count;
01561   return 0;
01562 #else
01563   ACE_UNUSED_ARG (handle);
01564   ACE_UNUSED_ARG (how_many);
01565   ACE_NOTSUP_RETURN (-1); // no implementation
01566 #endif /* sparc && SIOCGIFNUM */
01567 }
01568 
01569 // Routine to return a handle from which ioctl() requests can be made.
01570 
01571 ACE_HANDLE
01572 ACE::get_handle (void)
01573 {
01574   // Solaris 2.x
01575   ACE_HANDLE handle = ACE_INVALID_HANDLE;
01576 #if defined (sparc)
01577   handle = ACE_OS::open ("/dev/udp", O_RDONLY);
01578 #elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (__hpux) || (defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS)
01579   // Note: DEC CXX doesn't define "unix" BSD compatible OS: HP UX,
01580   // AIX, SunOS 4.x
01581 
01582   handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
01583 #endif /* sparc */
01584   return handle;
01585 }
01586 
01587 
01588 #if defined (ACE_HAS_IPV6)
01589 static int
01590 ip_check (int &ipvn_enabled, int pf)
01591 {
01592   // We only get to this point if ipvn_enabled was -1 in the caller.
01593   // Perform Double-Checked Locking Optimization.
01594   ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
01595                             *ACE_Static_Object_Lock::instance (), 0));
01596 
01597   if (ipvn_enabled == -1)
01598     {
01599       // Determine if the kernel has IPv6 support by attempting to
01600       // create a PF_INET socket and see if it fails.
01601       ACE_HANDLE const s = ACE_OS::socket (pf, SOCK_DGRAM, 0);
01602       if (s == ACE_INVALID_HANDLE)
01603         {
01604           ipvn_enabled = 0;
01605         }
01606       else
01607         {
01608           ipvn_enabled = 1;
01609           ACE_OS::closesocket (s);
01610         }
01611     }
01612   return ipvn_enabled;
01613 }
01614 #endif /* ACE_HAS_IPV6 */
01615 
01616 bool
01617 ACE::ipv4_enabled (void)
01618 {
01619 #if defined (ACE_HAS_IPV6)
01620   return static_cast<bool> (ace_ipv4_enabled == -1 ?
01621                             ::ip_check (ace_ipv4_enabled, PF_INET) :
01622                             ace_ipv4_enabled);
01623 #else
01624  // Assume it's always enabled since ACE requires some version of
01625  // TCP/IP to exist.
01626   return true;
01627 #endif  /* ACE_HAS_IPV6*/
01628 }
01629 
01630 int
01631 ACE::ipv6_enabled (void)
01632 {
01633 #if defined (ACE_HAS_IPV6)
01634   return ace_ipv6_enabled == -1 ?
01635     ::ip_check (ace_ipv6_enabled, PF_INET6) :
01636     ace_ipv6_enabled;
01637 #else /* ACE_HAS_IPV6 */
01638   return 0;
01639 #endif /* !ACE_HAS_IPV6 */
01640 }
01641 
01642 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 12:05:38 2008 for ACE by doxygen 1.3.6