Sock_Connect.cpp

Go to the documentation of this file.
00001 // Sock_Connect.cpp,v 1.66 2006/06/01 09:15:42 jwillemsen Exp
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 #endif /* ACE_HAS_IPV6 */
00027 
00028 # if defined (ACE_HAS_GETIFADDRS)
00029 #   if defined (ACE_VXWORKS)
00030 #     include /**/ <net/ifaddrs.h>
00031 #   else
00032 #     include /**/ <ifaddrs.h>
00033 #   endif
00034 # endif /* ACE_HAS_GETIFADDRS */
00035 
00036 #if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
00037 #include /**/ <inetLib.h>
00038 #include /**/ <netinet/in_var.h>
00039 extern "C" {
00040   extern struct in_ifaddr* in_ifaddr;
00041 }
00042 #include "ace/OS_NS_stdio.h"
00043 #endif /* ACE_VXWORKS < 0x600 */
00044 
00045 #if defined (ACE_HAS_WINCE)
00046 #include /**/ <Iphlpapi.h>
00047 #endif  // ACE_HAS_WINCE
00048 
00049 #if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
00050 # include "ace/OS_NS_stdio.h"
00051 #endif
00052 
00053 #if defined (ACE_HAS_IPV6)
00054 #  if defined (ACE_HAS_THREADS)
00055 #    include "ace/Object_Manager.h"
00056 #  endif /* ACE_HAS_THREADS */
00057 
00058 namespace
00059 {
00060   // private:
00061   //  Used internally so not exported.
00062 
00063   /// Does this box have ipv6 turned on?
00064   int ace_ipv6_enabled = -1;
00065 }
00066 #endif /* ACE_HAS_IPV6 */
00067 
00068 // This is a hack to work around a problem with Visual Age C++ 5 and 6 on AIX.
00069 // Without this, the compiler auto-instantiates the ACE_Auto_Array_Ptr for
00070 // ifreq (contained in this module) but only adds the #include for <net/if.h>
00071 // and not the one for <sys/socket.h> which is also needed.  Although we
00072 // don't need the template defined here, it makes the compiler pull in
00073 // <sys/socket.h> and the build runs clean.
00074 #if defined (AIX) && defined (__IBMCPP__) && (__IBMCPP__ >= 500) && (__IBMCPP__ < 700)
00075 static ACE_Auto_Array_Ptr<sockaddr> force_compiler_to_include_socket_h;
00076 #endif /* AIX && __IBMCPP__ >= 500 */
00077 
00078 
00079 ACE_RCSID (ace,
00080            Sock_Connect,
00081            "Sock_Connect.cpp,v 1.66 2006/06/01 09:15:42 jwillemsen Exp")
00082 
00083 
00084 #if defined (ACE_WIN32) && \
00085     (!defined (ACE_HAS_WINSOCK2) \
00086      || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 0)))
00087 
00088 static int
00089 get_reg_subkeys (const ACE_TCHAR *key,
00090                  ACE_TCHAR *buffer,
00091                  DWORD &buf_len)
00092 {
00093   HKEY hk;
00094   LONG rc = ACE_TEXT_RegOpenKeyEx (HKEY_LOCAL_MACHINE,
00095                                    key,
00096                                    0,
00097                                    KEY_READ,
00098                                    &hk);
00099 
00100   if (rc != ERROR_SUCCESS)
00101     return -1;
00102 
00103   ACE_TCHAR subkeyname[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
00104   DWORD subkeyname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN;
00105   FILETIME update_dummy;
00106 
00107   DWORD total = 0;
00108 
00109   for (int i = 0;
00110        (rc = ACE_TEXT_RegEnumKeyEx (hk, i,
00111                                     subkeyname,
00112                                     &subkeyname_len,
00113                                     0, 0, 0,
00114                                     &update_dummy)) != ERROR_NO_MORE_ITEMS;
00115         ++i)
00116     {
00117       if (subkeyname_len < buf_len - total)
00118         {
00119           ACE_OS::strcpy(buffer + total, subkeyname);
00120           total += subkeyname_len + 1;
00121           // Reset: was changed by RegEnumKeyEx call.
00122           subkeyname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
00123         }
00124       else
00125         return -1;
00126     }
00127 
00128   buf_len = total;
00129 
00130   ::RegCloseKey (hk);
00131   return 0;
00132 }
00133 
00134 // Return value in buffer for a key/name pair from the Windows
00135 // Registry up to buf_len size.
00136 // If all_subkeys == 1, look for name under all subkeys of key.
00137 
00138 static int
00139 get_reg_value (const ACE_TCHAR *key,
00140                const ACE_TCHAR *name,
00141                ACE_TCHAR *buffer,
00142                DWORD &buf_len,
00143                int all_subkeys = 0)
00144 {
00145   HKEY hk;
00146   DWORD buf_type;
00147   LONG rc = ACE_TEXT_RegOpenKeyEx (HKEY_LOCAL_MACHINE,
00148                                    key,
00149                                    0,
00150                                    KEY_READ,
00151                                    &hk);
00152 
00153   if (rc != ERROR_SUCCESS)
00154     // print_error_string(ACE_LIB_TEXT ("RegOpenKeyEx"), rc);
00155     return -1;
00156 
00157   if (all_subkeys)
00158     {
00159       ACE_TCHAR ifname[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
00160       DWORD ifname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
00161       FILETIME update_dummy;
00162 
00163       DWORD total = 0;
00164       DWORD size = buf_len;
00165 
00166       for (int i = 0;
00167            (rc = ACE_TEXT_RegEnumKeyEx (hk, i, ifname, &ifname_len,
00168                                         0, 0, 0,
00169                                         &update_dummy)) != ERROR_NO_MORE_ITEMS;
00170            ++i)
00171         {
00172           HKEY ifkey;
00173           if (rc != ERROR_SUCCESS
00174               || ACE_TEXT_RegOpenKeyEx (hk, ifname, 0,
00175                                         KEY_READ, &ifkey) != ERROR_SUCCESS)
00176             continue;
00177 
00178           if (ACE_TEXT_RegQueryValueEx (ifkey, name, 0, 0,
00179                                         (u_char*) (buffer + total),
00180                                         &size) != ERROR_SUCCESS)
00181             {
00182               RegCloseKey(ifkey);
00183               continue;
00184             }
00185           else
00186             {
00187               total += size;
00188               size = buf_len - total;
00189             }
00190           // Needs to be reset.
00191           ifname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
00192         }
00193 
00194       if (total == 0)
00195         {
00196           ::RegCloseKey (hk);
00197           return -2;
00198         }
00199       else
00200         {
00201           buf_len = total;
00202         }
00203     }
00204   else
00205     {
00206 
00207       rc = ACE_TEXT_RegQueryValueEx (hk,
00208                                      name,
00209                                      0,
00210                                      &buf_type,
00211                                      (u_char *) buffer,
00212                                      &buf_len);
00213       if (rc != ERROR_SUCCESS)
00214         {
00215           // print_error_string(ACE_LIB_TEXT ("RegEnumKeyEx"), rc);
00216           RegCloseKey (hk);
00217           return -2;
00218         }
00219     }
00220 
00221   ::RegCloseKey (hk);
00222   return 0;
00223 }
00224 
00225 enum ACE_WINDOWS_VERSION {
00226   ACE_WINDOWS_IS_UNKNOWN,
00227   ACE_WINDOWS_IS_WIN95,
00228   ACE_WINDOWS_IS_WIN98,
00229   ACE_WINDOWS_IS_WINME,
00230   ACE_WINDOWS_IS_WINNT,
00231   ACE_WINDOWS_IS_WIN2K,
00232   ACE_WINDOWS_IS_WINCE
00233 };
00234 
00235 static ACE_WINDOWS_VERSION
00236 get_windows_version()
00237 {
00238   OSVERSIONINFO vinfo;
00239   vinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00240   if (::GetVersionEx(&vinfo) == 0)
00241     {
00242       return ACE_WINDOWS_IS_UNKNOWN;
00243     }
00244 
00245   switch (vinfo.dwPlatformId)
00246     {
00247     case VER_PLATFORM_WIN32_NT:
00248       if (vinfo.dwMajorVersion <= 4)
00249         return ACE_WINDOWS_IS_WINNT;
00250       else
00251         return ACE_WINDOWS_IS_WIN2K;
00252     case VER_PLATFORM_WIN32_WINDOWS:
00253       if (vinfo.dwMajorVersion == 4)
00254         {
00255           if (vinfo.dwMinorVersion == 0)
00256             return ACE_WINDOWS_IS_WIN95;
00257           else if (vinfo.dwMinorVersion == 10)
00258             return ACE_WINDOWS_IS_WIN98;
00259           else if (vinfo.dwMinorVersion == 90)
00260             return ACE_WINDOWS_IS_WINME;
00261         }
00262 #if defined (VER_PLATFORM_WIN32_CE)
00263     case VER_PLATFORM_WIN32_CE:
00264         if (vinfo.dwMajorVersion >= 3) {
00265             return ACE_WINDOWS_IS_WINCE;
00266         }
00267         else {
00268             return ACE_WINDOWS_IS_UNKNOWN;
00269         }
00270 #endif /* VER_PLATFORM_WIN32_CE */
00271       // If no match we fall throu.
00272     default:
00273       return ACE_WINDOWS_IS_UNKNOWN;
00274     }
00275 }
00276 
00277 #endif //(ACE_WIN32) && !(ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 0)
00278 
00279 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00280 
00281 // Bind socket to an unused port.
00282 
00283 int
00284 ACE::bind_port (ACE_HANDLE handle, ACE_UINT32 ip_addr, int address_family)
00285 {
00286   ACE_TRACE ("ACE::bind_port");
00287 
00288   ACE_INET_Addr addr;
00289 
00290 #if defined (ACE_HAS_IPV6)
00291   if (address_family != PF_INET6)
00292     // What do we do if it is PF_"INET6?  Since it's 4 bytes, it must be an
00293     // IPV4 address. Is there a difference?  Why is this test done? dhinton
00294 #else /* ACE_HAS_IPV6 */
00295     ACE_UNUSED_ARG (address_family);
00296 #endif /* !ACE_HAS_IPV6 */
00297     addr = ACE_INET_Addr ((u_short)0, ip_addr);
00298 #if defined (ACE_HAS_IPV6)
00299  else if (ip_addr != INADDR_ANY)
00300  // address_family == PF_INET6 and a non default IP address means to bind
00301  // to the IPv4-mapped IPv6 address
00302    addr.set ((u_short)0, ip_addr, 1, 1);
00303 #endif /* ACE_HAS_IPV6 */
00304 
00305 #if !defined (ACE_LACKS_WILDCARD_BIND)
00306   // The OS kernel should select a free port for us.
00307   return ACE_OS::bind (handle,
00308                        (sockaddr*)addr.get_addr(),
00309                        addr.get_size());
00310 #else
00311   static u_short upper_limit = ACE_MAX_DEFAULT_PORT;
00312   int round_trip = upper_limit;
00313   int lower_limit = IPPORT_RESERVED;
00314 
00315   // We have to select the port explicitly.
00316 
00317   for (;;)
00318     {
00319       addr.set((u_short)upper_limit,ip_addr);
00320 
00321       if (ACE_OS::bind (handle,
00322                         (sockaddr*)addr.get_addr()
00323                         addr.get_size()) >= 0)
00324         {
00325 #if defined (ACE_WIN32)
00326           upper_limit--;
00327 #endif /* ACE_WIN32 */
00328           return 0;
00329         }
00330       else if (errno != EADDRINUSE)
00331         return -1;
00332       else
00333         {
00334           upper_limit--;
00335 
00336           // Wrap back around when we reach the bottom.
00337           if (upper_limit <= lower_limit)
00338             upper_limit = ACE_MAX_DEFAULT_PORT;
00339 
00340           // See if we have already gone around once!
00341           if (upper_limit == round_trip)
00342             {
00343               errno = EAGAIN;
00344               return -1;
00345             }
00346         }
00347     }
00348 #endif /* ACE_HAS_WILDCARD_BIND */
00349 }
00350 
00351 int
00352 ACE::get_bcast_addr (ACE_UINT32 &bcast_addr,
00353                      const ACE_TCHAR *host_name,
00354                      ACE_UINT32 host_addr,
00355                      ACE_HANDLE handle)
00356 {
00357   ACE_TRACE ("ACE::get_bcast_addr");
00358 
00359 #if !defined(ACE_WIN32) && !defined(__INTERIX)
00360   ACE_HANDLE s = handle;
00361 
00362   if (s == ACE_INVALID_HANDLE)
00363     s = ACE_OS::socket (AF_INET, SOCK_STREAM, 0);
00364 
00365   if (s == ACE_INVALID_HANDLE)
00366     ACE_ERROR_RETURN ((LM_ERROR,
00367                        ACE_LIB_TEXT ("%p\n"),
00368                        ACE_LIB_TEXT ("ACE_OS::socket")),
00369                       -1);
00370 
00371   struct ifconf ifc;
00372   char buf[BUFSIZ];
00373 
00374   ifc.ifc_len = sizeof buf;
00375   ifc.ifc_buf = buf;
00376 
00377   // Get interface structure and initialize the addresses using UNIX
00378   // techniques
00379 #if defined (AIX)
00380   int cmd = CSIOCGIFCONF;
00381 #else
00382   int cmd = SIOCGIFCONF;
00383 #endif /* AIX */
00384   if (ACE_OS::ioctl (s, cmd, (char *) &ifc) == -1)
00385     ACE_ERROR_RETURN ((LM_ERROR,
00386                        ACE_LIB_TEXT ("%p\n"),
00387                        ACE_LIB_TEXT ("ACE::get_bcast_addr:")
00388                        ACE_LIB_TEXT ("ioctl (get interface configuration)")),
00389                       -1);
00390 
00391   struct ifreq *ifr = ifc.ifc_req;
00392 
00393   struct sockaddr_in ip_addr;
00394 
00395   // Get host ip address if necessary.
00396   if (host_name)
00397     {
00398       hostent *hp = ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name));
00399 
00400       if (hp == 0)
00401         return -1;
00402       else
00403 #if !defined(_UNICOS)
00404         ACE_OS::memcpy ((char *) &ip_addr.sin_addr.s_addr,
00405                         (char *) hp->h_addr,
00406                         hp->h_length);
00407 #else /* _UNICOS */
00408       {
00409         ACE_UINT64 haddr;  // a place to put the address
00410         char * haddrp = (char *) &haddr;  // convert to char pointer
00411         ACE_OS::memcpy(haddrp,(char *) hp->h_addr,hp->h_length);
00412         ip_addr.sin_addr.s_addr = haddr;
00413       }
00414 #endif /* ! _UNICOS */
00415     }
00416   else
00417     {
00418       ACE_OS::memset ((void *) &ip_addr, 0, sizeof ip_addr);
00419 #if !defined(_UNICOS)
00420       ACE_OS::memcpy ((void *) &ip_addr.sin_addr,
00421                       (void*) &host_addr,
00422                       sizeof ip_addr.sin_addr);
00423 #else /* _UNICOS */
00424       ip_addr.sin_addr.s_addr = host_addr;   // just copy to the bitfield
00425 #endif /* ! _UNICOS */
00426     }
00427 
00428 #if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
00429   for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
00430        n--, ifr++)
00431 #else
00432   // see mk_broadcast@SOCK_Dgram_Bcast.cpp
00433   for (int nbytes = ifc.ifc_len; nbytes >= (int) sizeof (struct ifreq) &&
00434         ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
00435           (nbytes >= (int) sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len) : 1);
00436         ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
00437           (nbytes -= sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len,
00438             ifr = (struct ifreq *)
00439               ((caddr_t) &ifr->ifr_addr + ifr->ifr_addr.sa_len)) :
00440           (nbytes -= sizeof (struct ifreq), ifr++)))
00441 #endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
00442     {
00443       struct sockaddr_in if_addr;
00444 
00445       // Compare host ip address with interface ip address.
00446       ACE_OS::memcpy (&if_addr,
00447                       &ifr->ifr_addr,
00448                       sizeof if_addr);
00449 
00450       if (ip_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
00451         continue;
00452 
00453       if (ifr->ifr_addr.sa_family != AF_INET)
00454         {
00455           ACE_ERROR ((LM_ERROR,
00456                       ACE_LIB_TEXT ("%p\n"),
00457                       ACE_LIB_TEXT ("ACE::get_bcast_addr:")
00458                       ACE_LIB_TEXT ("Not AF_INET")));
00459           continue;
00460         }
00461 
00462       struct ifreq flags = *ifr;
00463       struct ifreq if_req = *ifr;
00464 
00465       if (ACE_OS::ioctl (s, SIOCGIFFLAGS, (char *) &flags) == -1)
00466         {
00467           ACE_ERROR ((LM_ERROR,
00468                       ACE_LIB_TEXT ("%p\n"),
00469                       ACE_LIB_TEXT ("ACE::get_bcast_addr:")
00470                       ACE_LIB_TEXT (" ioctl (get interface flags)")));
00471           continue;
00472         }
00473 
00474       if (ACE_BIT_DISABLED (flags.ifr_flags, IFF_UP))
00475         {
00476           ACE_ERROR ((LM_ERROR,
00477                       ACE_LIB_TEXT ("%p\n"),
00478                       ACE_LIB_TEXT ("ACE::get_bcast_addr:")
00479                       ACE_LIB_TEXT ("Network interface is not up")));
00480           continue;
00481         }
00482 
00483       if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_LOOPBACK))
00484         continue;
00485 
00486       if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_BROADCAST))
00487         {
00488           if (ACE_OS::ioctl (s,
00489                              SIOCGIFBRDADDR,
00490                              (char *) &if_req) == -1)
00491             ACE_ERROR ((LM_ERROR,
00492                         ACE_LIB_TEXT ("%p\n"),
00493                         ACE_LIB_TEXT ("ACE::get_bcast_addr:")
00494                         ACE_LIB_TEXT ("ioctl (get broadaddr)")));
00495           else
00496             {
00497               ACE_OS::memcpy (reinterpret_cast<sockaddr_in *> (&ip_addr),
00498                               reinterpret_cast<sockaddr_in *> (&if_req.ifr_broadaddr),
00499                               sizeof if_req.ifr_broadaddr);
00500 
00501               ACE_OS::memcpy ((void *) &host_addr,
00502                               (void *) &ip_addr.sin_addr,
00503                               sizeof host_addr);
00504 
00505               if (handle == ACE_INVALID_HANDLE)
00506                 ACE_OS::close (s);
00507 
00508               bcast_addr = host_addr;
00509               return 0;
00510             }
00511         }
00512       else
00513         ACE_ERROR ((LM_ERROR,
00514                     ACE_LIB_TEXT ("%p\n"),
00515                     ACE_LIB_TEXT ("ACE::get_bcast_addr:")
00516                     ACE_LIB_TEXT ("Broadcast is not enable for this interface.")));
00517 
00518       if (handle == ACE_INVALID_HANDLE)
00519         ACE_OS::close (s);
00520 
00521       bcast_addr = host_addr;
00522       return 0;
00523     }
00524 
00525   return 0;
00526 #else
00527   ACE_UNUSED_ARG (handle);
00528   ACE_UNUSED_ARG (host_addr);
00529   ACE_UNUSED_ARG (host_name);
00530   bcast_addr = (ACE_UINT32 (INADDR_BROADCAST));
00531   return 0;
00532 #endif /* !ACE_WIN32 && !__INTERIX */
00533 }
00534 
00535 // return an array of all configured IP interfaces on this host, count
00536 // rc = 0 on success (count == number of interfaces else -1 caller is
00537 // responsible for calling delete [] on parray
00538 
00539 int
00540 ACE::get_ip_interfaces (size_t &count,
00541                         ACE_INET_Addr *&addrs)
00542 {
00543   ACE_TRACE ("ACE::get_ip_interfaces");
00544 
00545   count = 0;
00546   addrs = 0;
00547 
00548 #if defined (ACE_WIN32)
00549   // Win32 can do this by a simple API call if MSVC 5 or later is the compiler.
00550   // Not sure if Borland supplies the needed header/lib, but it might.
00551 # if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
00552   int i, n_interfaces, status;
00553 
00554   INTERFACE_INFO info[64];
00555   SOCKET sock;
00556 
00557   // Get an (overlapped) DGRAM socket to test with
00558   sock = socket (AF_INET, SOCK_DGRAM, 0);
00559   if (sock == INVALID_SOCKET)
00560     return -1;
00561 
00562   DWORD bytes;
00563   status = WSAIoctl(sock,
00564                     SIO_GET_INTERFACE_LIST,
00565                     0,
00566                     0,
00567                     info,
00568                     sizeof(info),
00569                     &bytes,
00570                     0,
00571                     0);
00572   closesocket (sock);
00573   if (status == SOCKET_ERROR)
00574     return -1;
00575 
00576   n_interfaces = bytes / sizeof(INTERFACE_INFO);
00577   if (n_interfaces == 0)
00578     return 0;
00579 
00580   // SIO_GET_INTERFACE_LIST does not work for IPv6
00581   // Instead recent versions of Winsock2 add the new opcode SIO_ADDRESS_LIST_QUERY.
00582   // If this is not available forget about IPv6 local interfaces:-/
00583 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
00584   int n_v6_interfaces = 0;
00585 
00586   LPSOCKET_ADDRESS_LIST v6info;
00587   char *buffer;
00588   DWORD buflen = sizeof (SOCKET_ADDRESS_LIST) + (63 * sizeof (SOCKET_ADDRESS));
00589   ACE_NEW_RETURN (buffer,
00590                   char[buflen],
00591                   -1);
00592   v6info = reinterpret_cast<LPSOCKET_ADDRESS_LIST> (buffer);
00593 
00594   // Get an (overlapped) DGRAM socket to test with.
00595   // If it fails only return IPv4 interfaces.
00596   sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
00597   if (sock == INVALID_SOCKET)
00598     {
00599       delete [] buffer;
00600       return -1;
00601     }
00602 
00603   status = WSAIoctl(sock,
00604                     SIO_ADDRESS_LIST_QUERY,
00605                     0,
00606                     0,
00607                     v6info,
00608                     buflen,
00609                     &bytes,
00610                     0,
00611                     0);
00612   closesocket (sock);
00613   if (status == SOCKET_ERROR)
00614   {
00615       delete [] buffer; // clean up
00616       return -1;
00617   }
00618 
00619   n_v6_interfaces = v6info->iAddressCount;
00620 
00621   ACE_NEW_RETURN (addrs,
00622                   ACE_INET_Addr[n_interfaces + n_v6_interfaces],
00623                   -1);
00624 # else /* ACE_HAS_IPV6 */
00625   ACE_NEW_RETURN (addrs,
00626                   ACE_INET_Addr[n_interfaces],
00627                   -1);
00628 # endif /* !ACE_HAS_IPV6 */
00629 
00630   // Now go through the list and transfer the good ones to the list of
00631   // because they're down or don't have an IP address.
00632   for (count = 0, i = 0; i < n_interfaces; ++i)
00633     {
00634       LPINTERFACE_INFO lpii;
00635       struct sockaddr_in *addrp = 0;
00636 
00637       lpii = &info[i];
00638       if (!(lpii->iiFlags & IFF_UP))
00639         continue;
00640 
00641       // We assume IPv4 addresses here
00642       addrp = reinterpret_cast<struct sockaddr_in *> (&lpii->iiAddress.AddressIn);
00643       if (addrp->sin_addr.s_addr == INADDR_ANY)
00644         continue;
00645 
00646       // Set the address for the caller.
00647       addrs[count].set(addrp, sizeof(sockaddr_in));
00648       ++count;
00649     }
00650 
00651 # if defined (ACE_HAS_IPV6)
00652   // Now go through the list and transfer the good ones to the list of
00653   // because they're down or don't have an IP address.
00654   for (i = 0; i < n_v6_interfaces; i++)
00655     {
00656       struct sockaddr_in6 *addr6p;
00657 
00658       if (v6info->Address[i].lpSockaddr->sa_family != AF_INET6)
00659         continue;
00660 
00661       addr6p = reinterpret_cast<struct sockaddr_in6 *> (v6info->Address[i].lpSockaddr);
00662       if (IN6_IS_ADDR_UNSPECIFIED(&addr6p->sin6_addr))  // IN6ADDR_ANY?
00663         continue;
00664 
00665       // Set the address for the caller.
00666       addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr6p), sizeof(sockaddr_in6));
00667       ++count;
00668     }
00669 
00670   delete [] buffer; // Clean up
00671 # endif /* ACE_HAS_IPV6 */
00672 
00673   if (count == 0)
00674     {
00675       delete [] addrs;
00676       addrs = 0;
00677     }
00678 
00679   return 0;
00680 
00681 #else /* Winsock 2 && MSVC 5 or later */
00682 
00683   // PharLap ETS has kernel routines to rummage through the device
00684   // configs and extract the interface info. Sort of a pain in the
00685   // butt, but better than trying to figure out where it moved to in
00686   // the registry... :-|
00687 #  if defined (ACE_HAS_PHARLAP)
00688 #    if !defined (ACE_HAS_PHARLAP_RT)
00689   ACE_NOTSUP_RETURN (-1);
00690 #    endif /* ACE_HAS_PHARLAP_RT */
00691 
00692   // Locate all of the IP devices in the system, saving a DEVHANDLE
00693   // for each. Then allocate the ACE_INET_Addrs needed and fetch all
00694   // the IP addresses.  To locate the devices, try the available
00695   // device name roots and increment the device number until the
00696   // kernel says there are no more of that type.
00697   const size_t ACE_MAX_ETS_DEVICES = 64;  // Arbitrary, but should be enough.
00698   DEVHANDLE ip_dev[ACE_MAX_ETS_DEVICES];
00699   EK_TCPIPCFG *devp;
00700   size_t i, j;
00701   ACE_TCHAR dev_name[16];
00702 
00703   count = 0;
00704   for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
00705     {
00706       // Ethernet.
00707       ACE_OS::sprintf (dev_name,
00708                        "ether%d",
00709                        i);
00710       ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
00711       if (ip_dev[count] == 0)
00712         break;
00713     }
00714   for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
00715     {
00716       // SLIP.
00717       ACE_OS::sprintf (dev_name,
00718                        "sl%d",
00719                        i);
00720       ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
00721       if (ip_dev[count] == 0)
00722         break;
00723     }
00724   for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
00725     {
00726       // PPP.
00727       ACE_OS::sprintf (dev_name,
00728                        "ppp%d",
00729                        i);
00730       ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
00731       if (ip_dev[count] == 0)
00732         break;
00733     }
00734 
00735   if (count > 0)
00736     ACE_NEW_RETURN (addrs,
00737                     ACE_INET_Addr[count],
00738                     -1);
00739   else
00740     addrs = 0;
00741 
00742   for (i = 0, j = 0; i < count; i++)
00743     {
00744       devp = EtsTCPGetDeviceCfg (ip_dev[i]);
00745       if (devp != 0)
00746         {
00747           addrs[j].set (0,
00748                         devp->nwIPAddress,
00749                         0); // Already in net order.
00750           j++;
00751         }
00752       // There's no call to close the DEVHANDLE.
00753     }
00754 
00755   count = j;
00756   if (count == 0 && addrs != 0)
00757     {
00758       delete [] addrs;
00759       addrs = 0;
00760     }
00761 
00762   return 0;
00763 
00764 #  else /* ACE_HAS_PHARLAP */
00765 
00766 #   if defined (ACE_HAS_WINCE)
00767 
00768   // CE does not support Winsock2 (yet) and has many variations on registry setting.
00769   // Thus, it is better to use GetAdapterInfo defined in iphlpapi.h, which is a
00770   // standard library for CE.  iphlpapi.lib should come with the CE SDK and should
00771   // be included in the machine.
00772   // Note: This call is supported only in WinCE 3.0 or later.  Also, even though
00773   //       "iphlpapi.dll" may not be found in the /Windows directory on some machines,
00774   //       it will (must) support iphlpapi API's because it is part of the standard
00775   //       library for WinCE.
00776 
00777     IP_ADAPTER_INFO* adapterInfo = 0;
00778     ULONG sz = 0;
00779     DWORD result = ::GetAdaptersInfo(adapterInfo, &sz);
00780 
00781     while (result != ERROR_SUCCESS)
00782     {
00783         switch (result)
00784         {
00785         case ERROR_BUFFER_OVERFLOW:  // MUST come here at the first run because sz = 0
00786             adapterInfo = (PIP_ADAPTER_INFO)(new char[sz]);  // I know, I know, this is ugly.
00787 
00788             result = ::GetAdaptersInfo(adapterInfo, &sz);
00789             if (result == ERROR_SUCCESS) {
00790                 const char* invalid_IP = "0.0.0.0";
00791 
00792                 // find out how many interfaces are there
00793                 {
00794                     IP_ADAPTER_INFO* tempAdapterInfo = adapterInfo;
00795                     int n_interfaces = 0;
00796                     while (tempAdapterInfo != 0) {
00797                         IP_ADDR_STRING* addr = &tempAdapterInfo->IpAddressList;
00798                         while (addr != 0) {
00799                             if (ACE_OS::strcmp(addr->IpAddress.String, invalid_IP) != 0) {
00800                                 // skip invalid IP address
00801                                 ++n_interfaces;
00802                             }
00803                             addr = addr->Next;
00804                         }
00805                         tempAdapterInfo = tempAdapterInfo->Next;
00806                     }
00807                     if (n_interfaces == 0) {
00808                         ACE_ERROR_RETURN ((LM_ERROR,
00809                             ACE_LIB_TEXT ("%p\nACE::get_ip_interfaces - "),
00810                             ACE_LIB_TEXT ("No adapter found.")),
00811                             -1);
00812                     }
00813 
00814                     ACE_NEW_RETURN (addrs, ACE_INET_Addr[n_interfaces], -2);
00815                 }
00816 
00817                 // find out valid IP addresses and put them into the addr
00818                 while (adapterInfo != 0) {
00819                     IP_ADDR_STRING* addr = &adapterInfo->IpAddressList;
00820                     while (addr != 0) {
00821                         if (ACE_OS::strcmp(addr->IpAddress.String, invalid_IP) != 0) {
00822                             addrs[count++] = ACE_INET_Addr((u_short) 0, addr->IpAddress.String);
00823                         }
00824                         addr = addr->Next;
00825                     }
00826                     adapterInfo = adapterInfo->Next;
00827                 }
00828             }
00829             // if second GetAdaptersInfo call fails, let other cases take care of it
00830             break;
00831 
00832         case ERROR_NOT_SUPPORTED: // OS does not support this method
00833             ACE_ERROR_RETURN ((LM_ERROR,
00834                 ACE_LIB_TEXT ("%p\nACE::get_ip_interfaces - "),
00835                 ACE_LIB_TEXT ("This version of WinCE does not support GetAdapterInfo.")),
00836                 -1);
00837             break;
00838 
00839         case ERROR_NO_DATA:  // no adapter installed
00840             ACE_ERROR_RETURN ((LM_ERROR,
00841                 ACE_LIB_TEXT ("%p\nACE::get_ip_interfaces - "),
00842                 ACE_LIB_TEXT ("No network adapter installed.")),
00843                 -1);
00844             break;
00845 
00846         case ERROR_INVALID_PARAMETER:
00847             ACE_ERROR_RETURN ((LM_ERROR,
00848                 ACE_LIB_TEXT ("%p\nACE::get_ip_interfaces - "),
00849                 ACE_LIB_TEXT ("Invalid parameter.")),
00850                 -1);
00851             break;
00852 
00853         default:
00854             ACE_ERROR_RETURN ((LM_ERROR,
00855                 ACE_LIB_TEXT ("%p\nACE::get_ip_interfaces - "),
00856                 ACE_LIB_TEXT ("Adapter info access permission denied.")),
00857                 -1);
00858             break;
00859         }
00860     }
00861 
00862     delete [] adapterInfo;
00863     return 0;
00864 
00865 #   endif  // ACE_HAS_WINCE
00866 
00867   //
00868   // No Winsock2.
00869   // Get interface information from the registry.
00870   // As this information is in different locations of the registry
00871   // on different windows versions, we need to ask at runtime.
00872   //
00873 
00874   // Normally we have to look under one key for interfaces name,
00875   // and under a second key for ip address of those interfaces.
00876   // Exact values and the way to search depend on windows version.
00877 
00878   // This is the first key we have to look for.
00879   const ACE_TCHAR *BASE_KEY1;
00880 
00881   // This is the name we have to look for under the first key.
00882   // If this is == 0, we need to look for subkeys, not the values from
00883   // a name.
00884   const ACE_TCHAR *KEY1_NAME_ID;
00885 
00886   // The second key is normally constructed concatenating a prefix,
00887   // the value found on KEY1_NAME_ID stripped from the first s_offset
00888   // characters, and a suffix.
00889   unsigned int s_offset;
00890   const ACE_TCHAR *PREFFIX_KEY2;
00891   const ACE_TCHAR *SUFFIX_KEY2;
00892 
00893   // If != 0, look for the value of KEY1_NAME_ID not directly under
00894   // BASE_KEY1, but on every subkey of BASE_KEY1.
00895   int use_subkeys;
00896 
00897   // When we search for IP Addresses below, we look for a key with a
00898   // name in this array (null terminated).
00899   // For some windows versions, there is an
00900   // aditional key for ppp interfaces that will be stored on [1].
00901   const ACE_TCHAR *IPADDR_NAME_ID[3] = {
00902     ACE_LIB_TEXT ("IPAddress"), 0, 0
00903   };
00904 
00905   // Skip addresses that match this.
00906   const ACE_TCHAR *INVALID_TCPIP_DEVICE_ADDR = ACE_LIB_TEXT ("0.0.0.0");
00907 
00908   ACE_WINDOWS_VERSION winver = get_windows_version();
00909 
00910   switch (winver)
00911     {
00912       case ACE_WINDOWS_IS_WINNT:
00913         PREFFIX_KEY2 = ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services\\");
00914         BASE_KEY1 =
00915           ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services")
00916           ACE_LIB_TEXT ("\\Tcpip\\Linkage");
00917         SUFFIX_KEY2 = ACE_LIB_TEXT ("\\Parameters\\Tcpip");
00918         KEY1_NAME_ID = ACE_LIB_TEXT ("Bind");
00919         s_offset = 8;
00920         use_subkeys = 0;
00921         break;
00922 
00923       case ACE_WINDOWS_IS_WIN2K:
00924         BASE_KEY1 =
00925           ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services")
00926           ACE_LIB_TEXT ("\\Tcpip\\Parameters\\Interfaces\\");
00927         PREFFIX_KEY2 = BASE_KEY1;
00928         SUFFIX_KEY2 = ACE_LIB_TEXT ("");
00929         KEY1_NAME_ID = 0;
00930         s_offset = 0;
00931         use_subkeys = 1;
00932         // PPP.
00933         IPADDR_NAME_ID[1] = ACE_LIB_TEXT ("DhcpIPAddress");
00934         break;
00935 
00936       // If ACE_HAS_WINNT4 we can safely assume the ones below will
00937       // not be needed.
00938 #   if !defined(ACE_HAS_WINNT4) || (ACE_HAS_WINNT4 == 0)
00939       case ACE_WINDOWS_IS_WIN95:
00940       case ACE_WINDOWS_IS_WIN98:
00941       case ACE_WINDOWS_IS_WINME:
00942         PREFFIX_KEY2 =
00943           ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services\\Class\\");
00944         BASE_KEY1 = ACE_LIB_TEXT ("Enum\\Network\\MSTCP");
00945         SUFFIX_KEY2 = ACE_LIB_TEXT ("");
00946         KEY1_NAME_ID =  ACE_LIB_TEXT ("Driver");
00947         use_subkeys = 1;
00948         s_offset = 0;
00949         break;
00950 #   endif /* !ACE_HAS_WINNT4 */
00951 
00952       default:
00953         return -1;
00954     }
00955 
00956   ACE_TCHAR raw_buffer[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
00957   DWORD raw_buflen = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
00958 
00959   if (KEY1_NAME_ID == 0)
00960     {
00961       if (::get_reg_subkeys (BASE_KEY1,
00962                              raw_buffer,
00963                              raw_buflen))
00964         return -1;
00965     }
00966   else
00967     {
00968       if (::get_reg_value (BASE_KEY1,
00969                            KEY1_NAME_ID,
00970                            raw_buffer,
00971                            raw_buflen,
00972                            use_subkeys))
00973         return -1;
00974     }
00975   // return buffer contains 0 delimited strings
00976 
00977   ACE_Tokenizer dev_names (raw_buffer);
00978   dev_names.delimiter (ACE_LIB_TEXT ('\0'));
00979   int n_interfaces = 0;
00980 
00981   // Count the number of interfaces
00982   while (dev_names.next () != 0)
00983     ++n_interfaces;
00984 
00985   // case 1. no interfaces present, empty string? OS version change?
00986   if (n_interfaces == 0)
00987     return 0;
00988 
00989   ACE_NEW_RETURN (addrs,
00990                   ACE_INET_Addr[n_interfaces],
00991                   -2);
00992 
00993   ACE_TCHAR buffer[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
00994   DWORD buf_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
00995 
00996   count = 0;
00997   for (int i = 0; i < n_interfaces; i++)
00998     {
00999       for (const ACE_TCHAR **ipaddr_name_id = IPADDR_NAME_ID;
01000            *ipaddr_name_id != 0;
01001            ++ipaddr_name_id)
01002         {
01003           // a. construct name to access IP Address for this interface
01004           ACE_TString ifdevkey (PREFFIX_KEY2);
01005           ACE_TString the_dev = dev_names.next ();
01006 
01007           if (the_dev.length() < s_offset)
01008             {
01009               return -3;              // Something's wrong
01010             }
01011 
01012           // rest of string from offset.
01013           the_dev = the_dev.substring (s_offset);
01014 
01015           ifdevkey += the_dev;
01016           ifdevkey += SUFFIX_KEY2;
01017 
01018           // b. extract value
01019           // Gets overwritten on each call
01020           buf_len = sizeof (buffer);
01021           if (get_reg_value (ifdevkey.fast_rep (),
01022                              *ipaddr_name_id,
01023                              buffer,
01024                              buf_len))
01025             continue; // Skip unknown devices.
01026 
01027           if (ACE_OS::strcmp (buffer,
01028                               INVALID_TCPIP_DEVICE_ADDR) == 0)
01029             continue; // Don't count this device
01030 
01031           // c. store in hostinfo object array and up the counter
01032           addrs[count++] =
01033             ACE_INET_Addr ((u_short) 0, buffer);
01034         }
01035     }
01036 
01037   return 0;
01038 #  endif /* ACE_HAS_PHARLAP */
01039 # endif /* Winsock 2 && MSVC 5 or later */
01040 
01041 #elif defined (ACE_HAS_GETIFADDRS)
01042   // Take advantage of the BSD getifaddrs function that simplifies
01043   // access to connected interfaces.
01044   struct ifaddrs *ifap;
01045   struct ifaddrs *p_if;
01046 
01047   if (::getifaddrs (&ifap) != 0)
01048     return -1;
01049 
01050   // Count number of interfaces.
01051   size_t num_ifs = 0;
01052   for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
01053     ++num_ifs;
01054 
01055   // Now create and initialize output array.
01056   ACE_NEW_RETURN (addrs,
01057                   ACE_INET_Addr[num_ifs],
01058                   -1); // caller must free
01059 
01060   // Pull the address out of each INET interface.  Not every interface
01061   // is for IP, so be careful to count properly.  When setting the
01062   // INET_Addr, note that the 3rd arg (0) says to leave the byte order
01063   // (already in net byte order from the interface structure) as is.
01064   count = 0;
01065 
01066   for (p_if = ifap;
01067        p_if != 0;
01068        p_if = p_if->ifa_next)
01069     {
01070       if (p_if->ifa_addr &&
01071           p_if->ifa_addr->sa_family == AF_INET)
01072         {
01073           struct sockaddr_in *addr =
01074             reinterpret_cast<sockaddr_in *> (p_if->ifa_addr);
01075 
01076           // Sometimes the kernel returns 0.0.0.0 as the interface
01077           // address, skip those...
01078           if (addr->sin_addr.s_addr != INADDR_ANY)
01079             {
01080               addrs[count].set ((u_short) 0,
01081                                 addr->sin_addr.s_addr,
01082                                 0);
01083               ++count;
01084             }
01085         }
01086 # if defined (ACE_HAS_IPV6)
01087       else if (p_if->ifa_addr &&
01088                p_if->ifa_addr->sa_family == AF_INET6)
01089         {
01090           struct sockaddr_in6 *addr =
01091             reinterpret_cast<sockaddr_in6 *> (p_if->ifa_addr);
01092 
01093           // Skip the ANY address
01094           if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr))
01095             {
01096               addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr),
01097                                sizeof(sockaddr_in6));
01098               ++count;
01099             }
01100         }
01101 # endif /* ACE_HAS_IPV6 */
01102     }
01103 
01104   ::freeifaddrs (ifap);
01105 
01106   return 0;
01107 
01108 #elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (ACE_OPENVMS)
01109   // COMMON (SVR4 and BSD) UNIX CODE
01110 
01111   size_t num_ifs, num_ifs_found;
01112 
01113   // Call specific routine as necessary.
01114   ACE_HANDLE handle = get_handle();
01115 
01116   if (handle == ACE_INVALID_HANDLE)
01117     ACE_ERROR_RETURN ((LM_ERROR,
01118                        ACE_LIB_TEXT ("%p\n"),
01119                        ACE_LIB_TEXT ("ACE::get_ip_interfaces:open")),
01120                       -1);
01121   if (ACE::count_interfaces (handle, num_ifs))
01122     {
01123       ACE_OS::close (handle);
01124       return -1;
01125     }
01126 
01127   // ioctl likes to have an extra ifreq structure to mark the end of
01128   // what it returned, so increase the num_ifs by one.
01129   ++num_ifs;
01130 
01131   struct ifreq *ifs = 0;
01132   ACE_NEW_RETURN (ifs,
01133                   struct ifreq[num_ifs],
01134                   -1);
01135   ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct ifreq));
01136 
01137   ACE_Auto_Array_Ptr<struct ifreq> p_ifs (ifs);
01138 
01139   if (p_ifs.get() == 0)
01140     {
01141       ACE_OS::close (handle);
01142       errno = ENOMEM;
01143       return -1;
01144     }
01145 
01146   struct ifconf ifcfg;
01147   ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
01148   ifcfg.ifc_req = p_ifs.get ();
01149   ifcfg.ifc_len = num_ifs * sizeof (struct ifreq);
01150 
01151 #if defined (AIX)
01152   int cmd = CSIOCGIFCONF;
01153 #else
01154   int cmd = SIOCGIFCONF;
01155 #endif /* AIX */
01156   if (ACE_OS::ioctl (handle,
01157                      cmd,
01158                      (caddr_t) &ifcfg) == -1)
01159     {
01160       ACE_OS::close (handle);
01161       ACE_ERROR_RETURN ((LM_ERROR,
01162                          ACE_LIB_TEXT ("%p\n"),
01163                          ACE_LIB_TEXT ("ACE::get_ip_interfaces:")
01164                          ACE_LIB_TEXT ("ioctl - SIOCGIFCONF failed")),
01165                         -1);
01166     }
01167 
01168   ACE_OS::close (handle);
01169 
01170   // Now create and initialize output array.
01171 
01172   ACE_NEW_RETURN (addrs,
01173                   ACE_INET_Addr[num_ifs],
01174                   -1); // caller must free
01175 
01176   struct ifreq *pcur = p_ifs.get ();
01177   num_ifs_found = ifcfg.ifc_len / sizeof (struct ifreq); // get the number of returned ifs
01178 
01179   // Pull the address out of each INET interface.  Not every interface
01180   // is for IP, so be careful to count properly.  When setting the
01181   // INET_Addr, note that the 3rd arg (0) says to leave the byte order
01182   // (already in net byte order from the interface structure) as is.
01183   count = 0;
01184 
01185   for (size_t i = 0;
01186        i < num_ifs_found;
01187        i++)
01188     {
01189       if (pcur->ifr_addr.sa_family == AF_INET)
01190         {
01191 #if !defined(_UNICOS)
01192           struct sockaddr_in *addr =
01193             reinterpret_cast<sockaddr_in *> (&pcur->ifr_addr);
01194 
01195           // Sometimes the kernel returns 0.0.0.0 as the interface
01196           // address, skip those...
01197           if (addr->sin_addr.s_addr != 0)
01198             {
01199               addrs[count].set ((u_short) 0,
01200                                 addr->sin_addr.s_addr,
01201                                 0);
01202               count++;
01203             }
01204 #else /* ! _UNICOS */
01205           // need to explicitly copy on the Cray, since the bitfields kinda
01206           // screw things up here
01207           struct sockaddr_in inAddr;
01208 
01209           inAddr.sin_len = pcur->ifr_addr.sa_len;
01210           inAddr.sin_family = pcur->ifr_addr.sa_family;
01211           memcpy((void *)&(inAddr.sin_addr),
01212                  (const void *)&(pcur->ifr_addr.sa_data[8]),
01213                  sizeof(struct in_addr));
01214 
01215           if (inAddr.sin_addr.s_addr != 0)
01216             {
01217               addrs[count].set(&inAddr, sizeof(struct sockaddr_in));
01218               ++count;
01219             }
01220 #endif /* ! _UNICOS */
01221         }
01222 
01223 #if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
01224       ++pcur;
01225 #else
01226       if (pcur->ifr_addr.sa_len <= sizeof (struct sockaddr))
01227         {
01228            ++pcur;
01229         }
01230       else
01231         {
01232            pcur = (struct ifreq *)
01233                (pcur->ifr_addr.sa_len + (caddr_t) &pcur->ifr_addr);
01234         }
01235 #endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
01236     }
01237 
01238 # if defined (ACE_HAS_IPV6)
01239   // Retrieve IPv6 local interfaces by scanning /proc/net/if_inet6 if it exists.
01240   // If we cannot open it then ignore possible IPv6 interfaces, we did our best;-)
01241   FILE* fp;
01242   char addr_p[8][5];
01243   char s_ipaddr[64];
01244   int scopeid;
01245   struct addrinfo hints, *res0;
01246   int error;
01247 
01248   ACE_OS::memset (&hints, 0, sizeof (hints));
01249   hints.ai_flags = AI_NUMERICHOST;
01250   hints.ai_family = AF_INET6;
01251 
01252   if ((fp = ACE_OS::fopen (ACE_LIB_TEXT ("/proc/net/if_inet6"), ACE_LIB_TEXT ("r"))) != NULL)
01253     {
01254       while (fscanf (fp,
01255                      "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*8s\n",
01256                      addr_p[0], addr_p[1], addr_p[2], addr_p[3],
01257                      addr_p[4], addr_p[5], addr_p[6], addr_p[7], &scopeid) != EOF)
01258         {
01259           // Format the address intoa proper IPv6 decimal address specification and
01260           // resolve the resulting text using getaddrinfo().
01261 
01262           const char* ip_fmt = "%s:%s:%s:%s:%s:%s:%s:%s%%%d";
01263           ACE_OS::sprintf (s_ipaddr,
01264                            ip_fmt,
01265                            addr_p[0], addr_p[1], addr_p[2], addr_p[3],
01266                            addr_p[4], addr_p[5], addr_p[6], addr_p[7], scopeid);
01267 
01268           error = getaddrinfo (s_ipaddr, 0, &hints, &res0);
01269           if (error)
01270             continue;
01271 
01272           if (res0->ai_family == AF_INET6 &&
01273                 !IN6_IS_ADDR_UNSPECIFIED (&reinterpret_cast<sockaddr_in6 *> (res0->ai_addr)->sin6_addr))
01274             {
01275               addrs[count].set(reinterpret_cast<sockaddr_in *> (res0->ai_addr), res0->ai_addrlen);
01276               ++count;
01277             }
01278           freeaddrinfo (res0);
01279 
01280         }
01281       ACE_OS::fclose (fp);
01282     }
01283 # endif /* ACE_HAS_IPV6 */
01284 
01285   return 0;
01286 #elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
01287   count = 0;
01288   // Loop through each address structure
01289   for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
01290     {
01291       ++count;
01292     }
01293 
01294   // Now create and initialize output array.
01295   ACE_NEW_RETURN (addrs,
01296                   ACE_INET_Addr[count],
01297                   -1); // caller must free
01298   count = 0;
01299   for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
01300     {
01301       struct ifnet* ifp = ia->ia_ifa.ifa_ifp;
01302       if (ifp != 0)
01303         {
01304           // Get the current interface name
01305           char interface[64];
01306           ACE_OS::sprintf(interface, "%s%d", ifp->if_name, ifp->if_unit);
01307 
01308           // Get the address for the current interface
01309           char address [INET_ADDR_LEN];
01310           STATUS status = ifAddrGet(interface, address);
01311 
01312           if (status == OK)
01313             {
01314               // Concatenate a ':' at the end. This is because in
01315               // ACE_INET_Addr::string_to_addr, the ip_address is
01316               // obtained using ':' as the delimiter. Since, using
01317               // ifAddrGet(), we just get the IP address, I am adding
01318               // a ":" to get with the general case.
01319               ACE_OS::strcat (address, ":");
01320               addrs[count].set (address);
01321             }
01322           else
01323             {
01324               ACE_ERROR_RETURN ((LM_ERROR,
01325                                  ACE_LIB_TEXT ("ACE::get_ip_interface failed\n")
01326                                  ACE_LIB_TEXT ("Couldnt get the IP Address\n")),
01327                                  -1);
01328             }
01329           ++count;
01330         }
01331     }
01332   return 0;
01333 #else
01334   ACE_UNUSED_ARG (count);
01335   ACE_UNUSED_ARG (addrs);
01336   ACE_NOTSUP_RETURN (-1);                      // no implementation
01337 #endif /* ACE_WIN32 */
01338 }
01339 
01340 // Helper routine for get_ip_interfaces, differs by UNIX platform so
01341 // put into own subroutine.  perform some ioctls to retrieve ifconf
01342 // list of ifreq structs.
01343 
01344 int
01345 ACE::count_interfaces (ACE_HANDLE handle, size_t &how_many)
01346 {
01347 #if defined (sparc) && defined (SIOCGIFNUM)
01348   int tmp_how_many; // For 64 bit Solaris
01349   if (ACE_OS::ioctl (handle,
01350                      SIOCGIFNUM,
01351                      (caddr_t) &tmp_how_many) == -1)
01352     ACE_ERROR_RETURN ((LM_ERROR,
01353                        ACE_LIB_TEXT ("%p\n"),
01354                        ACE_LIB_TEXT ("ACE::count_interfaces:")
01355                        ACE_LIB_TEXT ("ioctl - SIOCGIFNUM failed")),
01356                       -1);
01357   how_many = (size_t) tmp_how_many;
01358   return 0;
01359 #elif defined (ACE_HAS_GETIFADDRS)
01360   ACE_UNUSED_ARG (handle);
01361 
01362   struct ifaddrs *ifap;
01363   struct ifaddrs *p_if;
01364 
01365   if (::getifaddrs (&ifap) != 0)
01366     return -1;
01367 
01368   // Count number of interfaces.
01369   size_t num_ifs = 0;
01370   for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
01371     ++num_ifs;
01372 
01373   ::freeifaddrs (ifap);
01374 
01375   how_many = num_ifs;
01376   return 0;
01377 #elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (ACE_OPENVMS)
01378   // Note: DEC CXX doesn't define "unix".  BSD compatible OS: HP UX,
01379   // AIX, SunOS 4.x perform some ioctls to retrieve ifconf list of
01380   // ifreq structs no SIOCGIFNUM on SunOS 4.x, so use guess and scan
01381   // algorithm
01382 
01383   // Probably hard to put this many ifs in a unix box..
01384   const int MAX_IF = 50;
01385 
01386   // HACK - set to an unreasonable number
01387   int num_ifs = MAX_IF;
01388 
01389   struct ifconf ifcfg;
01390   size_t ifreq_size = num_ifs * sizeof (struct ifreq);
01391   struct ifreq *p_ifs =
01392     (struct ifreq *) ACE_OS::malloc (ifreq_size);
01393 
01394   if (!p_ifs)
01395     {
01396       errno = ENOMEM;
01397       return -1;
01398     }
01399 
01400   ACE_OS::memset (p_ifs, 0, ifreq_size);
01401   ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
01402 
01403   ifcfg.ifc_req = p_ifs;
01404   ifcfg.ifc_len = ifreq_size;
01405 
01406 #if defined (AIX)
01407   int cmd = CSIOCGIFCONF;
01408 #else
01409   int cmd = SIOCGIFCONF;
01410 #endif /* AIX */
01411   if (ACE_OS::ioctl (handle,
01412                      cmd,
01413                      (caddr_t) &ifcfg) == -1)
01414     {
01415       ACE_OS::free (ifcfg.ifc_req);
01416       ACE_ERROR_RETURN ((LM_ERROR,
01417                          ACE_LIB_TEXT ("%p\n"),
01418                          ACE_LIB_TEXT ("ACE::count_interfaces:")
01419                          ACE_LIB_TEXT ("ioctl - SIOCGIFCONF failed")),
01420                         -1);
01421     }
01422 
01423   int if_count = 0, i;
01424 
01425   // get if address out of ifreq buffers.  ioctl puts a blank-named
01426   // interface to mark the end of the returned interfaces.
01427   for (i = 0;
01428        i < num_ifs;
01429        i++)
01430     {
01431       /* In OpenBSD, the length of the list is returned. */
01432       ifcfg.ifc_len -= sizeof (struct ifreq);
01433       if (ifcfg.ifc_len < 0)
01434         break;
01435 
01436       if_count++;
01437 #if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
01438       p_ifs++;
01439 #else
01440      if (p_ifs->ifr_addr.sa_len <= sizeof (struct sockaddr))
01441        {
01442           p_ifs++;
01443        }
01444        else
01445        {
01446           p_ifs = (struct ifreq *)
01447               (p_ifs->ifr_addr.sa_len + (caddr_t) &p_ifs->ifr_addr);
01448        }
01449 #endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
01450     }
01451 
01452   ACE_OS::free (ifcfg.ifc_req);
01453 
01454 # if defined (ACE_HAS_IPV6)
01455   FILE* fp;
01456 
01457   if ((fp = ACE_OS::fopen (ACE_LIB_TEXT ("/proc/net/if_inet6"), ACE_LIB_TEXT ("r"))) != NULL)
01458     {
01459       // Scan the lines according to the expected format but don't really read any input
01460       while (fscanf (fp, "%*32s %*02x %*02x %*02x %*02x %*8s\n") != EOF)
01461         {
01462           if_count++;
01463         }
01464       ACE_OS::fclose (fp);
01465     }
01466 # endif /* ACE_HAS_IPV6 */
01467 
01468   how_many = if_count;
01469   return 0;
01470 #else
01471   ACE_UNUSED_ARG (handle);
01472   ACE_UNUSED_ARG (how_many);
01473   ACE_NOTSUP_RETURN (-1); // no implementation
01474 #endif /* sparc && SIOCGIFNUM */
01475 }
01476 
01477 // Routine to return a handle from which ioctl() requests can be made.
01478 
01479 ACE_HANDLE
01480 ACE::get_handle (void)
01481 {
01482   // Solaris 2.x
01483   ACE_HANDLE handle = ACE_INVALID_HANDLE;
01484 #if defined (sparc)
01485   handle = ACE_OS::open ("/dev/udp", O_RDONLY);
01486 #elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || (defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)) || defined (ACE_OPENVMS)
01487   // Note: DEC CXX doesn't define "unix" BSD compatible OS: HP UX,
01488   // AIX, SunOS 4.x
01489 
01490   handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
01491 #endif /* sparc */
01492   return handle;
01493 }
01494 
01495 
01496 int
01497 ACE::ipv6_enabled (void)
01498 {
01499 #if defined (ACE_HAS_IPV6)
01500   if (ace_ipv6_enabled == -1)
01501     {
01502       // Perform Double-Checked Locking Optimization.
01503       ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
01504                                 *ACE_Static_Object_Lock::instance (), 0));
01505 
01506       if (ace_ipv6_enabled == -1)
01507         {
01508           // Determine if the kernel has IPv6 support by attempting to
01509           // create a PF_INET6 socket and see if it fails.
01510           ACE_HANDLE s = ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0);
01511           if (s == ACE_INVALID_HANDLE)
01512             {
01513               ace_ipv6_enabled = 0;
01514             }
01515           else
01516             {
01517               ace_ipv6_enabled = 1;
01518               ACE_OS::closesocket (s);
01519             }
01520         }
01521     }
01522 
01523   return ace_ipv6_enabled;
01524 #else /* ACE_HAS_IPV6 */
01525   return 0;
01526 #endif /* !ACE_HAS_IPV6 */
01527 }
01528 
01529 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 09:42:04 2006 for ACE by doxygen 1.3.6