diff options
Diffstat (limited to 'ace/Sock_Connect.cpp')
-rw-r--r-- | ace/Sock_Connect.cpp | 1367 |
1 files changed, 0 insertions, 1367 deletions
diff --git a/ace/Sock_Connect.cpp b/ace/Sock_Connect.cpp deleted file mode 100644 index ba7b8900669..00000000000 --- a/ace/Sock_Connect.cpp +++ /dev/null @@ -1,1367 +0,0 @@ -// $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_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) -# include /**/ <ifaddrs.h> -# endif /* ACE_HAS_GETIFADDRS */ - -#if defined (VXWORKS) -#include /**/ <inetLib.h> -#include /**/ <netinet/in_var.h> -extern "C" { - extern struct in_ifaddr* in_ifaddr; -} -#endif /* VXWORKS */ - -#if defined (ACE_HAS_WINCE) -#include /**/ <Iphlpapi.h> -#endif // ACE_HAS_WINCE - -#if defined (ACE_HAS_IPV6) -# if defined (ACE_HAS_THREADS) -# include "ace/Object_Manager.h" -# endif /* ACE_HAS_THREADS */ - -// Whether or not ipv6 is turned on in this box -int ACE_Sock_Connect::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) -# if (__IBMCPP__ >= 700) -# error Recheck this hack to see if version 7 fixed it! -# endif -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) - -// Bind socket to an unused port. - -int -ACE_Sock_Connect::bind_port (ACE_HANDLE handle, - ACE_UINT32 ip_addr, - int address_family) -{ - ACE_TRACE ("ACE_Sock_Connect::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_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_Sock_Connect::get_bcast_addr (ACE_UINT32 &bcast_addr, - const ACE_TCHAR *host_name, - ACE_UINT32 host_addr, - ACE_HANDLE handle) -{ - ACE_TRACE ("ACE_Sock_Connect::get_bcast_addr"); - -#if !defined(ACE_WIN32) - 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_Sock_Connect::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 (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(CHORUS_4) && !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) - 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(CHORUS_4) && !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) */ - { - 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_Sock_Connect::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_Sock_Connect::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_Sock_Connect::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_Sock_Connect::get_bcast_addr:") - ACE_LIB_TEXT ("ioctl (get broadaddr)"))); - else - { - ACE_OS::memcpy (ACE_reinterpret_cast(sockaddr_in *, &ip_addr), - ACE_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_Sock_Connect::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 */ -} - -// 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_Sock_Connect::get_ip_interfaces (size_t &count, - ACE_INET_Addr *&addrs) -{ - ACE_TRACE ("ACE_Sock_Connect::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; - - ACE_NEW_RETURN (addrs, - ACE_INET_Addr[n_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; - - lpii = &info[i]; - if (!(lpii->iiFlags & IFF_UP)) - continue; - - // We assume IPv4 addresses here - addrp = ACE_reinterpret_cast(struct sockaddr_in *, &(lpii->iiAddress)); - if (addrp->sin_addr.s_addr == INADDR_ANY) - continue; - - // Set the address for the caller. - addrs[count].set(addrp, sizeof(sockaddr_in)); - ++count; - } - - 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_Sock_Connect::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_Sock_Connect::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_Sock_Connect::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_Sock_Connect::get_ip_interfaces - "), - ACE_LIB_TEXT ("Invalid parameter.")), - -1); - break; - - default: - ACE_ERROR_RETURN ((LM_ERROR, - ACE_LIB_TEXT ("%p\nACE_Sock_Connect::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 = - ACE_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 != 0) - { - addrs[count].set ((u_short) 0, - addr->sin_addr.s_addr, - 0); - count++; - } - } - } - - ::freeifaddrs (ifap); - - return 0; - -#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) - // COMMON (SVR4 and BSD) UNIX CODE - - size_t num_ifs; - - // 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_Sock_Connect::get_ip_interfaces:open")), - -1); - if (ACE_Sock_Connect::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_Sock_Connect::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 (); - // 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; - i++) - { - if (pcur->ifr_addr.sa_family == AF_INET) - { -#if !defined(_UNICOS) - struct sockaddr_in *addr = - ACE_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(CHORUS_4) && !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) - 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(CHORUS_4) && !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) */ - } - return 0; -#elif defined (VXWORKS) - 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_Sock_Connect::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_Sock_Connect::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) - // 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_Sock_Connect::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(CHORUS_4) && !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) - 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(CHORUS_4) && !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) */ - } - - ACE_OS::free (ifcfg.ifc_req); - how_many = if_count; - return 0; -#else - ACE_UNUSED_ARG (handle); - ACE_UNUSED_ARG (how_many); - ACE_NOTSUP_RETURN (-1);; // no implmentation -#endif /* sparc && SIOCGIFNUM */ -} - -// Routine to return a handle from which ioctl() requests can be made. - -ACE_HANDLE -ACE_Sock_Connect::get_handle (void) -{ - // Solaris 2.x - ACE_HANDLE handle = ACE_INVALID_HANDLE; -#if defined (sparc) && ! defined (CHORUS) - handle = ACE_OS::open ("/dev/udp", O_RDONLY); -#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) - // 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_Sock_Connect::ipv6_enabled (void) -{ -#if defined (ACE_HAS_IPV6) - if (ACE_Sock_Connect::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_Sock_Connect::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_Sock_Connect::ipv6_enabled_ = 0; - } - else - { - ACE_Sock_Connect::ipv6_enabled_ = 1; - ACE_OS::closesocket (s); - } - } - } - - return ACE_Sock_Connect::ipv6_enabled_; -#else - return 0; -#endif /* ACE_HAS_IPV6 */ -} - -#if defined (__unix) || defined (__unix__) || defined (__Lynx__) || \ - defined (_AIX) -# if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Auto_Array_Ptr<struct ifreq>; -template class ACE_Auto_Basic_Array_Ptr<struct ifreq>; -# elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Auto_Array_Ptr<struct ifreq> -#pragma instantiate ACE_Auto_Basic_Array_Ptr<struct ifreq> -# endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ -#endif /* (__unix || __Lynx_ || AIX ) */ |