summaryrefslogtreecommitdiff
path: root/ACE/ace/Sock_Connect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace/Sock_Connect.cpp')
-rw-r--r--ACE/ace/Sock_Connect.cpp1529
1 files changed, 1529 insertions, 0 deletions
diff --git a/ACE/ace/Sock_Connect.cpp b/ACE/ace/Sock_Connect.cpp
new file mode 100644
index 00000000000..215f997675f
--- /dev/null
+++ b/ACE/ace/Sock_Connect.cpp
@@ -0,0 +1,1529 @@
+// $Id$
+
+#include "ace/Sock_Connect.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/Handle_Set.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/SString.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_stdio.h"
+
+#if defined (sparc)
+# include "ace/OS_NS_fcntl.h"
+#endif // sparc
+
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_netdb.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/os_include/net/os_if.h"
+
+#if defined (ACE_HAS_IPV6)
+# include "ace/Guard_T.h"
+# include "ace/Recursive_Thread_Mutex.h"
+#endif /* ACE_HAS_IPV6 */
+
+# if defined (ACE_HAS_GETIFADDRS)
+# if defined (ACE_VXWORKS)
+# include /**/ <net/ifaddrs.h>
+# else
+# include /**/ <ifaddrs.h>
+# endif
+# endif /* ACE_HAS_GETIFADDRS */
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
+#include /**/ <inetLib.h>
+#include /**/ <netinet/in_var.h>
+extern "C" {
+ extern struct in_ifaddr* in_ifaddr;
+}
+#include "ace/OS_NS_stdio.h"
+#endif /* ACE_VXWORKS < 0x600 */
+
+#if defined (ACE_HAS_WINCE)
+#include /**/ <Iphlpapi.h>
+#endif // ACE_HAS_WINCE
+
+#if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
+# include "ace/OS_NS_stdio.h"
+#endif
+
+#if defined (ACE_HAS_IPV6)
+# if defined (ACE_HAS_THREADS)
+# include "ace/Object_Manager.h"
+# endif /* ACE_HAS_THREADS */
+
+namespace
+{
+ // private:
+ // Used internally so not exported.
+
+ /// Does this box have ipv6 turned on?
+ int ace_ipv6_enabled = -1;
+}
+#endif /* ACE_HAS_IPV6 */
+
+// This is a hack to work around a problem with Visual Age C++ 5 and 6 on AIX.
+// Without this, the compiler auto-instantiates the ACE_Auto_Array_Ptr for
+// ifreq (contained in this module) but only adds the #include for <net/if.h>
+// and not the one for <sys/socket.h> which is also needed. Although we
+// don't need the template defined here, it makes the compiler pull in
+// <sys/socket.h> and the build runs clean.
+#if defined (AIX) && defined (__IBMCPP__) && (__IBMCPP__ >= 500) && (__IBMCPP__ < 700)
+static ACE_Auto_Array_Ptr<sockaddr> force_compiler_to_include_socket_h;
+#endif /* AIX && __IBMCPP__ >= 500 */
+
+
+ACE_RCSID (ace,
+ Sock_Connect,
+ "$Id$")
+
+
+#if defined (ACE_WIN32) && \
+ (!defined (ACE_HAS_WINSOCK2) \
+ || (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 0)))
+
+static int
+get_reg_subkeys (const ACE_TCHAR *key,
+ ACE_TCHAR *buffer,
+ DWORD &buf_len)
+{
+ HKEY hk;
+ LONG rc = ACE_TEXT_RegOpenKeyEx (HKEY_LOCAL_MACHINE,
+ key,
+ 0,
+ KEY_READ,
+ &hk);
+
+ if (rc != ERROR_SUCCESS)
+ return -1;
+
+ ACE_TCHAR subkeyname[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
+ DWORD subkeyname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN;
+ FILETIME update_dummy;
+
+ DWORD total = 0;
+
+ for (int i = 0;
+ (rc = ACE_TEXT_RegEnumKeyEx (hk, i,
+ subkeyname,
+ &subkeyname_len,
+ 0, 0, 0,
+ &update_dummy)) != ERROR_NO_MORE_ITEMS;
+ ++i)
+ {
+ if (subkeyname_len < buf_len - total)
+ {
+ ACE_OS::strcpy(buffer + total, subkeyname);
+ total += subkeyname_len + 1;
+ // Reset: was changed by RegEnumKeyEx call.
+ subkeyname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
+ }
+ else
+ return -1;
+ }
+
+ buf_len = total;
+
+ ::RegCloseKey (hk);
+ return 0;
+}
+
+// Return value in buffer for a key/name pair from the Windows
+// Registry up to buf_len size.
+// If all_subkeys == 1, look for name under all subkeys of key.
+
+static int
+get_reg_value (const ACE_TCHAR *key,
+ const ACE_TCHAR *name,
+ ACE_TCHAR *buffer,
+ DWORD &buf_len,
+ int all_subkeys = 0)
+{
+ HKEY hk;
+ DWORD buf_type;
+ LONG rc = ACE_TEXT_RegOpenKeyEx (HKEY_LOCAL_MACHINE,
+ key,
+ 0,
+ KEY_READ,
+ &hk);
+
+ if (rc != ERROR_SUCCESS)
+ // print_error_string(ACE_LIB_TEXT ("RegOpenKeyEx"), rc);
+ return -1;
+
+ if (all_subkeys)
+ {
+ ACE_TCHAR ifname[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
+ DWORD ifname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
+ FILETIME update_dummy;
+
+ DWORD total = 0;
+ DWORD size = buf_len;
+
+ for (int i = 0;
+ (rc = ACE_TEXT_RegEnumKeyEx (hk, i, ifname, &ifname_len,
+ 0, 0, 0,
+ &update_dummy)) != ERROR_NO_MORE_ITEMS;
+ ++i)
+ {
+ HKEY ifkey;
+ if (rc != ERROR_SUCCESS
+ || ACE_TEXT_RegOpenKeyEx (hk, ifname, 0,
+ KEY_READ, &ifkey) != ERROR_SUCCESS)
+ continue;
+
+ if (ACE_TEXT_RegQueryValueEx (ifkey, name, 0, 0,
+ (u_char*) (buffer + total),
+ &size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(ifkey);
+ continue;
+ }
+ else
+ {
+ total += size;
+ size = buf_len - total;
+ }
+ // Needs to be reset.
+ ifname_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
+ }
+
+ if (total == 0)
+ {
+ ::RegCloseKey (hk);
+ return -2;
+ }
+ else
+ {
+ buf_len = total;
+ }
+ }
+ else
+ {
+
+ rc = ACE_TEXT_RegQueryValueEx (hk,
+ name,
+ 0,
+ &buf_type,
+ (u_char *) buffer,
+ &buf_len);
+ if (rc != ERROR_SUCCESS)
+ {
+ // print_error_string(ACE_LIB_TEXT ("RegEnumKeyEx"), rc);
+ RegCloseKey (hk);
+ return -2;
+ }
+ }
+
+ ::RegCloseKey (hk);
+ return 0;
+}
+
+enum ACE_WINDOWS_VERSION {
+ ACE_WINDOWS_IS_UNKNOWN,
+ ACE_WINDOWS_IS_WIN95,
+ ACE_WINDOWS_IS_WIN98,
+ ACE_WINDOWS_IS_WINME,
+ ACE_WINDOWS_IS_WINNT,
+ ACE_WINDOWS_IS_WIN2K,
+ ACE_WINDOWS_IS_WINCE
+};
+
+static ACE_WINDOWS_VERSION
+get_windows_version()
+{
+ OSVERSIONINFO vinfo;
+ vinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (::GetVersionEx(&vinfo) == 0)
+ {
+ return ACE_WINDOWS_IS_UNKNOWN;
+ }
+
+ switch (vinfo.dwPlatformId)
+ {
+ case VER_PLATFORM_WIN32_NT:
+ if (vinfo.dwMajorVersion <= 4)
+ return ACE_WINDOWS_IS_WINNT;
+ else
+ return ACE_WINDOWS_IS_WIN2K;
+ case VER_PLATFORM_WIN32_WINDOWS:
+ if (vinfo.dwMajorVersion == 4)
+ {
+ if (vinfo.dwMinorVersion == 0)
+ return ACE_WINDOWS_IS_WIN95;
+ else if (vinfo.dwMinorVersion == 10)
+ return ACE_WINDOWS_IS_WIN98;
+ else if (vinfo.dwMinorVersion == 90)
+ return ACE_WINDOWS_IS_WINME;
+ }
+#if defined (VER_PLATFORM_WIN32_CE)
+ case VER_PLATFORM_WIN32_CE:
+ if (vinfo.dwMajorVersion >= 3) {
+ return ACE_WINDOWS_IS_WINCE;
+ }
+ else {
+ return ACE_WINDOWS_IS_UNKNOWN;
+ }
+#endif /* VER_PLATFORM_WIN32_CE */
+ // If no match we fall throu.
+ default:
+ return ACE_WINDOWS_IS_UNKNOWN;
+ }
+}
+
+#endif //(ACE_WIN32) && !(ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 0)
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Bind socket to an unused port.
+
+int
+ACE::bind_port (ACE_HANDLE handle, ACE_UINT32 ip_addr, int address_family)
+{
+ ACE_TRACE ("ACE::bind_port");
+
+ ACE_INET_Addr addr;
+
+#if defined (ACE_HAS_IPV6)
+ if (address_family != PF_INET6)
+ // What do we do if it is PF_"INET6? Since it's 4 bytes, it must be an
+ // IPV4 address. Is there a difference? Why is this test done? dhinton
+#else /* ACE_HAS_IPV6 */
+ ACE_UNUSED_ARG (address_family);
+#endif /* !ACE_HAS_IPV6 */
+ addr = ACE_INET_Addr ((u_short)0, ip_addr);
+#if defined (ACE_HAS_IPV6)
+ else if (ip_addr != INADDR_ANY)
+ // address_family == PF_INET6 and a non default IP address means to bind
+ // to the IPv4-mapped IPv6 address
+ addr.set ((u_short)0, ip_addr, 1, 1);
+#endif /* ACE_HAS_IPV6 */
+
+#if !defined (ACE_LACKS_WILDCARD_BIND)
+ // The OS kernel should select a free port for us.
+ return ACE_OS::bind (handle,
+ (sockaddr*)addr.get_addr(),
+ addr.get_size());
+#else
+ static u_short upper_limit = ACE_MAX_DEFAULT_PORT;
+ int round_trip = upper_limit;
+ int lower_limit = IPPORT_RESERVED;
+
+ // We have to select the port explicitly.
+
+ for (;;)
+ {
+ addr.set((u_short)upper_limit,ip_addr);
+
+ if (ACE_OS::bind (handle,
+ (sockaddr*)addr.get_addr()
+ addr.get_size()) >= 0)
+ {
+#if defined (ACE_WIN32)
+ upper_limit--;
+#endif /* ACE_WIN32 */
+ return 0;
+ }
+ else if (errno != EADDRINUSE)
+ return -1;
+ else
+ {
+ upper_limit--;
+
+ // Wrap back around when we reach the bottom.
+ if (upper_limit <= lower_limit)
+ upper_limit = ACE_MAX_DEFAULT_PORT;
+
+ // See if we have already gone around once!
+ if (upper_limit == round_trip)
+ {
+ errno = EAGAIN;
+ return -1;
+ }
+ }
+ }
+#endif /* ACE_HAS_WILDCARD_BIND */
+}
+
+int
+ACE::get_bcast_addr (ACE_UINT32 &bcast_addr,
+ const ACE_TCHAR *host_name,
+ ACE_UINT32 host_addr,
+ ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE::get_bcast_addr");
+
+#if !defined(ACE_WIN32) && !defined(__INTERIX)
+ ACE_HANDLE s = handle;
+
+ if (s == ACE_INVALID_HANDLE)
+ s = ACE_OS::socket (AF_INET, SOCK_STREAM, 0);
+
+ if (s == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE_OS::socket")),
+ -1);
+
+ struct ifconf ifc;
+ char buf[BUFSIZ];
+
+ ifc.ifc_len = sizeof buf;
+ ifc.ifc_buf = buf;
+
+ // Get interface structure and initialize the addresses using UNIX
+ // techniques
+#if defined (AIX)
+ int cmd = CSIOCGIFCONF;
+#else
+ int cmd = SIOCGIFCONF;
+#endif /* AIX */
+ if (ACE_OS::ioctl (s, cmd, (char *) &ifc) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::get_bcast_addr:")
+ ACE_LIB_TEXT ("ioctl (get interface configuration)")),
+ -1);
+
+ struct ifreq *ifr = ifc.ifc_req;
+
+ struct sockaddr_in ip_addr;
+
+ // Get host ip address if necessary.
+ if (host_name)
+ {
+ hostent *hp = ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name));
+
+ if (hp == 0)
+ return -1;
+ else
+#if !defined(_UNICOS)
+ ACE_OS::memcpy ((char *) &ip_addr.sin_addr.s_addr,
+ (char *) hp->h_addr,
+ hp->h_length);
+#else /* _UNICOS */
+ {
+ ACE_UINT64 haddr; // a place to put the address
+ char * haddrp = (char *) &haddr; // convert to char pointer
+ ACE_OS::memcpy(haddrp,(char *) hp->h_addr,hp->h_length);
+ ip_addr.sin_addr.s_addr = haddr;
+ }
+#endif /* ! _UNICOS */
+ }
+ else
+ {
+ ACE_OS::memset ((void *) &ip_addr, 0, sizeof ip_addr);
+#if !defined(_UNICOS)
+ ACE_OS::memcpy ((void *) &ip_addr.sin_addr,
+ (void*) &host_addr,
+ sizeof ip_addr.sin_addr);
+#else /* _UNICOS */
+ ip_addr.sin_addr.s_addr = host_addr; // just copy to the bitfield
+#endif /* ! _UNICOS */
+ }
+
+#if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
+ for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
+ n--, ifr++)
+#else
+ // see mk_broadcast@SOCK_Dgram_Bcast.cpp
+ for (int nbytes = ifc.ifc_len; nbytes >= (int) sizeof (struct ifreq) &&
+ ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
+ (nbytes >= (int) sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len) : 1);
+ ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
+ (nbytes -= sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len,
+ ifr = (struct ifreq *)
+ ((caddr_t) &ifr->ifr_addr + ifr->ifr_addr.sa_len)) :
+ (nbytes -= sizeof (struct ifreq), ifr++)))
+#endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
+ {
+ struct sockaddr_in if_addr;
+
+ // Compare host ip address with interface ip address.
+ ACE_OS::memcpy (&if_addr,
+ &ifr->ifr_addr,
+ sizeof if_addr);
+
+ if (ip_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
+ continue;
+
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::get_bcast_addr:")
+ ACE_LIB_TEXT ("Not AF_INET")));
+ continue;
+ }
+
+ struct ifreq flags = *ifr;
+ struct ifreq if_req = *ifr;
+
+ if (ACE_OS::ioctl (s, SIOCGIFFLAGS, (char *) &flags) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::get_bcast_addr:")
+ ACE_LIB_TEXT (" ioctl (get interface flags)")));
+ continue;
+ }
+
+ if (ACE_BIT_DISABLED (flags.ifr_flags, IFF_UP))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::get_bcast_addr:")
+ ACE_LIB_TEXT ("Network interface is not up")));
+ continue;
+ }
+
+ if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_LOOPBACK))
+ continue;
+
+ if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_BROADCAST))
+ {
+ if (ACE_OS::ioctl (s,
+ SIOCGIFBRDADDR,
+ (char *) &if_req) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::get_bcast_addr:")
+ ACE_LIB_TEXT ("ioctl (get broadaddr)")));
+ else
+ {
+ ACE_OS::memcpy (reinterpret_cast<sockaddr_in *> (&ip_addr),
+ reinterpret_cast<sockaddr_in *> (&if_req.ifr_broadaddr),
+ sizeof if_req.ifr_broadaddr);
+
+ ACE_OS::memcpy ((void *) &host_addr,
+ (void *) &ip_addr.sin_addr,
+ sizeof host_addr);
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_OS::close (s);
+
+ bcast_addr = host_addr;
+ return 0;
+ }
+ }
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::get_bcast_addr:")
+ ACE_LIB_TEXT ("Broadcast is not enable for this interface.")));
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_OS::close (s);
+
+ bcast_addr = host_addr;
+ return 0;
+ }
+
+ return 0;
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (host_addr);
+ ACE_UNUSED_ARG (host_name);
+ bcast_addr = (ACE_UINT32 (INADDR_BROADCAST));
+ return 0;
+#endif /* !ACE_WIN32 && !__INTERIX */
+}
+
+// return an array of all configured IP interfaces on this host, count
+// rc = 0 on success (count == number of interfaces else -1 caller is
+// responsible for calling delete [] on parray
+
+int
+ACE::get_ip_interfaces (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ ACE_TRACE ("ACE::get_ip_interfaces");
+
+ count = 0;
+ addrs = 0;
+
+#if defined (ACE_WIN32)
+ // Win32 can do this by a simple API call if MSVC 5 or later is the compiler.
+ // Not sure if Borland supplies the needed header/lib, but it might.
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ int i, n_interfaces, status;
+
+ INTERFACE_INFO info[64];
+ SOCKET sock;
+
+ // Get an (overlapped) DGRAM socket to test with
+ sock = socket (AF_INET, SOCK_DGRAM, 0);
+ if (sock == INVALID_SOCKET)
+ return -1;
+
+ DWORD bytes;
+ status = WSAIoctl(sock,
+ SIO_GET_INTERFACE_LIST,
+ 0,
+ 0,
+ info,
+ sizeof(info),
+ &bytes,
+ 0,
+ 0);
+ closesocket (sock);
+ if (status == SOCKET_ERROR)
+ return -1;
+
+ n_interfaces = bytes / sizeof(INTERFACE_INFO);
+ if (n_interfaces == 0)
+ return 0;
+
+ // SIO_GET_INTERFACE_LIST does not work for IPv6
+ // Instead recent versions of Winsock2 add the new opcode SIO_ADDRESS_LIST_QUERY.
+ // If this is not available forget about IPv6 local interfaces:-/
+# if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
+ int n_v6_interfaces = 0;
+
+ LPSOCKET_ADDRESS_LIST v6info;
+ char *buffer;
+ DWORD buflen = sizeof (SOCKET_ADDRESS_LIST) + (63 * sizeof (SOCKET_ADDRESS));
+ ACE_NEW_RETURN (buffer,
+ char[buflen],
+ -1);
+ v6info = reinterpret_cast<LPSOCKET_ADDRESS_LIST> (buffer);
+
+ // Get an (overlapped) DGRAM socket to test with.
+ // If it fails only return IPv4 interfaces.
+ sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock == INVALID_SOCKET)
+ {
+ delete [] buffer;
+ return -1;
+ }
+
+ status = WSAIoctl(sock,
+ SIO_ADDRESS_LIST_QUERY,
+ 0,
+ 0,
+ v6info,
+ buflen,
+ &bytes,
+ 0,
+ 0);
+ closesocket (sock);
+ if (status == SOCKET_ERROR)
+ {
+ delete [] buffer; // clean up
+ return -1;
+ }
+
+ n_v6_interfaces = v6info->iAddressCount;
+
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[n_interfaces + n_v6_interfaces],
+ -1);
+# else /* ACE_HAS_IPV6 */
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[n_interfaces],
+ -1);
+# endif /* !ACE_HAS_IPV6 */
+
+ // Now go through the list and transfer the good ones to the list of
+ // because they're down or don't have an IP address.
+ for (count = 0, i = 0; i < n_interfaces; ++i)
+ {
+ LPINTERFACE_INFO lpii;
+ struct sockaddr_in *addrp = 0;
+
+ lpii = &info[i];
+ if (!(lpii->iiFlags & IFF_UP))
+ continue;
+
+ // We assume IPv4 addresses here
+ addrp = reinterpret_cast<struct sockaddr_in *> (&lpii->iiAddress.AddressIn);
+ if (addrp->sin_addr.s_addr == INADDR_ANY)
+ continue;
+
+ // Set the address for the caller.
+ addrs[count].set(addrp, sizeof(sockaddr_in));
+ ++count;
+ }
+
+# if defined (ACE_HAS_IPV6)
+ // Now go through the list and transfer the good ones to the list of
+ // because they're down or don't have an IP address.
+ for (i = 0; i < n_v6_interfaces; i++)
+ {
+ struct sockaddr_in6 *addr6p;
+
+ if (v6info->Address[i].lpSockaddr->sa_family != AF_INET6)
+ continue;
+
+ addr6p = reinterpret_cast<struct sockaddr_in6 *> (v6info->Address[i].lpSockaddr);
+ if (IN6_IS_ADDR_UNSPECIFIED(&addr6p->sin6_addr)) // IN6ADDR_ANY?
+ continue;
+
+ // Set the address for the caller.
+ addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr6p), sizeof(sockaddr_in6));
+ ++count;
+ }
+
+ delete [] buffer; // Clean up
+# endif /* ACE_HAS_IPV6 */
+
+ if (count == 0)
+ {
+ delete [] addrs;
+ addrs = 0;
+ }
+
+ return 0;
+
+#else /* Winsock 2 && MSVC 5 or later */
+
+ // PharLap ETS has kernel routines to rummage through the device
+ // configs and extract the interface info. Sort of a pain in the
+ // butt, but better than trying to figure out where it moved to in
+ // the registry... :-|
+# if defined (ACE_HAS_PHARLAP)
+# if !defined (ACE_HAS_PHARLAP_RT)
+ ACE_NOTSUP_RETURN (-1);
+# endif /* ACE_HAS_PHARLAP_RT */
+
+ // Locate all of the IP devices in the system, saving a DEVHANDLE
+ // for each. Then allocate the ACE_INET_Addrs needed and fetch all
+ // the IP addresses. To locate the devices, try the available
+ // device name roots and increment the device number until the
+ // kernel says there are no more of that type.
+ const size_t ACE_MAX_ETS_DEVICES = 64; // Arbitrary, but should be enough.
+ DEVHANDLE ip_dev[ACE_MAX_ETS_DEVICES];
+ EK_TCPIPCFG *devp;
+ size_t i, j;
+ ACE_TCHAR dev_name[16];
+
+ count = 0;
+ for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
+ {
+ // Ethernet.
+ ACE_OS::sprintf (dev_name,
+ "ether%d",
+ i);
+ ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
+ if (ip_dev[count] == 0)
+ break;
+ }
+ for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
+ {
+ // SLIP.
+ ACE_OS::sprintf (dev_name,
+ "sl%d",
+ i);
+ ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
+ if (ip_dev[count] == 0)
+ break;
+ }
+ for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
+ {
+ // PPP.
+ ACE_OS::sprintf (dev_name,
+ "ppp%d",
+ i);
+ ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
+ if (ip_dev[count] == 0)
+ break;
+ }
+
+ if (count > 0)
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[count],
+ -1);
+ else
+ addrs = 0;
+
+ for (i = 0, j = 0; i < count; i++)
+ {
+ devp = EtsTCPGetDeviceCfg (ip_dev[i]);
+ if (devp != 0)
+ {
+ addrs[j].set (0,
+ devp->nwIPAddress,
+ 0); // Already in net order.
+ j++;
+ }
+ // There's no call to close the DEVHANDLE.
+ }
+
+ count = j;
+ if (count == 0 && addrs != 0)
+ {
+ delete [] addrs;
+ addrs = 0;
+ }
+
+ return 0;
+
+# else /* ACE_HAS_PHARLAP */
+
+# if defined (ACE_HAS_WINCE)
+
+ // CE does not support Winsock2 (yet) and has many variations on registry setting.
+ // Thus, it is better to use GetAdapterInfo defined in iphlpapi.h, which is a
+ // standard library for CE. iphlpapi.lib should come with the CE SDK and should
+ // be included in the machine.
+ // Note: This call is supported only in WinCE 3.0 or later. Also, even though
+ // "iphlpapi.dll" may not be found in the /Windows directory on some machines,
+ // it will (must) support iphlpapi API's because it is part of the standard
+ // library for WinCE.
+
+ IP_ADAPTER_INFO* adapterInfo = 0;
+ ULONG sz = 0;
+ DWORD result = ::GetAdaptersInfo(adapterInfo, &sz);
+
+ while (result != ERROR_SUCCESS)
+ {
+ switch (result)
+ {
+ case ERROR_BUFFER_OVERFLOW: // MUST come here at the first run because sz = 0
+ adapterInfo = (PIP_ADAPTER_INFO)(new char[sz]); // I know, I know, this is ugly.
+
+ result = ::GetAdaptersInfo(adapterInfo, &sz);
+ if (result == ERROR_SUCCESS) {
+ const char* invalid_IP = "0.0.0.0";
+
+ // find out how many interfaces are there
+ {
+ IP_ADAPTER_INFO* tempAdapterInfo = adapterInfo;
+ int n_interfaces = 0;
+ while (tempAdapterInfo != 0) {
+ IP_ADDR_STRING* addr = &tempAdapterInfo->IpAddressList;
+ while (addr != 0) {
+ if (ACE_OS::strcmp(addr->IpAddress.String, invalid_IP) != 0) {
+ // skip invalid IP address
+ ++n_interfaces;
+ }
+ addr = addr->Next;
+ }
+ tempAdapterInfo = tempAdapterInfo->Next;
+ }
+ if (n_interfaces == 0) {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\nACE::get_ip_interfaces - "),
+ ACE_LIB_TEXT ("No adapter found.")),
+ -1);
+ }
+
+ ACE_NEW_RETURN (addrs, ACE_INET_Addr[n_interfaces], -2);
+ }
+
+ // find out valid IP addresses and put them into the addr
+ while (adapterInfo != 0) {
+ IP_ADDR_STRING* addr = &adapterInfo->IpAddressList;
+ while (addr != 0) {
+ if (ACE_OS::strcmp(addr->IpAddress.String, invalid_IP) != 0) {
+ addrs[count++] = ACE_INET_Addr((u_short) 0, addr->IpAddress.String);
+ }
+ addr = addr->Next;
+ }
+ adapterInfo = adapterInfo->Next;
+ }
+ }
+ // if second GetAdaptersInfo call fails, let other cases take care of it
+ break;
+
+ case ERROR_NOT_SUPPORTED: // OS does not support this method
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\nACE::get_ip_interfaces - "),
+ ACE_LIB_TEXT ("This version of WinCE does not support GetAdapterInfo.")),
+ -1);
+ break;
+
+ case ERROR_NO_DATA: // no adapter installed
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\nACE::get_ip_interfaces - "),
+ ACE_LIB_TEXT ("No network adapter installed.")),
+ -1);
+ break;
+
+ case ERROR_INVALID_PARAMETER:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\nACE::get_ip_interfaces - "),
+ ACE_LIB_TEXT ("Invalid parameter.")),
+ -1);
+ break;
+
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\nACE::get_ip_interfaces - "),
+ ACE_LIB_TEXT ("Adapter info access permission denied.")),
+ -1);
+ break;
+ }
+ }
+
+ delete [] adapterInfo;
+ return 0;
+
+# endif // ACE_HAS_WINCE
+
+ //
+ // No Winsock2.
+ // Get interface information from the registry.
+ // As this information is in different locations of the registry
+ // on different windows versions, we need to ask at runtime.
+ //
+
+ // Normally we have to look under one key for interfaces name,
+ // and under a second key for ip address of those interfaces.
+ // Exact values and the way to search depend on windows version.
+
+ // This is the first key we have to look for.
+ const ACE_TCHAR *BASE_KEY1;
+
+ // This is the name we have to look for under the first key.
+ // If this is == 0, we need to look for subkeys, not the values from
+ // a name.
+ const ACE_TCHAR *KEY1_NAME_ID;
+
+ // The second key is normally constructed concatenating a prefix,
+ // the value found on KEY1_NAME_ID stripped from the first s_offset
+ // characters, and a suffix.
+ unsigned int s_offset;
+ const ACE_TCHAR *PREFFIX_KEY2;
+ const ACE_TCHAR *SUFFIX_KEY2;
+
+ // If != 0, look for the value of KEY1_NAME_ID not directly under
+ // BASE_KEY1, but on every subkey of BASE_KEY1.
+ int use_subkeys;
+
+ // When we search for IP Addresses below, we look for a key with a
+ // name in this array (null terminated).
+ // For some windows versions, there is an
+ // aditional key for ppp interfaces that will be stored on [1].
+ const ACE_TCHAR *IPADDR_NAME_ID[3] = {
+ ACE_LIB_TEXT ("IPAddress"), 0, 0
+ };
+
+ // Skip addresses that match this.
+ const ACE_TCHAR *INVALID_TCPIP_DEVICE_ADDR = ACE_LIB_TEXT ("0.0.0.0");
+
+ ACE_WINDOWS_VERSION winver = get_windows_version();
+
+ switch (winver)
+ {
+ case ACE_WINDOWS_IS_WINNT:
+ PREFFIX_KEY2 = ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services\\");
+ BASE_KEY1 =
+ ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services")
+ ACE_LIB_TEXT ("\\Tcpip\\Linkage");
+ SUFFIX_KEY2 = ACE_LIB_TEXT ("\\Parameters\\Tcpip");
+ KEY1_NAME_ID = ACE_LIB_TEXT ("Bind");
+ s_offset = 8;
+ use_subkeys = 0;
+ break;
+
+ case ACE_WINDOWS_IS_WIN2K:
+ BASE_KEY1 =
+ ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services")
+ ACE_LIB_TEXT ("\\Tcpip\\Parameters\\Interfaces\\");
+ PREFFIX_KEY2 = BASE_KEY1;
+ SUFFIX_KEY2 = ACE_LIB_TEXT ("");
+ KEY1_NAME_ID = 0;
+ s_offset = 0;
+ use_subkeys = 1;
+ // PPP.
+ IPADDR_NAME_ID[1] = ACE_LIB_TEXT ("DhcpIPAddress");
+ break;
+
+ // If ACE_HAS_WINNT4 we can safely assume the ones below will
+ // not be needed.
+# if !defined(ACE_HAS_WINNT4) || (ACE_HAS_WINNT4 == 0)
+ case ACE_WINDOWS_IS_WIN95:
+ case ACE_WINDOWS_IS_WIN98:
+ case ACE_WINDOWS_IS_WINME:
+ PREFFIX_KEY2 =
+ ACE_LIB_TEXT ("SYSTEM\\CurrentControlSet\\Services\\Class\\");
+ BASE_KEY1 = ACE_LIB_TEXT ("Enum\\Network\\MSTCP");
+ SUFFIX_KEY2 = ACE_LIB_TEXT ("");
+ KEY1_NAME_ID = ACE_LIB_TEXT ("Driver");
+ use_subkeys = 1;
+ s_offset = 0;
+ break;
+# endif /* !ACE_HAS_WINNT4 */
+
+ default:
+ return -1;
+ }
+
+ ACE_TCHAR raw_buffer[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
+ DWORD raw_buflen = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
+
+ if (KEY1_NAME_ID == 0)
+ {
+ if (::get_reg_subkeys (BASE_KEY1,
+ raw_buffer,
+ raw_buflen))
+ return -1;
+ }
+ else
+ {
+ if (::get_reg_value (BASE_KEY1,
+ KEY1_NAME_ID,
+ raw_buffer,
+ raw_buflen,
+ use_subkeys))
+ return -1;
+ }
+ // return buffer contains 0 delimited strings
+
+ ACE_Tokenizer dev_names (raw_buffer);
+ dev_names.delimiter (ACE_LIB_TEXT ('\0'));
+ int n_interfaces = 0;
+
+ // Count the number of interfaces
+ while (dev_names.next () != 0)
+ ++n_interfaces;
+
+ // case 1. no interfaces present, empty string? OS version change?
+ if (n_interfaces == 0)
+ return 0;
+
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[n_interfaces],
+ -2);
+
+ ACE_TCHAR buffer[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1];
+ DWORD buf_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1;
+
+ count = 0;
+ for (int i = 0; i < n_interfaces; i++)
+ {
+ for (const ACE_TCHAR **ipaddr_name_id = IPADDR_NAME_ID;
+ *ipaddr_name_id != 0;
+ ++ipaddr_name_id)
+ {
+ // a. construct name to access IP Address for this interface
+ ACE_TString ifdevkey (PREFFIX_KEY2);
+ ACE_TString the_dev = dev_names.next ();
+
+ if (the_dev.length() < s_offset)
+ {
+ return -3; // Something's wrong
+ }
+
+ // rest of string from offset.
+ the_dev = the_dev.substring (s_offset);
+
+ ifdevkey += the_dev;
+ ifdevkey += SUFFIX_KEY2;
+
+ // b. extract value
+ // Gets overwritten on each call
+ buf_len = sizeof (buffer);
+ if (get_reg_value (ifdevkey.fast_rep (),
+ *ipaddr_name_id,
+ buffer,
+ buf_len))
+ continue; // Skip unknown devices.
+
+ if (ACE_OS::strcmp (buffer,
+ INVALID_TCPIP_DEVICE_ADDR) == 0)
+ continue; // Don't count this device
+
+ // c. store in hostinfo object array and up the counter
+ addrs[count++] =
+ ACE_INET_Addr ((u_short) 0, buffer);
+ }
+ }
+
+ return 0;
+# endif /* ACE_HAS_PHARLAP */
+# endif /* Winsock 2 && MSVC 5 or later */
+
+#elif defined (ACE_HAS_GETIFADDRS)
+ // Take advantage of the BSD getifaddrs function that simplifies
+ // access to connected interfaces.
+ struct ifaddrs *ifap;
+ struct ifaddrs *p_if;
+
+ if (::getifaddrs (&ifap) != 0)
+ return -1;
+
+ // Count number of interfaces.
+ size_t num_ifs = 0;
+ for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
+ ++num_ifs;
+
+ // Now create and initialize output array.
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[num_ifs],
+ -1); // caller must free
+
+ // Pull the address out of each INET interface. Not every interface
+ // is for IP, so be careful to count properly. When setting the
+ // INET_Addr, note that the 3rd arg (0) says to leave the byte order
+ // (already in net byte order from the interface structure) as is.
+ count = 0;
+
+ for (p_if = ifap;
+ p_if != 0;
+ p_if = p_if->ifa_next)
+ {
+ if (p_if->ifa_addr &&
+ p_if->ifa_addr->sa_family == AF_INET)
+ {
+ struct sockaddr_in *addr =
+ reinterpret_cast<sockaddr_in *> (p_if->ifa_addr);
+
+ // Sometimes the kernel returns 0.0.0.0 as the interface
+ // address, skip those...
+ if (addr->sin_addr.s_addr != INADDR_ANY)
+ {
+ addrs[count].set ((u_short) 0,
+ addr->sin_addr.s_addr,
+ 0);
+ ++count;
+ }
+ }
+# if defined (ACE_HAS_IPV6)
+ else if (p_if->ifa_addr &&
+ p_if->ifa_addr->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *addr =
+ reinterpret_cast<sockaddr_in6 *> (p_if->ifa_addr);
+
+ // Skip the ANY address
+ if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr))
+ {
+ addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr),
+ sizeof(sockaddr_in6));
+ ++count;
+ }
+ }
+# endif /* ACE_HAS_IPV6 */
+ }
+
+ ::freeifaddrs (ifap);
+
+ return 0;
+
+#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (ACE_OPENVMS)
+ // COMMON (SVR4 and BSD) UNIX CODE
+
+ size_t num_ifs, num_ifs_found;
+
+ // Call specific routine as necessary.
+ ACE_HANDLE handle = get_handle();
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::get_ip_interfaces:open")),
+ -1);
+ if (ACE::count_interfaces (handle, num_ifs))
+ {
+ ACE_OS::close (handle);
+ return -1;
+ }
+
+ // ioctl likes to have an extra ifreq structure to mark the end of
+ // what it returned, so increase the num_ifs by one.
+ ++num_ifs;
+
+ struct ifreq *ifs = 0;
+ ACE_NEW_RETURN (ifs,
+ struct ifreq[num_ifs],
+ -1);
+ ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct ifreq));
+
+ ACE_Auto_Array_Ptr<struct ifreq> p_ifs (ifs);
+
+ if (p_ifs.get() == 0)
+ {
+ ACE_OS::close (handle);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ struct ifconf ifcfg;
+ ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
+ ifcfg.ifc_req = p_ifs.get ();
+ ifcfg.ifc_len = num_ifs * sizeof (struct ifreq);
+
+#if defined (AIX)
+ int cmd = CSIOCGIFCONF;
+#else
+ int cmd = SIOCGIFCONF;
+#endif /* AIX */
+ if (ACE_OS::ioctl (handle,
+ cmd,
+ (caddr_t) &ifcfg) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::get_ip_interfaces:")
+ ACE_LIB_TEXT ("ioctl - SIOCGIFCONF failed")),
+ -1);
+ }
+
+ ACE_OS::close (handle);
+
+ // Now create and initialize output array.
+
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[num_ifs],
+ -1); // caller must free
+
+ struct ifreq *pcur = p_ifs.get ();
+ num_ifs_found = ifcfg.ifc_len / sizeof (struct ifreq); // get the number of returned ifs
+
+ // Pull the address out of each INET interface. Not every interface
+ // is for IP, so be careful to count properly. When setting the
+ // INET_Addr, note that the 3rd arg (0) says to leave the byte order
+ // (already in net byte order from the interface structure) as is.
+ count = 0;
+
+ for (size_t i = 0;
+ i < num_ifs_found;
+ i++)
+ {
+ if (pcur->ifr_addr.sa_family == AF_INET)
+ {
+#if !defined(_UNICOS)
+ struct sockaddr_in *addr =
+ reinterpret_cast<sockaddr_in *> (&pcur->ifr_addr);
+
+ // Sometimes the kernel returns 0.0.0.0 as the interface
+ // address, skip those...
+ if (addr->sin_addr.s_addr != 0)
+ {
+ addrs[count].set ((u_short) 0,
+ addr->sin_addr.s_addr,
+ 0);
+ count++;
+ }
+#else /* ! _UNICOS */
+ // need to explicitly copy on the Cray, since the bitfields kinda
+ // screw things up here
+ struct sockaddr_in inAddr;
+
+ inAddr.sin_len = pcur->ifr_addr.sa_len;
+ inAddr.sin_family = pcur->ifr_addr.sa_family;
+ memcpy((void *)&(inAddr.sin_addr),
+ (const void *)&(pcur->ifr_addr.sa_data[8]),
+ sizeof(struct in_addr));
+
+ if (inAddr.sin_addr.s_addr != 0)
+ {
+ addrs[count].set(&inAddr, sizeof(struct sockaddr_in));
+ ++count;
+ }
+#endif /* ! _UNICOS */
+ }
+
+#if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
+ ++pcur;
+#else
+ if (pcur->ifr_addr.sa_len <= sizeof (struct sockaddr))
+ {
+ ++pcur;
+ }
+ else
+ {
+ pcur = (struct ifreq *)
+ (pcur->ifr_addr.sa_len + (caddr_t) &pcur->ifr_addr);
+ }
+#endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
+ }
+
+# if defined (ACE_HAS_IPV6)
+ // Retrieve IPv6 local interfaces by scanning /proc/net/if_inet6 if it exists.
+ // If we cannot open it then ignore possible IPv6 interfaces, we did our best;-)
+ FILE* fp;
+ char addr_p[8][5];
+ char s_ipaddr[64];
+ int scopeid;
+ struct addrinfo hints, *res0;
+ int error;
+
+ ACE_OS::memset (&hints, 0, sizeof (hints));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = AF_INET6;
+
+ if ((fp = ACE_OS::fopen (ACE_LIB_TEXT ("/proc/net/if_inet6"), ACE_LIB_TEXT ("r"))) != NULL)
+ {
+ while (fscanf (fp,
+ "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*8s\n",
+ addr_p[0], addr_p[1], addr_p[2], addr_p[3],
+ addr_p[4], addr_p[5], addr_p[6], addr_p[7], &scopeid) != EOF)
+ {
+ // Format the address intoa proper IPv6 decimal address specification and
+ // resolve the resulting text using getaddrinfo().
+
+ const char* ip_fmt = "%s:%s:%s:%s:%s:%s:%s:%s%%%d";
+ ACE_OS::sprintf (s_ipaddr,
+ ip_fmt,
+ addr_p[0], addr_p[1], addr_p[2], addr_p[3],
+ addr_p[4], addr_p[5], addr_p[6], addr_p[7], scopeid);
+
+ error = getaddrinfo (s_ipaddr, 0, &hints, &res0);
+ if (error)
+ continue;
+
+ if (res0->ai_family == AF_INET6 &&
+ !IN6_IS_ADDR_UNSPECIFIED (&reinterpret_cast<sockaddr_in6 *> (res0->ai_addr)->sin6_addr))
+ {
+ addrs[count].set(reinterpret_cast<sockaddr_in *> (res0->ai_addr), res0->ai_addrlen);
+ ++count;
+ }
+ freeaddrinfo (res0);
+
+ }
+ ACE_OS::fclose (fp);
+ }
+# endif /* ACE_HAS_IPV6 */
+
+ return 0;
+#elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
+ count = 0;
+ // Loop through each address structure
+ for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
+ {
+ ++count;
+ }
+
+ // Now create and initialize output array.
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[count],
+ -1); // caller must free
+ count = 0;
+ for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
+ {
+ struct ifnet* ifp = ia->ia_ifa.ifa_ifp;
+ if (ifp != 0)
+ {
+ // Get the current interface name
+ char interface[64];
+ ACE_OS::sprintf(interface, "%s%d", ifp->if_name, ifp->if_unit);
+
+ // Get the address for the current interface
+ char address [INET_ADDR_LEN];
+ STATUS status = ifAddrGet(interface, address);
+
+ if (status == OK)
+ {
+ // Concatenate a ':' at the end. This is because in
+ // ACE_INET_Addr::string_to_addr, the ip_address is
+ // obtained using ':' as the delimiter. Since, using
+ // ifAddrGet(), we just get the IP address, I am adding
+ // a ":" to get with the general case.
+ ACE_OS::strcat (address, ":");
+ addrs[count].set (address);
+ }
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE::get_ip_interface failed\n")
+ ACE_LIB_TEXT ("Couldnt get the IP Address\n")),
+ -1);
+ }
+ ++count;
+ }
+ }
+ return 0;
+#else
+ ACE_UNUSED_ARG (count);
+ ACE_UNUSED_ARG (addrs);
+ ACE_NOTSUP_RETURN (-1); // no implementation
+#endif /* ACE_WIN32 */
+}
+
+// Helper routine for get_ip_interfaces, differs by UNIX platform so
+// put into own subroutine. perform some ioctls to retrieve ifconf
+// list of ifreq structs.
+
+int
+ACE::count_interfaces (ACE_HANDLE handle, size_t &how_many)
+{
+#if defined (sparc) && defined (SIOCGIFNUM)
+ int tmp_how_many; // For 64 bit Solaris
+ if (ACE_OS::ioctl (handle,
+ SIOCGIFNUM,
+ (caddr_t) &tmp_how_many) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::count_interfaces:")
+ ACE_LIB_TEXT ("ioctl - SIOCGIFNUM failed")),
+ -1);
+ how_many = (size_t) tmp_how_many;
+ return 0;
+#elif defined (ACE_HAS_GETIFADDRS)
+ ACE_UNUSED_ARG (handle);
+
+ struct ifaddrs *ifap;
+ struct ifaddrs *p_if;
+
+ if (::getifaddrs (&ifap) != 0)
+ return -1;
+
+ // Count number of interfaces.
+ size_t num_ifs = 0;
+ for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
+ ++num_ifs;
+
+ ::freeifaddrs (ifap);
+
+ how_many = num_ifs;
+ return 0;
+#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (ACE_OPENVMS)
+ // Note: DEC CXX doesn't define "unix". BSD compatible OS: HP UX,
+ // AIX, SunOS 4.x perform some ioctls to retrieve ifconf list of
+ // ifreq structs no SIOCGIFNUM on SunOS 4.x, so use guess and scan
+ // algorithm
+
+ // Probably hard to put this many ifs in a unix box..
+ const int MAX_IF = 50;
+
+ // HACK - set to an unreasonable number
+ int num_ifs = MAX_IF;
+
+ struct ifconf ifcfg;
+ size_t ifreq_size = num_ifs * sizeof (struct ifreq);
+ struct ifreq *p_ifs =
+ (struct ifreq *) ACE_OS::malloc (ifreq_size);
+
+ if (!p_ifs)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ACE_OS::memset (p_ifs, 0, ifreq_size);
+ ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
+
+ ifcfg.ifc_req = p_ifs;
+ ifcfg.ifc_len = ifreq_size;
+
+#if defined (AIX)
+ int cmd = CSIOCGIFCONF;
+#else
+ int cmd = SIOCGIFCONF;
+#endif /* AIX */
+ if (ACE_OS::ioctl (handle,
+ cmd,
+ (caddr_t) &ifcfg) == -1)
+ {
+ ACE_OS::free (ifcfg.ifc_req);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("ACE::count_interfaces:")
+ ACE_LIB_TEXT ("ioctl - SIOCGIFCONF failed")),
+ -1);
+ }
+
+ int if_count = 0, i;
+
+ // get if address out of ifreq buffers. ioctl puts a blank-named
+ // interface to mark the end of the returned interfaces.
+ for (i = 0;
+ i < num_ifs;
+ i++)
+ {
+ /* In OpenBSD, the length of the list is returned. */
+ ifcfg.ifc_len -= sizeof (struct ifreq);
+ if (ifcfg.ifc_len < 0)
+ break;
+
+ if_count++;
+#if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
+ p_ifs++;
+#else
+ if (p_ifs->ifr_addr.sa_len <= sizeof (struct sockaddr))
+ {
+ p_ifs++;
+ }
+ else
+ {
+ p_ifs = (struct ifreq *)
+ (p_ifs->ifr_addr.sa_len + (caddr_t) &p_ifs->ifr_addr);
+ }
+#endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
+ }
+
+ ACE_OS::free (ifcfg.ifc_req);
+
+# if defined (ACE_HAS_IPV6)
+ FILE* fp;
+
+ if ((fp = ACE_OS::fopen (ACE_LIB_TEXT ("/proc/net/if_inet6"), ACE_LIB_TEXT ("r"))) != NULL)
+ {
+ // Scan the lines according to the expected format but don't really read any input
+ while (fscanf (fp, "%*32s %*02x %*02x %*02x %*02x %*8s\n") != EOF)
+ {
+ if_count++;
+ }
+ ACE_OS::fclose (fp);
+ }
+# endif /* ACE_HAS_IPV6 */
+
+ how_many = if_count;
+ return 0;
+#else
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (how_many);
+ ACE_NOTSUP_RETURN (-1); // no implementation
+#endif /* sparc && SIOCGIFNUM */
+}
+
+// Routine to return a handle from which ioctl() requests can be made.
+
+ACE_HANDLE
+ACE::get_handle (void)
+{
+ // Solaris 2.x
+ ACE_HANDLE handle = ACE_INVALID_HANDLE;
+#if defined (sparc)
+ handle = ACE_OS::open ("/dev/udp", O_RDONLY);
+#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || (defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)) || defined (ACE_OPENVMS)
+ // Note: DEC CXX doesn't define "unix" BSD compatible OS: HP UX,
+ // AIX, SunOS 4.x
+
+ handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
+#endif /* sparc */
+ return handle;
+}
+
+
+int
+ACE::ipv6_enabled (void)
+{
+#if defined (ACE_HAS_IPV6)
+ if (ace_ipv6_enabled == -1)
+ {
+ // Perform Double-Checked Locking Optimization.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ if (ace_ipv6_enabled == -1)
+ {
+ // Determine if the kernel has IPv6 support by attempting to
+ // create a PF_INET6 socket and see if it fails.
+ ACE_HANDLE s = ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0);
+ if (s == ACE_INVALID_HANDLE)
+ {
+ ace_ipv6_enabled = 0;
+ }
+ else
+ {
+ ace_ipv6_enabled = 1;
+ ACE_OS::closesocket (s);
+ }
+ }
+ }
+
+ return ace_ipv6_enabled;
+#else /* ACE_HAS_IPV6 */
+ return 0;
+#endif /* !ACE_HAS_IPV6 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL