aboutsummaryrefslogtreecommitdiff
path: root/externals/ace/Sock_Connect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'externals/ace/Sock_Connect.cpp')
-rw-r--r--externals/ace/Sock_Connect.cpp1597
1 files changed, 1597 insertions, 0 deletions
diff --git a/externals/ace/Sock_Connect.cpp b/externals/ace/Sock_Connect.cpp
new file mode 100644
index 00000000000..217d83c9381
--- /dev/null
+++ b/externals/ace/Sock_Connect.cpp
@@ -0,0 +1,1597 @@
+// $Id: Sock_Connect.cpp 87160 2009-10-19 14:01:10Z olli $
+
+#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"
+#include "ace/ACE.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"
+# if defined (_AIX)
+# include /**/ <netinet/in6_var.h>
+# endif /* _AIX */
+#endif /* ACE_HAS_IPV6 */
+
+# if defined (ACE_HAS_GETIFADDRS)
+# if defined (ACE_VXWORKS)
+# include /**/ <net/ifaddrs.h>
+# else
+# include /**/ <ifaddrs.h>
+# endif /*ACE_VXWORKS */
+# endif /* ACE_HAS_GETIFADDRS */
+
+#if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
+#include /**/ <inetLib.h>
+#include /**/ <netinet/in_var.h>
+#if defined (ACE_HAS_IPV6)
+#include /**/ <ifLib.h>
+extern "C" {
+ extern struct in_ifaddr* in_ifaddr;
+ extern LIST_HEAD(in_ifaddrhashhead, in_ifaddr) *in_ifaddrhashtbl;
+}
+#endif /* ACE_HAS_IPV6 */
+#include "ace/OS_NS_stdio.h"
+#endif /* ACE_VXWORKS < 0x600 */
+
+#if defined (ACE_VXWORKS) && ((ACE_VXWORKS >= 0x630) && (ACE_VXWORKS <= 0x670)) && defined (__RTP__) && defined (ACE_HAS_IPV6)
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
+const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
+const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
+#endif /* ACE_VXWORKS >= 0x630 && <= 0x670 && __RTP__ && ACE_HAS_IPV6 */
+
+#if defined (ACE_HAS_WINCE)
+#include /**/ <iphlpapi.h>
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && (_WIN32_WCE < 0x600) && defined (ACE_HAS_IPV6)
+// The following code is suggested by microsoft as a workaround to the fact
+// that on Windows CE, these constants are exported as function addresses
+// rather than simply values.
+# include /**/ <ws2tcpip.h>
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+# endif
+#endif // ACE_HAS_WINCE
+
+#if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
+# include "ace/OS_NS_stdio.h"
+#endif
+
+#if defined (ACE_HAS_IPV6)
+
+// These defines support a generic usage based on
+// the various SIGCF*IF ioctl implementations
+
+# if defined (SIOCGLIFCONF)
+# define SIOCGIFCONF_CMD SIOCGLIFCONF
+# if defined (__hpux)
+# define IFREQ if_laddrreq
+# define IFCONF if_laddrconf
+# define IFC_REQ iflc_req
+# define IFC_LEN iflc_len
+# define IFC_BUF iflc_buf
+# define IFR_ADDR iflr_addr
+# define IFR_NAME iflr_name
+# define IFR_FLAGS iflr_flags
+# undef SETFAMILY
+# define SA_FAMILY sa_family
+# else
+# define IFREQ lifreq
+# define IFCONF lifconf
+# define IFC_REQ lifc_req
+# define IFC_LEN lifc_len
+# define IFC_BUF lifc_buf
+# define IFR_ADDR lifr_addr
+# define IFR_NAME lifr_name
+# define IFR_FLAGS lifr_flags
+# define SETFAMILY
+# define IFC_FAMILY lifc_family
+# define IFC_FLAGS lifc_flags
+# define SA_FAMILY ss_family
+# endif
+# else
+# define SIOCGIFCONF_CMD SIOCGIFCONF
+# define IFREQ ifreq
+# define IFCONF ifconf
+# define IFC_REQ ifc_req
+# define IFC_LEN ifc_len
+# define IFC_BUF ifc_buf
+# define IFR_ADDR ifr_addr
+# define IFR_NAME ifr_name
+# define IFR_FLAGS ifr_flags
+# undef SETFAMILY
+# define SA_FAMILY sa_family
+# endif /* SIOCGLIFCONF */
+
+# 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 ipv4 turned on?
+ int ace_ipv4_enabled = -1;
+
+ // Does this box have ipv6 turned on?
+ int ace_ipv6_enabled = -1;
+
+}
+#else /* ACE_HAS_IPV6 */
+# define SIOCGIFCONF_CMD SIOCGIFCONF
+# define IFREQ ifreq
+# define IFCONF ifconf
+# define IFC_REQ ifc_req
+# define IFC_LEN ifc_len
+# define IFC_BUF ifc_buf
+# define IFR_ADDR ifr_addr
+# define IFR_NAME ifr_name
+# define IFR_FLAGS ifr_flags
+# undef SETFAMILY
+# define SA_FAMILY sa_family
+#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: Sock_Connect.cpp 87160 2009-10-19 14:01:10Z olli $")
+
+
+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 */
+
+ // The OS kernel should select a free port for us.
+ return ACE_OS::bind (handle,
+ (sockaddr*)addr.get_addr(),
+ addr.get_size());
+}
+
+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_LACKS_GET_BCAST_ADDR)
+ ACE_UNUSED_ARG (bcast_addr);
+ ACE_UNUSED_ARG (host_name);
+ ACE_UNUSED_ARG (host_addr);
+ ACE_UNUSED_ARG (handle);
+ ACE_NOTSUP_RETURN (-1);
+#elif !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_TEXT ("%p\n"),
+ ACE_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 (ACE_OS::ioctl (s, SIOCGIFCONF_CMD, (char *) &ifc) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_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__) && !defined (__Lynx__)
+ 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__) && !defined (__Lynx__) */
+ {
+ 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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_TEXT (" ioctl (get interface flags)")));
+ continue;
+ }
+
+ if (ACE_BIT_DISABLED (flags.ifr_flags, IFF_UP))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_TEXT ("ioctl (get broadaddr)")));
+ else
+ {
+ ACE_OS::memcpy (&ip_addr,
+ &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_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_bcast_addr:")
+ ACE_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 */
+}
+
+int
+ACE::get_fqdn (ACE_INET_Addr const & addr,
+ char hostname[],
+ size_t len)
+{
+ int h_error; // Not the same as errno!
+ hostent hentry;
+ ACE_HOSTENT_DATA buf;
+
+ char * ip_addr = 0;
+ int ip_addr_size = 0;
+ if (addr.get_type () == AF_INET)
+ {
+ sockaddr_in * const sock_addr =
+ reinterpret_cast<sockaddr_in *> (addr.get_addr ());
+ ip_addr_size = sizeof sock_addr->sin_addr;
+ ip_addr = (char*) &sock_addr->sin_addr;
+ }
+#ifdef ACE_HAS_IPV6
+ else
+ {
+ sockaddr_in6 * sock_addr =
+ reinterpret_cast<sockaddr_in6 *> (addr.get_addr ());
+
+ ip_addr_size = sizeof sock_addr->sin6_addr;
+ ip_addr = (char*) &sock_addr->sin6_addr;
+ }
+#endif /* ACE_HAS_IPV6 */
+
+ // get the host entry for the address in question
+ hostent * const hp = ACE_OS::gethostbyaddr_r (ip_addr,
+ ip_addr_size,
+ addr.get_type (),
+ &hentry,
+ buf,
+ &h_error);
+
+ // if it's not found in the host file or the DNS datase, there is nothing
+ // much we can do. embed the IP address
+ if (hp == 0 || hp->h_name == 0)
+ return -1;
+
+ if (ACE::debug())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
+ ACE_TEXT ("canonical host name is %C\n"),
+ hp->h_name));
+
+ // check if the canonical name is the FQDN
+ if (!ACE_OS::strchr(hp->h_name, '.'))
+ {
+ // list of address
+ char** p;
+ // list of aliases
+ char** q;
+
+ // for every address and for every alias within the address, check and
+ // see if we can locate a FQDN
+ for (p = hp->h_addr_list; *p != 0; ++p)
+ {
+ for (q = hp->h_aliases; *q != 0; ++q)
+ {
+ if (ACE_OS::strchr(*q, '.'))
+ {
+ // we got an FQDN from an alias. use this
+ if (ACE_OS::strlen (*q) >= len)
+ // the hostname is too huge to fit into a
+ // buffer of size MAXHOSTNAMELEN
+ // should we check other aliases as well
+ // before bailing out prematurely?
+ // for right now, let's do it. this (short name)
+ // is atleast better than embedding the IP
+ // address in the profile
+ continue;
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
+ ACE_TEXT ("found fqdn within alias as %C\n"),
+ *q));
+ ACE_OS::strcpy (hostname, *q);
+
+ return 0;
+ }
+ }
+ }
+ }
+
+ // The canonical name may be an FQDN when we reach here.
+ // Alternatively, the canonical name (a non FQDN) may be the best
+ // we can do.
+ if (ACE_OS::strlen (hp->h_name) >= len)
+ {
+ // The hostname is too large to fit into a buffer of size
+ // MAXHOSTNAMELEN.
+ return -2;
+ }
+ else
+ {
+ ACE_OS::strcpy (hostname, hp->h_name);
+ }
+
+ return 0;
+}
+
+#if defined (ACE_WIN32)
+
+static int
+get_ip_interfaces_win32 (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+# if defined (ACE_HAS_WINCE) && defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ // moved the ACE_HAS_WINCE impl ahaid of ACE_HAS_WINSOCK2 because
+ // WINCE in fact has winsock2, but doesn't properly support the
+ // WSAIoctl for obtaining IPv6 address info.
+ PIP_ADAPTER_ADDRESSES AdapterAddresses = 0;
+ ULONG OutBufferLength = 0;
+ ULONG RetVal = 0;
+ unsigned char *octet_buffer = 0;
+
+ RetVal =
+ GetAdaptersAddresses(AF_UNSPEC,
+ 0,
+ 0,
+ AdapterAddresses,
+ &OutBufferLength);
+
+ if (RetVal != ERROR_BUFFER_OVERFLOW)
+ {
+ return -1;
+ }
+
+ ACE_NEW_RETURN (octet_buffer, unsigned char[OutBufferLength],-1);
+ AdapterAddresses = (IP_ADAPTER_ADDRESSES *)octet_buffer;
+
+ RetVal =
+ GetAdaptersAddresses(AF_UNSPEC,
+ 0,
+ 0,
+ AdapterAddresses,
+ &OutBufferLength);
+
+ if (RetVal != NO_ERROR)
+ {
+ delete [] octet_buffer;
+ return -1;
+ }
+
+ // If successful, output some information from the data we received
+ PIP_ADAPTER_ADDRESSES AdapterList = AdapterAddresses;
+ while (AdapterList)
+ {
+ if (AdapterList->OperStatus == IfOperStatusUp)
+ {
+ if (AdapterList->IfIndex != 0)
+ ++count;
+ if (AdapterList->Ipv6IfIndex != 0)
+ ++count;
+ }
+ AdapterList = AdapterList->Next;
+ }
+
+ AdapterList = AdapterAddresses;
+
+ ACE_NEW_RETURN (addrs, ACE_INET_Addr[count],-1);
+ count = 0;
+ for (AdapterList = AdapterAddresses;
+ AdapterList != 0;
+ AdapterList = AdapterList->Next)
+ {
+ if (AdapterList->OperStatus != IfOperStatusUp)
+ continue;
+
+ IP_ADAPTER_UNICAST_ADDRESS *uni = 0;
+ if (AdapterList->IfIndex != 0)
+ for (uni = AdapterList->FirstUnicastAddress;
+ uni != 0;
+ uni = uni->Next)
+ {
+ SOCKET_ADDRESS *sa_addr = &uni->Address;
+ if (sa_addr->lpSockaddr->sa_family == AF_INET)
+ {
+ sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
+ addrs[count].set(sin,sa_addr->iSockaddrLength);
+ ++count;
+ break;
+ }
+ }
+ if (AdapterList->Ipv6IfIndex != 0)
+ {
+ for (uni = AdapterList->FirstUnicastAddress;
+ uni != 0;
+ uni = uni->Next)
+ {
+ SOCKET_ADDRESS *sa_addr = &uni->Address;
+ if (sa_addr->lpSockaddr->sa_family == AF_INET6)
+ {
+ sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
+ addrs[count].set(sin,sa_addr->iSockaddrLength);
+ ++count;
+ break;
+ }
+ }
+ }
+ }
+
+ delete [] octet_buffer;
+ return 0;
+
+# elif defined (ACE_HAS_PHARLAP)
+ // PharLap ETS has its own kernel routines to rummage through the device
+ // configs and extract the interface info, but only for Pharlap RT.
+# 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 = 0;
+ 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
+ // All non-CE, non-Pharlap Windows. Must support Winsock2.
+
+ 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);
+
+ // 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:-/
+ int n_v6_interfaces = 0;
+
+# if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
+
+ 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)
+ {
+ status = WSAIoctl(sock,
+ SIO_ADDRESS_LIST_QUERY,
+ 0,
+ 0,
+ v6info,
+ buflen,
+ &bytes,
+ 0,
+ 0);
+ closesocket (sock);
+ if (status != SOCKET_ERROR)
+ n_v6_interfaces = v6info->iAddressCount;
+ }
+# endif /* ACE_HAS_IPV6 */
+
+ ACE_NEW_RETURN (addrs,
+ ACE_INET_Addr[n_interfaces + n_v6_interfaces],
+ -1);
+
+ // 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) && defined (SIO_ADDRESS_LIST_QUERY)
+ // 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;
+
+# endif /* ACE_HAS_WINCE */
+}
+#elif defined (ACE_HAS_GETIFADDRS)
+static int
+get_ip_interfaces_getifaddrs (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ // Take advantage of the BSD getifaddrs function that simplifies
+ // access to connected interfaces.
+ struct ifaddrs *ifap = 0;
+ struct ifaddrs *p_if = 0;
+
+ 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 (__hpux)
+static int
+get_ip_interfaces_hpux (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ size_t num_ifs = 0;
+ size_t num_ifs_found = 0;
+
+ // Call specific routine as necessary.
+ ACE_HANDLE handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
+ ACE_HANDLE handle_ipv6 = ACE_INVALID_HANDLE;
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces:open")),
+ -1);
+
+ int result = 0;
+ int tmp_how_many = 0;
+
+ result = ACE_OS::ioctl (handle,
+ SIOCGIFNUM,
+ (caddr_t) &tmp_how_many);
+ if (result != -1)
+ num_ifs = (size_t)tmp_how_many;
+
+# if defined (ACE_HAS_IPV6)
+ tmp_how_many = 0;
+ handle_ipv6 = ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0);
+ result = ACE_OS::ioctl (handle_ipv6,
+ SIOCGLIFNUM,
+ (caddr_t) &tmp_how_many);
+ if (result != -1)
+ num_ifs += (size_t)tmp_how_many;
+# endif
+
+ if (num_ifs == 0)
+ {
+ ACE_OS::close (handle);
+ ACE_OS::close (handle_ipv6);
+ 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;
+
+ //HPUX requires two passes, First for IPv4, then for IPv6
+
+ 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);
+ ACE_OS::close (handle_ipv6);
+ 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 (ACE_OS::ioctl (handle,
+ SIOCGIFCONF,
+ (char *) &ifcfg) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces:")
+ ACE_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
+
+ for (size_t i = 0;
+ i < num_ifs_found;
+ i++)
+ {
+ struct sockaddr_in *addr =
+ reinterpret_cast<sockaddr_in *> (&pcur->ifr_addr);
+ if (addr->sin_addr.s_addr != 0)
+ {
+ addrs[count].set ((u_short) 0,
+ addr->sin_addr.s_addr,
+ 0);
+ ++count;
+ }
+ ++pcur;
+ }
+
+# if defined (ACE_HAS_IPV6)
+
+ if (handle_ipv6 != ACE_INVALID_HANDLE)
+ {
+ struct if_laddrreq *lifs = 0;
+ ACE_NEW_RETURN (lifs,
+ struct if_laddrreq[num_ifs],
+ -1);
+ ACE_OS::memset (lifs, 0, num_ifs * sizeof (struct if_laddrreq));
+
+ ACE_Auto_Array_Ptr<struct if_laddrreq> p_lifs (lifs);
+
+ if (p_lifs.get() == 0)
+ {
+ ACE_OS::close (handle);
+ ACE_OS::close (handle_ipv6);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ struct if_laddrconf lifcfg;
+ ACE_OS::memset (&lifcfg, 0, sizeof (struct if_laddrconf));
+
+ lifcfg.iflc_req = p_lifs.get ();
+ lifcfg.iflc_len = num_ifs * sizeof (struct if_laddrreq);
+
+ if (ACE_OS::ioctl (handle_ipv6,
+ SIOCGLIFCONF,
+ (char *) &lifcfg) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces:")
+ ACE_TEXT ("ioctl - SIOCGLIFCONF failed")),
+ -1);
+ }
+
+ ACE_OS::close (handle_ipv6);
+
+ struct if_laddrreq *plcur = p_lifs.get ();
+ num_ifs_found = lifcfg.iflc_len / sizeof (struct if_laddrreq);
+
+ for (size_t i = 0;
+ i < num_ifs_found;
+ i++)
+ {
+ struct sockaddr_in *addr =
+ reinterpret_cast<sockaddr_in *> (&plcur->iflr_addr);
+ if (!IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
+ {
+ addrs[count].set(addr, sizeof(struct sockaddr_in6));
+ ++count;
+ }
+ ++plcur;
+ }
+ }
+# endif /* ACE_HAS_IPV6 */
+ return 0;
+}
+#elif defined (_AIX)
+static int
+get_ip_interfaces_aix (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ ACE_HANDLE handle = ACE::get_handle();
+ size_t num_ifs = 0;
+ struct ifconf ifc;
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces_aix:")),
+ -1);
+
+ if (ACE_OS::ioctl (handle,
+ SIOCGSIZIFCONF,
+ (caddr_t)&ifc.ifc_len) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get ifconf size")),
+ -1);
+ }
+
+ ACE_NEW_RETURN (ifc.ifc_buf,char [ifc.ifc_len], -1);
+
+ ACE_Auto_Array_Ptr<char> safe_buf (ifc.ifc_buf);
+ ACE_OS::memset (safe_buf.get(), 0, ifc.ifc_len);
+
+ if (ACE_OS::ioctl(handle, SIOCGIFCONF, (caddr_t)&ifc) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get ifconf")),
+ -1);
+ }
+
+ ACE_OS::close (handle);
+
+ char *buf_start = safe_buf.get();
+ char *buf_end = buf_start + ifc.ifc_len;
+
+ num_ifs = 0;
+ for (char *ptr = buf_start; ptr < buf_end; )
+ {
+ struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
+ ptr += IFNAMSIZ;
+ ptr += req->ifr_addr.sa_len;
+ if (req->ifr_addr.sa_family == AF_INET
+# if defined (ACE_HAS_IPV6)
+ || req->ifr_addr.sa_family == AF_INET6
+# endif
+ )
+ ++num_ifs;
+ }
+ ACE_NEW_RETURN (addrs,ACE_INET_Addr[num_ifs], -1);
+
+ for (char * ptr = buf_start; ptr < buf_end; )
+ {
+ struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
+ // skip the interface name
+ ptr += IFNAMSIZ;
+ if (req->ifr_addr.sa_family == AF_INET
+# if defined (ACE_HAS_IPV6)
+ || req->ifr_addr.sa_family == AF_INET6
+# endif
+ )
+ {
+ sockaddr_in *addr = (sockaddr_in*)&req->ifr_addr;
+ addrs[count++].set(addr, addr->sin_len);
+ }
+ ptr += req->ifr_addr.sa_len;
+ }
+
+ return 0;
+}
+
+#elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600) && !defined (ACE_HAS_VXWORKS551_MEDUSA)
+int
+get_ip_interfaces_vxworks_lt600 (size_t &count,
+ ACE_INET_Addr *&addrs)
+{
+ count = 0;
+ // Loop through each address structure
+
+# if defined (ACE_HAS_IPV6) && defined (TAILQ_ENTRY)
+# define ia_next ia_link.tqe_next
+# endif /* TAILQ_ENTRY */
+
+ 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_TEXT ("ACE::get_ip_interface failed\n")
+ ACE_TEXT ("Couldnt get the IP Address\n")),
+ -1);
+ }
+ ++count;
+ }
+ }
+ return 0;
+}
+#endif // ACE_WIN32 || ACE_HAS_GETIFADDRS || __hpux || _AIX || ACE_VXWORKS < 0x600
+
+
+// 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)
+ return get_ip_interfaces_win32 (count, addrs);
+#elif defined (ACE_HAS_GETIFADDRS)
+ return get_ip_interfaces_getifaddrs (count, addrs);
+#elif defined (__hpux)
+ return get_ip_interfaces_hpux (count, addrs);
+#elif defined (_AIX)
+ return get_ip_interfaces_aix (count, addrs);
+#elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600) && !defined (ACE_HAS_VXWORKS551_MEDUSA)
+ return get_ip_interfaces_vxworks_lt600 (count, addrs);
+#elif (defined (__unix) || defined (__unix__) || defined (ACE_OPENVMS) || (defined (ACE_VXWORKS) && !defined (ACE_HAS_GETIFADDRS)) || defined (ACE_HAS_RTEMS)) && !defined (ACE_LACKS_NETWORKING)
+ // COMMON (SVR4 and BSD) UNIX CODE
+
+ // Call specific routine as necessary.
+ ACE_HANDLE handle = ACE::get_handle();
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces:open")),
+ -1);
+
+ size_t num_ifs = 0;
+
+ 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));
+
+# ifdef SETFAMILY
+ ifcfg.IFC_FAMILY = AF_UNSPEC; // request all families be returned
+ ifcfg.IFC_FLAGS = 0;
+# endif
+
+ ifcfg.IFC_REQ = p_ifs.get ();
+ ifcfg.IFC_LEN = num_ifs * sizeof (struct IFREQ);
+
+ if (ACE_OS::ioctl (handle,
+ SIOCGIFCONF_CMD,
+ (caddr_t) &ifcfg) == -1)
+ {
+ ACE_OS::close (handle);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::get_ip_interfaces:")
+ ACE_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 ();
+ size_t 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 (ACE_HAS_IPV6)
+ || pcur->IFR_ADDR.SA_FAMILY == AF_INET6
+# endif
+ )
+
+ {
+# if !defined(_UNICOS)
+ struct sockaddr_in *addr =
+ reinterpret_cast<sockaddr_in *> (&pcur->IFR_ADDR);
+
+ // Sometimes the kernel returns 0.0.0.0 as an IPv4 interface
+ // address; skip those...
+ if (addr->sin_addr.s_addr != 0
+# if defined (ACE_HAS_IPV6)
+ || (addr->sin_family == AF_INET6 &&
+ !IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
+# endif
+ )
+ {
+ int addrlen = static_cast<int> (sizeof (struct sockaddr_in));
+# if defined (ACE_HAS_IPV6)
+ if (addr->sin_family == AF_INET6)
+ addrlen = static_cast<int> (sizeof (struct sockaddr_in6));
+# endif
+ addrs[count].set (addr, addrlen);
+ ++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 (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS) && !defined (__Lynx__)
+ ++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 (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS) && !defined (__Lynx__) */
+ }
+
+# 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 = 0;
+ 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_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
+ {
+ 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;
+#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 (SIOCGIFNUM)
+# if defined (SIOCGLIFNUM) && !defined (ACE_LACKS_STRUCT_LIFNUM)
+ int cmd = SIOCGLIFNUM;
+ struct lifnum if_num = {AF_UNSPEC,0,0};
+# else
+ int cmd = SIOCGIFNUM;
+ int if_num = 0;
+# endif /* SIOCGLIFNUM */
+ if (ACE_OS::ioctl (handle, cmd, (caddr_t)&if_num) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::count_interfaces:")
+ ACE_TEXT ("ioctl - SIOCGLIFNUM failed")),
+ -1);
+# if defined (SIOCGLIFNUM) && !defined (ACE_LACKS_STRUCT_LIFNUM)
+ how_many = if_num.lifn_count;
+# else
+ how_many = if_num;
+# endif /* SIOCGLIFNUM */
+return 0;
+
+#elif (defined (__unix) || defined (__unix__) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS) || (defined (ACE_VXWORKS) && !defined (ACE_HAS_GETIFADDRS))) && !defined (ACE_LACKS_NETWORKING)
+ // 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..
+ int const MAX_IF = 50;
+
+ // HACK - set to an unreasonable number
+ int const 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 (ACE_OS::ioctl (handle,
+ SIOCGIFCONF_CMD,
+ (caddr_t) &ifcfg) == -1)
+ {
+ ACE_OS::free (ifcfg.ifc_req);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::count_interfaces:")
+ ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
+ -1);
+ }
+
+ int if_count = 0;
+ int i = 0;
+
+ // 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 (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS) && !defined (__Lynx__)
+ ++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 (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS) && !defined (__Lynx__)*/
+ }
+
+ ACE_OS::free (ifcfg.ifc_req);
+
+# if defined (ACE_HAS_IPV6)
+ FILE* fp = 0;
+
+ if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
+ {
+ // 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 (_AIX) || defined (__hpux) || (defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS)
+ // 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;
+}
+
+
+#if defined (ACE_HAS_IPV6)
+static int
+ip_check (int &ipvn_enabled, int pf)
+{
+ // We only get to this point if ipvn_enabled was -1 in the caller.
+ // Perform Double-Checked Locking Optimization.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+
+ if (ipvn_enabled == -1)
+ {
+ // Determine if the kernel has IPv6 support by attempting to
+ // create a PF_INET socket and see if it fails.
+ ACE_HANDLE const s = ACE_OS::socket (pf, SOCK_DGRAM, 0);
+ if (s == ACE_INVALID_HANDLE)
+ {
+ ipvn_enabled = 0;
+ }
+ else
+ {
+ ipvn_enabled = 1;
+ ACE_OS::closesocket (s);
+ }
+ }
+ return ipvn_enabled;
+}
+#endif /* ACE_HAS_IPV6 */
+
+bool
+ACE::ipv4_enabled (void)
+{
+#if defined (ACE_HAS_IPV6)
+ return static_cast<bool> (ace_ipv4_enabled == -1 ?
+ ::ip_check (ace_ipv4_enabled, PF_INET) :
+ ace_ipv4_enabled);
+#else
+ // Assume it's always enabled since ACE requires some version of
+ // TCP/IP to exist.
+ return true;
+#endif /* ACE_HAS_IPV6*/
+}
+
+int
+ACE::ipv6_enabled (void)
+{
+#if defined (ACE_HAS_IPV6)
+ return ace_ipv6_enabled == -1 ?
+ ::ip_check (ace_ipv6_enabled, PF_INET6) :
+ ace_ipv6_enabled;
+#else /* ACE_HAS_IPV6 */
+ return 0;
+#endif /* !ACE_HAS_IPV6 */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL