diff options
author | Johnny Willemsen <jwillemsen@remedy.nl> | 2006-08-23 08:25:34 +0000 |
---|---|---|
committer | Johnny Willemsen <jwillemsen@remedy.nl> | 2006-08-23 08:25:34 +0000 |
commit | 0511e6ca049601b0cb6349c18cc37bd79c2607f6 (patch) | |
tree | b9cf14265033138894926868aefec5c84d22cae4 | |
parent | 94e66778a3f8122104775aea98e25794ba800e56 (diff) | |
download | ATCD-0511e6ca049601b0cb6349c18cc37bd79c2607f6.tar.gz |
reverted changes of Phil
-rw-r--r-- | ACE/ace/Sock_Connect.cpp | 1474 | ||||
-rw-r--r-- | ACE/ace/Sock_Connect.h | 9 |
2 files changed, 615 insertions, 868 deletions
diff --git a/ACE/ace/Sock_Connect.cpp b/ACE/ace/Sock_Connect.cpp index a975ad0f98b..215f997675f 100644 --- a/ACE/ace/Sock_Connect.cpp +++ b/ACE/ace/Sock_Connect.cpp @@ -26,21 +26,21 @@ #endif /* ACE_HAS_IPV6 */ # if defined (ACE_HAS_GETIFADDRS) -# include /**/ <ifaddrs.h> +# if defined (ACE_VXWORKS) +# include /**/ <net/ifaddrs.h> +# else +# include /**/ <ifaddrs.h> +# endif # endif /* ACE_HAS_GETIFADDRS */ -#if defined (_AIX) && defined (ACE_HAS_IPV6) -# include /**/ <netinet/in6_var.h> -#endif /* _AIX */ - -#if defined (VXWORKS) +#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 /* VXWORKS */ +#endif /* ACE_VXWORKS < 0x600 */ #if defined (ACE_HAS_WINCE) #include /**/ <Iphlpapi.h> @@ -60,9 +60,6 @@ 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; } @@ -84,9 +81,10 @@ ACE_RCSID (ace, "$Id$") -#if defined (ACE_WIN32) -# if (!defined (ACE_HAS_WINSOCK2) \ +#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, @@ -276,26 +274,293 @@ get_windows_version() } } -# endif // !(ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 0) +#endif //(ACE_WIN32) && !(ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 0) -static int -get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) +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 n_interfaces = 0; - int i, status; + int i, n_interfaces, status; INTERFACE_INFO info[64]; SOCKET sock; - DWORD bytes; // Get an (overlapped) DGRAM socket to test with sock = socket (AF_INET, SOCK_DGRAM, 0); - if (sock != INVALID_SOCKET) - { - status = WSAIoctl(sock, + if (sock == INVALID_SOCKET) + return -1; + + DWORD bytes; + status = WSAIoctl(sock, SIO_GET_INTERFACE_LIST, 0, 0, @@ -304,17 +569,18 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) &bytes, 0, 0); - closesocket (sock); - if (status != SOCKET_ERROR) - { - n_interfaces = bytes / sizeof(INTERFACE_INFO); - } - } + closesocket (sock); + if (status == SOCKET_ERROR) + return -1; + + n_interfaces = bytes / sizeof(INTERFACE_INFO); + if (n_interfaces == 0) + return 0; -# if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY) // 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; @@ -328,10 +594,13 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) // 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) + if (sock == INVALID_SOCKET) { + delete [] buffer; + return -1; + } - status = WSAIoctl(sock, + status = WSAIoctl(sock, SIO_ADDRESS_LIST_QUERY, 0, 0, @@ -340,20 +609,23 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) &bytes, 0, 0); - closesocket (sock); - if (status != SOCKET_ERROR) - { - n_v6_interfaces = v6info->iAddressCount; - } - } + 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 */ +# else /* ACE_HAS_IPV6 */ ACE_NEW_RETURN (addrs, ACE_INET_Addr[n_interfaces], -1); -# endif /* !ACE_HAS_IPV6 */ +# 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. @@ -376,7 +648,7 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) ++count; } -# if defined (ACE_HAS_IPV6) +# 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++) @@ -396,7 +668,7 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) } delete [] buffer; // Clean up -# endif /* ACE_HAS_IPV6 */ +# endif /* ACE_HAS_IPV6 */ if (count == 0) { @@ -406,7 +678,7 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) return 0; -# else /* Winsock 2 && MSVC 5 or later */ +#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 @@ -429,7 +701,7 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) ACE_TCHAR dev_name[16]; count = 0; - for (i = 0; count < ACE_MAX_ETS_DEVICES; ++i, ++count) + for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count) { // Ethernet. ACE_OS::sprintf (dev_name, @@ -439,7 +711,7 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) if (ip_dev[count] == 0) break; } - for (i = 0; count < ACE_MAX_ETS_DEVICES; ++i, ++count) + for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count) { // SLIP. ACE_OS::sprintf (dev_name, @@ -449,7 +721,7 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) if (ip_dev[count] == 0) break; } - for (i = 0; count < ACE_MAX_ETS_DEVICES; ++i, ++count) + for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count) { // PPP. ACE_OS::sprintf (dev_name, @@ -467,7 +739,7 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) else addrs = 0; - for (i = 0, j = 0; i < count; ++i) + for (i = 0, j = 0; i < count; i++) { devp = EtsTCPGetDeviceCfg (ip_dev[i]); if (devp != 0) @@ -475,7 +747,7 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) addrs[j].set (0, devp->nwIPAddress, 0); // Already in net order. - ++j; + j++; } // There's no call to close the DEVHANDLE. } @@ -722,7 +994,7 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) DWORD buf_len = ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 1; count = 0; - for (int i = 0; i < n_interfaces; ++i) + for (int i = 0; i < n_interfaces; i++) { for (const ACE_TCHAR **ipaddr_name_id = IPADDR_NAME_ID; *ipaddr_name_id != 0; @@ -765,126 +1037,96 @@ get_ip_interfaces_win32 (size_t& count, ACE_INET_Addr *&addrs) return 0; # endif /* ACE_HAS_PHARLAP */ # endif /* Winsock 2 && MSVC 5 or later */ -} -//#endif /* ACE_WIN32 */ -#elif defined (_AIX) - -static int -get_ip_interfaces_aix (size_t& count, ACE_INET_Addr *&addrs) -{ - size_t num_ifs; - ACE_HANDLE handle = - ACE_OS::socket ( -#if defined (ACE_HAS_IPV6) - PF_INET6, -#else - PF_INET, -#endif /* ACE_HAS_IPV6 */ - SOCK_DGRAM, 0); - if (handle == ACE_INVALID_HANDLE) - ACE_ERROR_RETURN ((LM_ERROR, - ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("ACE::get_ip_interfaces:open")), - -1); +#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; - struct ifconf ifc; + if (::getifaddrs (&ifap) != 0) + return -1; - if (ACE_OS::ioctl (handle, - SIOCGSIZIFCONF, - (caddr_t)&ifc.ifc_len) == -1) - { - ACE_OS::close (handle); - ACE_ERROR_RETURN((LM_ERROR, - ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("get ifconf size")), - -1); - } - num_ifs = (ifc.ifc_len - sizeof (int)) / sizeof (in6_ifreq); - ACE_NEW_RETURN (ifc.ifc_buf,char [ifc.ifc_len], -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; - ACE_Auto_Array_Ptr<char> safe_buf (ifc.ifc_buf); - ACE_OS::memset (safe_buf.get(), 0, ifc.ifc_len); + // Now create and initialize output array. + ACE_NEW_RETURN (addrs, + ACE_INET_Addr[num_ifs], + -1); // caller must free - if (ACE_OS::ioctl(handle, CSIOCGIFCONF, (caddr_t)&ifc) == -1) - { - ACE_OS::close (handle); - ACE_ERROR_RETURN((LM_ERROR, - ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("get ifconf")), - -1); - } + // 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; - char *ptr = safe_buf.get(); + 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); - num_ifs = ifc.ifc_len / sizeof(ifreq); - ACE_NEW_RETURN (addrs,ACE_INET_Addr[num_ifs], -1); + // 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); - for (int i = 0; i < num_ifs && ifc.ifc_len > 0; ++i) - { - struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr); -# if defined ACE_HAS_IPV6 - if (req->ifr_addr.sa_family == AF_INET6) - { - in6_ifreq req6; - ACE_OS::strcpy (req6.ifr_name, req->ifr_name); - ACE_OS::ioctl (handle,SIOCGIFADDR6,(caddr_t)&req6); - sockaddr_in *addr = (sockaddr_in *)&req6.ifr_Addr; - addrs[count++].set(addr, sizeof (req6.ifr_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 */ - if (req->ifr_addr.sa_family == AF_INET) - { - sockaddr_in *addr = (sockaddr_in*)&req->ifr_addr; - addr->sin_family = AF_INET; - addr->sin_len = sizeof (req->ifr_addr); - addrs[count++].set(addr, addr->sin_len); - } - // else no-op. CSIOCGIFCONF also returns AF_LINK entries, but - // we don't use those. + } - ptr += sizeof(ifreq); - ifc.ifc_len -= sizeof(ifreq); - } + ::freeifaddrs (ifap); return 0; -} -//#endif /* _AIX */ -#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; + +#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 = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0); - ACE_HANDLE handle_ipv6 = -#if defined (ACE_HAS_IPV6) - ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0); -#else - ACE_INVALID_HANDLE; -#endif /* ACE_HAS_IPV6 */ + 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; + } - int tmp_how_many = 0; - if (ACE_OS::ioctl (handle, - SIOCGIFNUM, - (caddr_t) &tmp_how_many) != -1) - num_ifs = (size_t)tmp_how_many; - - tmp_how_many = 0; - if (ACE_OS::ioctl (handle_ipv6, - SIOCGLIFNUM, - (caddr_t) &tmp_how_many) != -1) - num_ifs += (size_t)tmp_how_many; - - //HPUX requires two passes, First for IPv4, then for IPv6 + // 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, @@ -897,20 +1139,23 @@ get_ip_interfaces_hpux (size_t& count, ACE_INET_Addr *&addrs) 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 defined (AIX) + int cmd = CSIOCGIFCONF; +#else + int cmd = SIOCGIFCONF; +#endif /* AIX */ if (ACE_OS::ioctl (handle, - SIOCGIFCONF, - (char *) &ifcfg) == -1) + cmd, + (caddr_t) &ifcfg) == -1) { ACE_OS::close (handle); ACE_ERROR_RETURN ((LM_ERROR, @@ -931,84 +1176,115 @@ get_ip_interfaces_hpux (size_t& count, ACE_INET_Addr *&addrs) 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) - - 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); + // 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; - if (p_lifs.get() == 0) + for (size_t i = 0; + i < num_ifs_found; + i++) { - ACE_OS::close (handle); - ACE_OS::close (handle_ipv6); - errno = ENOMEM; - return -1; - } + if (pcur->ifr_addr.sa_family == AF_INET) + { +#if !defined(_UNICOS) + struct sockaddr_in *addr = + reinterpret_cast<sockaddr_in *> (&pcur->ifr_addr); - struct if_laddrconf lifcfg; - ACE_OS::memset (&lifcfg, 0, sizeof (struct if_laddrconf)); + // 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 */ + } - lifcfg.iflc_req = p_lifs.get (); - lifcfg.iflc_len = num_ifs * sizeof (struct if_laddrreq); +#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 (ACE_OS::ioctl (handle_ipv6, - SIOCGLIFCONF, - (char *) &lifcfg) == -1) +# 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) { - 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 - SIOCGLIFCONF failed")), - -1); - } + 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(). - ACE_OS::close (handle_ipv6); + 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); - struct if_laddrreq *plcur = p_lifs.get (); - num_ifs_found = lifcfg.iflc_len / sizeof (struct if_laddrreq); + error = getaddrinfo (s_ipaddr, 0, &hints, &res0); + if (error) + continue; - 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; - } + 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; -} - -//#endif /* __hpux */ -#elif defined (VXWORKS) - -static int -get_ip_interfaces_vxworks (size_t& count, ACE_INET_Addr *&addrs) -{ +#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) { @@ -1054,15 +1330,35 @@ get_ip_interfaces_vxworks (size_t& count, ACE_INET_Addr *&addrs) } } return 0; +#else + ACE_UNUSED_ARG (count); + ACE_UNUSED_ARG (addrs); + ACE_NOTSUP_RETURN (-1); // no implementation +#endif /* ACE_WIN32 */ } -//#endif /* VXWORKS */ -#elif defined (ACE_HAS_GETIFADDRS) -static int -get_ip_interfaces_getifaddrs (size_t& count, ACE_INET_Addr *&addrs) +// 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) { - // Take advantage of the BSD getifaddrs function that simplifies - // access to connected interfaces. +#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; @@ -1074,679 +1370,108 @@ get_ip_interfaces_getifaddrs (size_t& count, ACE_INET_Addr *&addrs) 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); + how_many = num_ifs; return 0; -} -//#endif /* ACE_HAS_GETIFADDRS */ -#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) - -// These defines support a generic usage based on -// the various SIGCF*IF ioctl implementations - -# if defined (SIOCGLIFCONF) -# 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 -# define GET_IFCONF_CMD SIOCGLIFCONF -# define GET_NUM_IF_CMD SIOCGLIFNUM -# else -# 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 -# define GET_IFCONF_CMD SIOCGIFCONF -# define GET_NUM_IF_CMD SIOCGIFNUM -# endif - -static int -get_ip_interfaces_ioctl (size_t &count, ACE_INET_Addr *&addrs) -{ - // COMMON (SVR4 and BSD) UNIX CODE - - size_t num_ifs = 0; - size_t num_ifs_found = 0; - - // Call specific routine as necessary. - ACE_HANDLE handle = ACE::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 defined (SIOCGIFNUM) -# if defined (sparc) - struct lifnum if_num; - ACE_OS::memset (&if_num, 0, sizeof (struct lifnum)); - if_num.lifn_family = AF_UNSPEC; -# else - int if_num; -# endif /* sparc */ - if (ACE_OS::ioctl (handle, - GET_NUM_IF_CMD, - &if_num) == -1) - { - ACE_OS::close (handle); - ACE_ERROR_RETURN ((LM_ERROR, - ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("ACE::count_interfaces:") - ACE_LIB_TEXT ("ioctl - SIOCGLIFNUM failed")), - -1); - } -# if defined (sparc) - num_ifs = if_num.lifn_count; -# else - num_ifs = (size_t) if_num; -# endif /* sparc */ - - // 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; - int pass = 1; -#else - // we lack SIOCGIFNOUM, so two passes through the buffer are required - int pass = 2; +#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 size_t MAX_IF = 50; + const int MAX_IF = 50; // HACK - set to an unreasonable number - num_ifs = MAX_IF; + int num_ifs = MAX_IF; -#endif /* SIOCGIFNUM */ - 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); + 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.get() == 0) + if (!p_ifs) { - 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 + ACE_OS::memset (p_ifs, 0, ifreq_size); + ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf)); - ifcfg.IFC_REQ = p_ifs.get (); - ifcfg.IFC_LEN = num_ifs * sizeof (struct IFREQ); + 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, - GET_IFCONF_CMD, - (char *) &ifcfg) == -1) + cmd, + (caddr_t) &ifcfg) == -1) { - ACE_OS::close (handle); + ACE_OS::free (ifcfg.ifc_req); ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("ACE::get_ip_interfaces:") + ACE_LIB_TEXT ("ACE::count_interfaces:") ACE_LIB_TEXT ("ioctl - SIOCGIFCONF failed")), -1); } - ACE_OS::close (handle); + int if_count = 0, i; - num_ifs_found = ifcfg.IFC_LEN / sizeof (struct IFREQ); // get the number of returned ifs - - while (pass > 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++) { - if (pass == 1) - // 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_found; ++i) - { -# if defined (ACE_HAS_IPV6) - if (pcur->IFR_ADDR.SA_FAMILY == AF_INET6) - { - struct sockaddr_in *addr = - reinterpret_cast<sockaddr_in *> (&pcur->IFR_ADDR); - if (!IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr)) - { - if (pass == 1) - addrs[count].set(addr, sizeof(struct sockaddr_in6)); - ++count; - } - } -# endif /* ACE_HAS_IPV6 */ - 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) - { - if (pass == 1) - 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) - { - if (pass == 1) - addrs[count].set(&inAddr, sizeof(struct sockaddr_in)); - ++count; - } -# endif /* ! _UNICOS */ - } - -# if !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 (__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) - { - if (pass == 2) - { - ++count; - continue; - } - // Format the address into a 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 */ - --pass; - // when using the two-pass method, reset the number of interfaces here - // so that the correct size for the addrs array is used. - num_ifs = count; - } - return 0; -} -#endif /* __unix, __unix__, __Lynx__ */ - -#if defined (ACE_HAS_IPV6) -static int -ip_check (int &guard_value, int pf) -{ - if (guard_value == -1) - { - // Perform Double-Checked Locking Optimization. - ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, - *ACE_Static_Object_Lock::instance (), 0)); - - if (guard_value == -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) - { - guard_value = 0; - } - else - { -#if defined (ACE_HAS_WINCE) - if (pf == PF_INET6) - { - // it seems that ws2.lib does not initialize the values of - // in6addr_any and in6addr_loopback. So we do it here for - // now. - in6_addr any = IN6ADDR_ANY_INIT; - in6_addr loopback = IN6ADDR_LOOPBACK_INIT; - *(const_cast<in6_addr *>(&in6addr_any)) = any; - *(const_cast<in6_addr *>(&in6addr_loopback)) = loopback; - } -#endif /* ACE_HAS_WINCE */ - guard_value = 1; - ACE_OS::closesocket (s); - } - } - } - - return guard_value; -} -#endif /* ACE_HAS_IPV6 */ - -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 */ + /* In OpenBSD, the length of the list is returned. */ + ifcfg.ifc_len -= sizeof (struct ifreq); + if (ifcfg.ifc_len < 0) + break; -#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()); + if_count++; +#if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) + p_ifs++; #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; - } - } + 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__) */ } -#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)); + ACE_OS::free (ifcfg.ifc_req); - 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 (ACE_HAS_IPV6) + FILE* fp; -# 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__) */ + if ((fp = ACE_OS::fopen (ACE_LIB_TEXT ("/proc/net/if_inet6"), ACE_LIB_TEXT ("r"))) != NULL) { - 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) + // 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) { - ACE_ERROR ((LM_ERROR, - ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("ACE::get_bcast_addr:") - ACE_LIB_TEXT ("Not AF_INET"))); - continue; + if_count++; } - - 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; + ACE_OS::fclose (fp); } +# endif /* ACE_HAS_IPV6 */ + how_many = if_count; 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_HAS_GETIFADDRS) - - return ::get_ip_interfaces_getifaddrs (count, addrs); - -#elif defined (ACE_WIN32) - - return ::get_ip_interfaces_win32 (count, addrs); - -#elif defined (__hpux) - - return ::get_ip_interfaces_hpux (count, addrs); - -#elif defined (VXWORKS) - - return ::get_ip_interfaces_vxworks (count, addrs); - -#elif defined (_AIX) - - return ::get_ip_interfaces_aix (count, addrs); - -#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) - - return ::get_ip_interfaces_ioctl (count, addrs); - -#else - ACE_NOTSUP_RETURN (-1); // no implementation -#endif /* ACE_HAS_GETIFADDRS */ + 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. @@ -1758,32 +1483,47 @@ ACE::get_handle (void) ACE_HANDLE handle = ACE_INVALID_HANDLE; #if defined (sparc) handle = ACE_OS::open ("/dev/udp", O_RDONLY); -#elif defined (__unix) || defined (__unix__) || defined (__Lynx__) +#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::ipv4_enabled (void) -{ -#if defined (ACE_HAS_IPV6) - return ::ip_check (ace_ipv4_enabled, PF_INET); -#endif /* ACE_HAS_IPV6*/ - // Assume it's always enabled since ACE requires some version of - // TCP/IP to exist. - return 1; -} int ACE::ipv6_enabled (void) { #if defined (ACE_HAS_IPV6) - return ::ip_check (ace_ipv6_enabled, PF_INET6); -#endif /* !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 diff --git a/ACE/ace/Sock_Connect.h b/ACE/ace/Sock_Connect.h index 24e94ecbd7f..2df0ec90d21 100644 --- a/ACE/ace/Sock_Connect.h +++ b/ACE/ace/Sock_Connect.h @@ -61,6 +61,14 @@ namespace ACE extern ACE_Export int get_ip_interfaces (size_t &count, ACE_INET_Addr *&addr_array); + /** + * 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. + */ + extern ACE_Export int count_interfaces (ACE_HANDLE handle, + size_t &how_many); + /// Routine to return a handle from which @c ioctl requests can be /// made. Caller must close the handle. extern ACE_Export ACE_HANDLE get_handle (void); @@ -73,7 +81,6 @@ namespace ACE * returning 1 if it succeeds, and 0 if it fails. Caches the result * so it only gets checked once. */ - extern ACE_Export int ipv4_enabled (void); extern ACE_Export int ipv6_enabled (void); } |