Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Sock_Connect.cpp

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

Generated on Mon Jun 16 11:21:18 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002