Sock_Connect.cpp

Go to the documentation of this file.
00001 // $Id: Sock_Connect.cpp 81696 2008-05-14 18:15:31Z johnnyw $
00002 
00003 #include "ace/Sock_Connect.h"
00004 #include "ace/INET_Addr.h"
00005 #include "ace/Log_Msg.h"
00006 #include "ace/Handle_Set.h"
00007 #include "ace/Auto_Ptr.h"
00008 #include "ace/SString.h"
00009 #include "ace/OS_Memory.h"
00010 #include "ace/OS_NS_stdio.h"
00011 #include "ace/ACE.h"
00012 
00013 #if defined (sparc)
00014 #  include "ace/OS_NS_fcntl.h"
00015 #endif  // sparc
00016 
00017 #include "ace/OS_NS_stdlib.h"
00018 #include "ace/OS_NS_string.h"
00019 #include "ace/OS_NS_sys_socket.h"
00020 #include "ace/OS_NS_netdb.h"
00021 #include "ace/OS_NS_unistd.h"
00022 #include "ace/os_include/net/os_if.h"
00023 
00024 #if defined (ACE_HAS_IPV6)
00025 #  include "ace/Guard_T.h"
00026 #  include "ace/Recursive_Thread_Mutex.h"
00027 # if defined (_AIX)
00028 #  include /**/ <netinet/in6_var.h>
00029 # endif /* _AIX */
00030 #endif /* ACE_HAS_IPV6 */
00031 
00032 # if defined (ACE_HAS_GETIFADDRS)
00033 #   if defined (ACE_VXWORKS)
00034 #     include /**/ <net/ifaddrs.h>
00035 #   else
00036 #     include /**/ <ifaddrs.h>
00037 #   endif /*ACE_VXWORKS */
00038 # endif /* ACE_HAS_GETIFADDRS */
00039 
00040 #if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
00041 #include /**/ <inetLib.h>
00042 #include /**/ <netinet/in_var.h>
00043 #if defined (ACE_HAS_IPV6)
00044 #include /**/ <ifLib.h>
00045 extern "C" {
00046   extern struct in_ifaddr* in_ifaddr;
00047   extern LIST_HEAD(in_ifaddrhashhead, in_ifaddr) *in_ifaddrhashtbl;
00048 }
00049 #endif /* ACE_HAS_IPV6 */
00050 #include "ace/OS_NS_stdio.h"
00051 #endif /* ACE_VXWORKS < 0x600 */
00052 
00053 #if defined (ACE_VXWORKS) && ((ACE_VXWORKS == 0x630) || (ACE_VXWORKS == 0x640)) && defined (__RTP__) && defined (ACE_HAS_IPV6)
00054 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
00055 const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
00056 const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
00057 const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
00058 #endif /* ACE_VXWORKS == 0x630 && __RTP__ && ACE_HAS_IPV6 */
00059 
00060 #if defined (ACE_HAS_WINCE)
00061 #include /**/ <Iphlpapi.h>
00062 // The following code is suggested by microsoft as a workaround to the fact
00063 // that on Windows CE, these constants are exported as function addresses
00064 // rather than simply values.
00065 #  include /**/ <ws2tcpip.h>
00066 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
00067 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
00068 #endif  // ACE_HAS_WINCE
00069 
00070 #if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
00071 # include "ace/OS_NS_stdio.h"
00072 #endif
00073 
00074 #if defined (ACE_HAS_IPV6)
00075 
00076 // These defines support a generic usage based on
00077 // the various SIGCF*IF ioctl implementations
00078 
00079 # if defined (SIOCGLIFCONF)
00080 #  define SIOCGIFCONF_CMD SIOCGLIFCONF
00081 #  if defined (__hpux)
00082 #   define IFREQ if_laddrreq
00083 #   define IFCONF if_laddrconf
00084 #   define IFC_REQ iflc_req
00085 #   define IFC_LEN iflc_len
00086 #   define IFC_BUF iflc_buf
00087 #   define IFR_ADDR iflr_addr
00088 #   define IFR_NAME iflr_name
00089 #   define IFR_FLAGS iflr_flags
00090 #   undef SETFAMILY
00091 #   define SA_FAMILY sa_family
00092 #  else
00093 #   define IFREQ lifreq
00094 #   define IFCONF lifconf
00095 #   define IFC_REQ lifc_req
00096 #   define IFC_LEN lifc_len
00097 #   define IFC_BUF lifc_buf
00098 #   define IFR_ADDR lifr_addr
00099 #   define IFR_NAME lifr_name
00100 #   define IFR_FLAGS lifr_flags
00101 #   define SETFAMILY
00102 #   define IFC_FAMILY lifc_family
00103 #   define IFC_FLAGS lifc_flags
00104 #   define SA_FAMILY ss_family
00105 #  endif
00106 # else
00107 #  define SIOCGIFCONF_CMD SIOCGIFCONF
00108 #  define IFREQ ifreq
00109 #  define IFCONF ifconf
00110 #  define IFC_REQ ifc_req
00111 #  define IFC_LEN ifc_len
00112 #  define IFC_BUF ifc_buf
00113 #  define IFR_ADDR ifr_addr
00114 #  define IFR_NAME ifr_name
00115 #  define IFR_FLAGS ifr_flags
00116 #  undef SETFAMILY
00117 #  define SA_FAMILY sa_family
00118 # endif /* SIOCGLIFCONF */
00119 
00120 # if defined (ACE_HAS_THREADS)
00121 #  include "ace/Object_Manager.h"
00122 # endif /* ACE_HAS_THREADS */
00123 
00124 namespace
00125 {
00126   // private:
00127   //  Used internally so not exported.
00128 
00129   // Does this box have ipv4 turned on?
00130   int ace_ipv4_enabled = -1;
00131 
00132   // Does this box have ipv6 turned on?
00133   int ace_ipv6_enabled = -1;
00134 
00135 }
00136 #else /* ACE_HAS_IPV6 */
00137 # define SIOCGIFCONF_CMD SIOCGIFCONF
00138 # define IFREQ ifreq
00139 # define IFCONF ifconf
00140 # define IFC_REQ ifc_req
00141 # define IFC_LEN ifc_len
00142 # define IFC_BUF ifc_buf
00143 # define IFR_ADDR ifr_addr
00144 # define IFR_NAME ifr_name
00145 # define IFR_FLAGS ifr_flags
00146 # undef SETFAMILY
00147 # define SA_FAMILY sa_family
00148 #endif /* ACE_HAS_IPV6 */
00149 
00150 // This is a hack to work around a problem with Visual Age C++ 5 and 6 on AIX.
00151 // Without this, the compiler auto-instantiates the ACE_Auto_Array_Ptr for
00152 // ifreq (contained in this module) but only adds the #include for <net/if.h>
00153 // and not the one for <sys/socket.h> which is also needed.  Although we
00154 // don't need the template defined here, it makes the compiler pull in
00155 // <sys/socket.h> and the build runs clean.
00156 #if defined (AIX) && defined (__IBMCPP__) && (__IBMCPP__ >= 500) && (__IBMCPP__ < 700)
00157 static ACE_Auto_Array_Ptr<sockaddr> force_compiler_to_include_socket_h;
00158 #endif /* AIX && __IBMCPP__ >= 500 */
00159 
00160 
00161 ACE_RCSID (ace,
00162            Sock_Connect,
00163            "$Id: Sock_Connect.cpp 81696 2008-05-14 18:15:31Z johnnyw $")
00164 
00165 
00166 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00167 
00168 // Bind socket to an unused port.
00169 
00170 int
00171 ACE::bind_port (ACE_HANDLE handle, ACE_UINT32 ip_addr, int address_family)
00172 {
00173   ACE_TRACE ("ACE::bind_port");
00174 
00175   ACE_INET_Addr addr;
00176 
00177 #if defined (ACE_HAS_IPV6)
00178   if (address_family != PF_INET6)
00179     // What do we do if it is PF_"INET6?  Since it's 4 bytes, it must be an
00180     // IPV4 address. Is there a difference?  Why is this test done? dhinton
00181 #else /* ACE_HAS_IPV6 */
00182     ACE_UNUSED_ARG (address_family);
00183 #endif /* !ACE_HAS_IPV6 */
00184     addr = ACE_INET_Addr ((u_short)0, ip_addr);
00185 #if defined (ACE_HAS_IPV6)
00186  else if (ip_addr != INADDR_ANY)
00187  // address_family == PF_INET6 and a non default IP address means to bind
00188  // to the IPv4-mapped IPv6 address
00189    addr.set ((u_short)0, ip_addr, 1, 1);
00190 #endif /* ACE_HAS_IPV6 */
00191 
00192 #if !defined (ACE_LACKS_WILDCARD_BIND)
00193   // The OS kernel should select a free port for us.
00194   return ACE_OS::bind (handle,
00195                        (sockaddr*)addr.get_addr(),
00196                        addr.get_size());
00197 #else
00198   static u_short upper_limit = ACE_MAX_DEFAULT_PORT;
00199   int round_trip = upper_limit;
00200   int lower_limit = IPPORT_RESERVED;
00201 
00202   // We have to select the port explicitly.
00203 
00204   for (;;)
00205     {
00206       addr.set((u_short)upper_limit,ip_addr);
00207 
00208       if (ACE_OS::bind (handle,
00209                         (sockaddr*)addr.get_addr()
00210                         addr.get_size()) >= 0)
00211         {
00212 #if defined (ACE_WIN32)
00213           upper_limit--;
00214 #endif /* ACE_WIN32 */
00215           return 0;
00216         }
00217       else if (errno != EADDRINUSE)
00218         return -1;
00219       else
00220         {
00221           upper_limit--;
00222 
00223           // Wrap back around when we reach the bottom.
00224           if (upper_limit <= lower_limit)
00225             upper_limit = ACE_MAX_DEFAULT_PORT;
00226 
00227           // See if we have already gone around once!
00228           if (upper_limit == round_trip)
00229             {
00230               errno = EAGAIN;
00231               return -1;
00232             }
00233         }
00234     }
00235 #endif /* ACE_HAS_WILDCARD_BIND */
00236 }
00237 
00238 int
00239 ACE::get_bcast_addr (ACE_UINT32 &bcast_addr,
00240                      const ACE_TCHAR *host_name,
00241                      ACE_UINT32 host_addr,
00242                      ACE_HANDLE handle)
00243 {
00244   ACE_TRACE ("ACE::get_bcast_addr");
00245 
00246 #if defined (ACE_LACKS_GET_BCAST_ADDR)
00247   ACE_UNUSED_ARG (bcast_addr);
00248   ACE_UNUSED_ARG (host_name);
00249   ACE_UNUSED_ARG (host_addr);
00250   ACE_UNUSED_ARG (handle);
00251   ACE_NOTSUP_RETURN (-1);
00252 #elif !defined(ACE_WIN32) && !defined(__INTERIX)
00253   ACE_HANDLE s = handle;
00254 
00255   if (s == ACE_INVALID_HANDLE)
00256     s = ACE_OS::socket (AF_INET, SOCK_STREAM, 0);
00257 
00258   if (s == ACE_INVALID_HANDLE)
00259     ACE_ERROR_RETURN ((LM_ERROR,
00260                        ACE_TEXT ("%p\n"),
00261                        ACE_TEXT ("ACE_OS::socket")),
00262                       -1);
00263 
00264   struct ifconf ifc;
00265   char buf[BUFSIZ];
00266 
00267   ifc.ifc_len = sizeof buf;
00268   ifc.ifc_buf = buf;
00269 
00270   // Get interface structure and initialize the addresses using UNIX
00271   // techniques
00272   if (ACE_OS::ioctl (s, SIOCGIFCONF_CMD, (char *) &ifc) == -1)
00273     ACE_ERROR_RETURN ((LM_ERROR,
00274                        ACE_TEXT ("%p\n"),
00275                        ACE_TEXT ("ACE::get_bcast_addr:")
00276                        ACE_TEXT ("ioctl (get interface configuration)")),
00277                       -1);
00278 
00279   struct ifreq *ifr = ifc.ifc_req;
00280 
00281   struct sockaddr_in ip_addr;
00282 
00283   // Get host ip address if necessary.
00284   if (host_name)
00285     {
00286       hostent *hp = ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name));
00287 
00288       if (hp == 0)
00289         return -1;
00290       else
00291 #if !defined(_UNICOS)
00292         ACE_OS::memcpy ((char *) &ip_addr.sin_addr.s_addr,
00293                         (char *) hp->h_addr,
00294                         hp->h_length);
00295 #else /* _UNICOS */
00296       {
00297         ACE_UINT64 haddr;  // a place to put the address
00298         char * haddrp = (char *) &haddr;  // convert to char pointer
00299         ACE_OS::memcpy(haddrp,(char *) hp->h_addr,hp->h_length);
00300         ip_addr.sin_addr.s_addr = haddr;
00301       }
00302 #endif /* ! _UNICOS */
00303     }
00304   else
00305     {
00306       ACE_OS::memset ((void *) &ip_addr, 0, sizeof ip_addr);
00307 #if !defined(_UNICOS)
00308       ACE_OS::memcpy ((void *) &ip_addr.sin_addr,
00309                       (void*) &host_addr,
00310                       sizeof ip_addr.sin_addr);
00311 #else /* _UNICOS */
00312       ip_addr.sin_addr.s_addr = host_addr;   // just copy to the bitfield
00313 #endif /* ! _UNICOS */
00314     }
00315 
00316 #if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
00317   for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
00318        n--, ifr++)
00319 #else
00320   // see mk_broadcast@SOCK_Dgram_Bcast.cpp
00321   for (int nbytes = ifc.ifc_len; nbytes >= (int) sizeof (struct ifreq) &&
00322         ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
00323           (nbytes >= (int) sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len) : 1);
00324         ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
00325           (nbytes -= sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len,
00326             ifr = (struct ifreq *)
00327               ((caddr_t) &ifr->ifr_addr + ifr->ifr_addr.sa_len)) :
00328           (nbytes -= sizeof (struct ifreq), ifr++)))
00329 #endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
00330     {
00331       struct sockaddr_in if_addr;
00332 
00333       // Compare host ip address with interface ip address.
00334       ACE_OS::memcpy (&if_addr,
00335                       &ifr->ifr_addr,
00336                       sizeof if_addr);
00337 
00338       if (ip_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
00339         continue;
00340 
00341       if (ifr->ifr_addr.sa_family != AF_INET)
00342         {
00343           ACE_ERROR ((LM_ERROR,
00344                       ACE_TEXT ("%p\n"),
00345                       ACE_TEXT ("ACE::get_bcast_addr:")
00346                       ACE_TEXT ("Not AF_INET")));
00347           continue;
00348         }
00349 
00350       struct ifreq flags = *ifr;
00351       struct ifreq if_req = *ifr;
00352 
00353       if (ACE_OS::ioctl (s, SIOCGIFFLAGS, (char *) &flags) == -1)
00354         {
00355           ACE_ERROR ((LM_ERROR,
00356                       ACE_TEXT ("%p\n"),
00357                       ACE_TEXT ("ACE::get_bcast_addr:")
00358                       ACE_TEXT (" ioctl (get interface flags)")));
00359           continue;
00360         }
00361 
00362       if (ACE_BIT_DISABLED (flags.ifr_flags, IFF_UP))
00363         {
00364           ACE_ERROR ((LM_ERROR,
00365                       ACE_TEXT ("%p\n"),
00366                       ACE_TEXT ("ACE::get_bcast_addr:")
00367                       ACE_TEXT ("Network interface is not up")));
00368           continue;
00369         }
00370 
00371       if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_LOOPBACK))
00372         continue;
00373 
00374       if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_BROADCAST))
00375         {
00376           if (ACE_OS::ioctl (s,
00377                              SIOCGIFBRDADDR,
00378                              (char *) &if_req) == -1)
00379             ACE_ERROR ((LM_ERROR,
00380                         ACE_TEXT ("%p\n"),
00381                         ACE_TEXT ("ACE::get_bcast_addr:")
00382                         ACE_TEXT ("ioctl (get broadaddr)")));
00383           else
00384             {
00385               ACE_OS::memcpy (&ip_addr,
00386                               &if_req.ifr_broadaddr,
00387                               sizeof if_req.ifr_broadaddr);
00388 
00389               ACE_OS::memcpy ((void *) &host_addr,
00390                               (void *) &ip_addr.sin_addr,
00391                               sizeof host_addr);
00392 
00393               if (handle == ACE_INVALID_HANDLE)
00394                 ACE_OS::close (s);
00395 
00396               bcast_addr = host_addr;
00397               return 0;
00398             }
00399         }
00400       else
00401         ACE_ERROR ((LM_ERROR,
00402                     ACE_TEXT ("%p\n"),
00403                     ACE_TEXT ("ACE::get_bcast_addr:")
00404                     ACE_TEXT ("Broadcast is not enable for this interface.")));
00405 
00406       if (handle == ACE_INVALID_HANDLE)
00407         ACE_OS::close (s);
00408 
00409       bcast_addr = host_addr;
00410       return 0;
00411     }
00412 
00413   return 0;
00414 #else
00415   ACE_UNUSED_ARG (handle);
00416   ACE_UNUSED_ARG (host_addr);
00417   ACE_UNUSED_ARG (host_name);
00418   bcast_addr = (ACE_UINT32 (INADDR_BROADCAST));
00419   return 0;
00420 #endif /* !ACE_WIN32 && !__INTERIX */
00421 }
00422 
00423 int
00424 ACE::get_fqdn (ACE_INET_Addr const & addr,
00425                char hostname[],
00426                size_t len)
00427 {
00428   int h_error;  // Not the same as errno!
00429   hostent hentry;
00430   ACE_HOSTENT_DATA buf;
00431 
00432   char * ip_addr = 0;
00433   int ip_addr_size = 0;
00434   if (addr.get_type () == AF_INET)
00435     {
00436       sockaddr_in * const sock_addr =
00437         reinterpret_cast<sockaddr_in *> (addr.get_addr ());
00438       ip_addr_size = sizeof sock_addr->sin_addr;
00439       ip_addr = (char*) &sock_addr->sin_addr;
00440     }
00441 #ifdef ACE_HAS_IPV6
00442   else
00443     {
00444       sockaddr_in6 * sock_addr =
00445         reinterpret_cast<sockaddr_in6 *> (addr.get_addr ());
00446 
00447       ip_addr_size = sizeof sock_addr->sin6_addr;
00448       ip_addr = (char*) &sock_addr->sin6_addr;
00449     }
00450 #endif  /* ACE_HAS_IPV6 */
00451 
00452    // get the host entry for the address in question
00453    hostent * const hp = ACE_OS::gethostbyaddr_r (ip_addr,
00454                                                  ip_addr_size,
00455                                                  addr.get_type (),
00456                                                  &hentry,
00457                                                  buf,
00458                                                  &h_error);
00459 
00460    // if it's not found in the host file or the DNS datase, there is nothing
00461    // much we can do. embed the IP address
00462    if (hp == 0 || hp->h_name == 0)
00463      return -1;
00464 
00465    if (ACE::debug())
00466      ACE_DEBUG ((LM_DEBUG,
00467                  ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
00468                  ACE_TEXT ("canonical host name is %s\n"),
00469                  ACE_TEXT_CHAR_TO_TCHAR (hp->h_name)));
00470 
00471    // check if the canonical name is the FQDN
00472    if (!ACE_OS::strchr(hp->h_name, '.'))
00473      {
00474        // list of address
00475        char** p;
00476        // list of aliases
00477        char** q;
00478 
00479        // for every address and for every alias within the address, check and
00480        // see if we can locate a FQDN
00481        for (p = hp->h_addr_list; *p != 0; ++p)
00482          {
00483            for (q = hp->h_aliases; *q != 0; ++q)
00484              {
00485                if (ACE_OS::strchr(*q, '.'))
00486                  {
00487                    // we got an FQDN from an alias. use this
00488                    if (ACE_OS::strlen (*q) >= len)
00489                      // the hostname is too huge to fit into a
00490                      // buffer of size MAXHOSTNAMELEN
00491                      // should we check other aliases as well
00492                      // before bailing out prematurely?
00493                      // for right now, let's do it. this (short name)
00494                      // is atleast better than embedding the IP
00495                      // address in the profile
00496                      continue;
00497 
00498                    if (ACE::debug ())
00499                      ACE_DEBUG ((LM_DEBUG,
00500                                  ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
00501                                  ACE_TEXT ("found fqdn within alias as %s\n"),
00502                                  ACE_TEXT_CHAR_TO_TCHAR(*q)));
00503                    ACE_OS::strcpy (hostname, *q);
00504 
00505                    return 0;
00506                  }
00507              }
00508          }
00509      }
00510 
00511    // The canonical name may be an FQDN when we reach here.
00512    // Alternatively, the canonical name (a non FQDN) may be the best
00513    // we can do.
00514    if (ACE_OS::strlen (hp->h_name) >= len)
00515      {
00516        // The hostname is too large to fit into a buffer of size
00517        // MAXHOSTNAMELEN.
00518        return -2;
00519      }
00520    else
00521      {
00522        ACE_OS::strcpy (hostname, hp->h_name);
00523      }
00524 
00525    return 0;
00526 }
00527 
00528 #if defined (ACE_WIN32)
00529 
00530 static int
00531 get_ip_interfaces_win32 (size_t &count,
00532                          ACE_INET_Addr *&addrs)
00533 {
00534 # if defined (ACE_HAS_WINCE)
00535   // moved the ACE_HAS_WINCE impl ahaid of ACE_HAS_WINSOCK2 because
00536   // WINCE in fact has winsock2, but doesn't properly support the
00537   // WSAIoctl for obtaining IPv6 address info.
00538   PIP_ADAPTER_ADDRESSES AdapterAddresses = 0;
00539   ULONG OutBufferLength = 0;
00540   ULONG RetVal = 0;
00541   unsigned char *octet_buffer = 0;
00542 
00543   RetVal =
00544     GetAdaptersAddresses(AF_UNSPEC,
00545                          0,
00546                          0,
00547                          AdapterAddresses,
00548                          &OutBufferLength);
00549 
00550   if (RetVal != ERROR_BUFFER_OVERFLOW)
00551     {
00552       return -1;
00553     }
00554 
00555   ACE_NEW_RETURN (octet_buffer, unsigned char[OutBufferLength],-1);
00556   AdapterAddresses = (IP_ADAPTER_ADDRESSES *)octet_buffer;
00557 
00558   RetVal =
00559     GetAdaptersAddresses(AF_UNSPEC,
00560                          0,
00561                          0,
00562                          AdapterAddresses,
00563                          &OutBufferLength);
00564 
00565   if (RetVal != NO_ERROR)
00566     {
00567       delete [] octet_buffer;
00568       return -1;
00569      }
00570 
00571   // If successful, output some information from the data we received
00572   PIP_ADAPTER_ADDRESSES AdapterList = AdapterAddresses;
00573   while (AdapterList)
00574     {
00575       if (AdapterList->OperStatus == IfOperStatusUp)
00576         {
00577           if (AdapterList->IfIndex != 0)
00578             ++count;
00579           if (AdapterList->Ipv6IfIndex != 0)
00580             ++count;
00581         }
00582       AdapterList = AdapterList->Next;
00583     }
00584 
00585   AdapterList = AdapterAddresses;
00586 
00587   ACE_NEW_RETURN (addrs, ACE_INET_Addr[count],-1);
00588   count = 0;
00589   for (AdapterList =  AdapterAddresses;
00590        AdapterList != 0;
00591        AdapterList = AdapterList->Next)
00592     {
00593       if (AdapterList->OperStatus != IfOperStatusUp)
00594         continue;
00595 
00596       IP_ADAPTER_UNICAST_ADDRESS *uni = 0;
00597       if (AdapterList->IfIndex != 0)
00598         for (uni = AdapterList->FirstUnicastAddress;
00599              uni != 0;
00600              uni = uni->Next)
00601           {
00602             SOCKET_ADDRESS *sa_addr = &uni->Address;
00603             if (sa_addr->lpSockaddr->sa_family == AF_INET)
00604               {
00605                 sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
00606                 addrs[count].set(sin,sa_addr->iSockaddrLength);
00607                 ++count;
00608                 break;
00609               }
00610           }
00611       if (AdapterList->Ipv6IfIndex != 0)
00612         {
00613         for (uni = AdapterList->FirstUnicastAddress;
00614              uni != 0;
00615              uni = uni->Next)
00616             {
00617               SOCKET_ADDRESS *sa_addr = &uni->Address;
00618               if (sa_addr->lpSockaddr->sa_family == AF_INET6)
00619                 {
00620                   sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
00621                   addrs[count].set(sin,sa_addr->iSockaddrLength);
00622                   ++count;
00623                   break;
00624                 }
00625             }
00626         }
00627     }
00628 
00629   delete [] octet_buffer;
00630   return 0;
00631 
00632 # elif defined (ACE_HAS_PHARLAP)
00633   // PharLap ETS has its own kernel routines to rummage through the device
00634   // configs and extract the interface info, but only for Pharlap RT.
00635 #   if !defined (ACE_HAS_PHARLAP_RT)
00636   ACE_NOTSUP_RETURN (-1);
00637 #   endif /* ACE_HAS_PHARLAP_RT */
00638 
00639   // Locate all of the IP devices in the system, saving a DEVHANDLE
00640   // for each. Then allocate the ACE_INET_Addrs needed and fetch all
00641   // the IP addresses.  To locate the devices, try the available
00642   // device name roots and increment the device number until the
00643   // kernel says there are no more of that type.
00644   const size_t ACE_MAX_ETS_DEVICES = 64;  // Arbitrary, but should be enough.
00645   DEVHANDLE ip_dev[ACE_MAX_ETS_DEVICES];
00646   EK_TCPIPCFG *devp;
00647   size_t i, j;
00648   ACE_TCHAR dev_name[16];
00649 
00650   count = 0;
00651   for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
00652     {
00653       // Ethernet.
00654       ACE_OS::sprintf (dev_name,
00655                        "ether%d",
00656                        i);
00657       ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
00658       if (ip_dev[count] == 0)
00659         break;
00660     }
00661   for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
00662     {
00663       // SLIP.
00664       ACE_OS::sprintf (dev_name,
00665                        "sl%d",
00666                        i);
00667       ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
00668       if (ip_dev[count] == 0)
00669         break;
00670     }
00671   for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
00672     {
00673       // PPP.
00674       ACE_OS::sprintf (dev_name,
00675                        "ppp%d",
00676                        i);
00677       ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
00678       if (ip_dev[count] == 0)
00679         break;
00680     }
00681 
00682   if (count > 0)
00683     ACE_NEW_RETURN (addrs,
00684                     ACE_INET_Addr[count],
00685                     -1);
00686   else
00687     addrs = 0;
00688 
00689   for (i = 0, j = 0; i < count; i++)
00690     {
00691       devp = EtsTCPGetDeviceCfg (ip_dev[i]);
00692       if (devp != 0)
00693         {
00694           addrs[j].set (0,
00695                         devp->nwIPAddress,
00696                         0); // Already in net order.
00697           ++j;
00698         }
00699       // There's no call to close the DEVHANDLE.
00700     }
00701 
00702   count = j;
00703   if (count == 0 && addrs != 0)
00704     {
00705       delete [] addrs;
00706       addrs = 0;
00707     }
00708 
00709   return 0;
00710 
00711 
00712 # else
00713   // All non-CE, non-Pharlap Windows. Must support Winsock2.
00714 
00715   int i, n_interfaces, status;
00716 
00717   INTERFACE_INFO info[64];
00718   SOCKET sock;
00719 
00720   // Get an (overlapped) DGRAM socket to test with
00721   sock = socket (AF_INET, SOCK_DGRAM, 0);
00722   if (sock == INVALID_SOCKET)
00723     return -1;
00724 
00725   DWORD bytes;
00726   status = WSAIoctl(sock,
00727                     SIO_GET_INTERFACE_LIST,
00728                     0,
00729                     0,
00730                     info,
00731                     sizeof(info),
00732                     &bytes,
00733                     0,
00734                     0);
00735   closesocket (sock);
00736   if (status == SOCKET_ERROR)
00737     return -1;
00738 
00739   n_interfaces = bytes / sizeof(INTERFACE_INFO);
00740 
00741   // SIO_GET_INTERFACE_LIST does not work for IPv6
00742   // Instead recent versions of Winsock2 add the new opcode
00743   // SIO_ADDRESS_LIST_QUERY.
00744   // If this is not available forget about IPv6 local interfaces:-/
00745   int n_v6_interfaces = 0;
00746 
00747 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
00748 
00749   LPSOCKET_ADDRESS_LIST v6info;
00750   char *buffer;
00751   DWORD buflen = sizeof (SOCKET_ADDRESS_LIST) + (63 * sizeof (SOCKET_ADDRESS));
00752   ACE_NEW_RETURN (buffer,
00753                   char[buflen],
00754                   -1);
00755   v6info = reinterpret_cast<LPSOCKET_ADDRESS_LIST> (buffer);
00756 
00757   // Get an (overlapped) DGRAM socket to test with.
00758   // If it fails only return IPv4 interfaces.
00759   sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
00760   if (sock != INVALID_SOCKET)
00761     {
00762       status = WSAIoctl(sock,
00763                         SIO_ADDRESS_LIST_QUERY,
00764                         0,
00765                         0,
00766                         v6info,
00767                         buflen,
00768                         &bytes,
00769                         0,
00770                         0);
00771       closesocket (sock);
00772       if (status != SOCKET_ERROR)
00773         n_v6_interfaces = v6info->iAddressCount;
00774     }
00775 # endif /* ACE_HAS_IPV6 */
00776 
00777   ACE_NEW_RETURN (addrs,
00778                   ACE_INET_Addr[n_interfaces + n_v6_interfaces],
00779                   -1);
00780 
00781   // Now go through the list and transfer the good ones to the list of
00782   // because they're down or don't have an IP address.
00783   for (count = 0, i = 0; i < n_interfaces; ++i)
00784     {
00785       LPINTERFACE_INFO lpii;
00786       struct sockaddr_in *addrp = 0;
00787 
00788       lpii = &info[i];
00789       if (!(lpii->iiFlags & IFF_UP))
00790         continue;
00791 
00792       // We assume IPv4 addresses here
00793       addrp = reinterpret_cast<struct sockaddr_in *> (&lpii->iiAddress.AddressIn);
00794       if (addrp->sin_addr.s_addr == INADDR_ANY)
00795         continue;
00796 
00797       // Set the address for the caller.
00798       addrs[count].set(addrp, sizeof(sockaddr_in));
00799       ++count;
00800     }
00801 
00802 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
00803   // Now go through the list and transfer the good ones to the list of
00804   // because they're down or don't have an IP address.
00805   for (i = 0; i < n_v6_interfaces; i++)
00806     {
00807       struct sockaddr_in6 *addr6p;
00808 
00809       if (v6info->Address[i].lpSockaddr->sa_family != AF_INET6)
00810         continue;
00811 
00812       addr6p = reinterpret_cast<struct sockaddr_in6 *> (v6info->Address[i].lpSockaddr);
00813       if (IN6_IS_ADDR_UNSPECIFIED(&addr6p->sin6_addr))  // IN6ADDR_ANY?
00814         continue;
00815 
00816       // Set the address for the caller.
00817       addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr6p), sizeof(sockaddr_in6));
00818       ++count;
00819     }
00820 
00821   delete [] buffer; // Clean up
00822 # endif /* ACE_HAS_IPV6 */
00823 
00824   if (count == 0)
00825     {
00826       delete [] addrs;
00827       addrs = 0;
00828     }
00829 
00830   return 0;
00831 
00832 # endif /* ACE_HAS_WINCE */
00833 }
00834 #elif defined (ACE_HAS_GETIFADDRS)
00835 static int
00836 get_ip_interfaces_getifaddrs (size_t &count,
00837                               ACE_INET_Addr *&addrs)
00838 {
00839   // Take advantage of the BSD getifaddrs function that simplifies
00840   // access to connected interfaces.
00841   struct ifaddrs *ifap = 0;
00842   struct ifaddrs *p_if = 0;
00843 
00844   if (::getifaddrs (&ifap) != 0)
00845     return -1;
00846 
00847   // Count number of interfaces.
00848   size_t num_ifs = 0;
00849   for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
00850     ++num_ifs;
00851 
00852   // Now create and initialize output array.
00853   ACE_NEW_RETURN (addrs,
00854                   ACE_INET_Addr[num_ifs],
00855                   -1); // caller must free
00856 
00857   // Pull the address out of each INET interface.  Not every interface
00858   // is for IP, so be careful to count properly.  When setting the
00859   // INET_Addr, note that the 3rd arg (0) says to leave the byte order
00860   // (already in net byte order from the interface structure) as is.
00861   count = 0;
00862 
00863   for (p_if = ifap;
00864        p_if != 0;
00865        p_if = p_if->ifa_next)
00866     {
00867       if (p_if->ifa_addr &&
00868           p_if->ifa_addr->sa_family == AF_INET)
00869         {
00870           struct sockaddr_in *addr =
00871             reinterpret_cast<sockaddr_in *> (p_if->ifa_addr);
00872 
00873           // Sometimes the kernel returns 0.0.0.0 as the interface
00874           // address, skip those...
00875           if (addr->sin_addr.s_addr != INADDR_ANY)
00876             {
00877               addrs[count].set ((u_short) 0,
00878                                 addr->sin_addr.s_addr,
00879                                 0);
00880               ++count;
00881             }
00882         }
00883 # if defined (ACE_HAS_IPV6)
00884       else if (p_if->ifa_addr &&
00885                p_if->ifa_addr->sa_family == AF_INET6)
00886         {
00887           struct sockaddr_in6 *addr =
00888             reinterpret_cast<sockaddr_in6 *> (p_if->ifa_addr);
00889 
00890           // Skip the ANY address
00891           if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr))
00892             {
00893               addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr),
00894                                sizeof(sockaddr_in6));
00895               ++count;
00896             }
00897         }
00898 # endif /* ACE_HAS_IPV6 */
00899     }
00900 
00901   ::freeifaddrs (ifap);
00902 
00903   return 0;
00904 }
00905 #elif defined (__hpux)
00906 static int
00907 get_ip_interfaces_hpux (size_t &count,
00908                         ACE_INET_Addr *&addrs)
00909 {
00910   size_t num_ifs = 0;
00911   size_t num_ifs_found = 0;
00912 
00913   // Call specific routine as necessary.
00914   ACE_HANDLE handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
00915   ACE_HANDLE handle_ipv6 = ACE_INVALID_HANDLE;
00916 
00917   if (handle == ACE_INVALID_HANDLE)
00918     ACE_ERROR_RETURN ((LM_ERROR,
00919                        ACE_TEXT ("%p\n"),
00920                        ACE_TEXT ("ACE::get_ip_interfaces:open")),
00921                       -1);
00922 
00923   int result = 0;
00924   int tmp_how_many = 0;
00925 
00926   result = ACE_OS::ioctl (handle,
00927                           SIOCGIFNUM,
00928                           (caddr_t) &tmp_how_many);
00929   if (result != -1)
00930     num_ifs = (size_t)tmp_how_many;
00931 
00932 # if defined (ACE_HAS_IPV6)
00933   tmp_how_many = 0;
00934   handle_ipv6 = ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0);
00935   result = ACE_OS::ioctl (handle_ipv6,
00936                           SIOCGLIFNUM,
00937                           (caddr_t) &tmp_how_many);
00938   if (result != -1)
00939     num_ifs += (size_t)tmp_how_many;
00940 # endif
00941 
00942   if (num_ifs == 0)
00943     {
00944       ACE_OS::close (handle);
00945       ACE_OS::close (handle_ipv6);
00946       return -1;
00947     }
00948 
00949   // ioctl likes to have an extra IFREQ structure to mark the end of
00950   // what it returned, so increase the num_ifs by one.
00951   ++num_ifs;
00952 
00953   //HPUX requires two passes, First for IPv4, then for IPv6
00954 
00955   struct ifreq *ifs = 0;
00956   ACE_NEW_RETURN (ifs,
00957                   struct ifreq[num_ifs],
00958                   -1);
00959   ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct ifreq));
00960 
00961   ACE_Auto_Array_Ptr<struct ifreq> p_ifs (ifs);
00962 
00963   if (p_ifs.get() == 0)
00964     {
00965       ACE_OS::close (handle);
00966       ACE_OS::close (handle_ipv6);
00967       errno = ENOMEM;
00968       return -1;
00969     }
00970 
00971   struct ifconf ifcfg;
00972   ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
00973 
00974   ifcfg.ifc_req = p_ifs.get ();
00975   ifcfg.ifc_len = num_ifs * sizeof (struct ifreq);
00976 
00977   if (ACE_OS::ioctl (handle,
00978                      SIOCGIFCONF,
00979                      (char *) &ifcfg) == -1)
00980     {
00981       ACE_OS::close (handle);
00982       ACE_ERROR_RETURN ((LM_ERROR,
00983                          ACE_TEXT ("%p\n"),
00984                          ACE_TEXT ("ACE::get_ip_interfaces:")
00985                          ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
00986                         -1);
00987     }
00988 
00989   ACE_OS::close (handle);
00990 
00991   // Now create and initialize output array.
00992 
00993   ACE_NEW_RETURN (addrs,
00994                   ACE_INET_Addr[num_ifs],
00995                   -1); // caller must free
00996 
00997   struct ifreq *pcur = p_ifs.get ();
00998   num_ifs_found = ifcfg.ifc_len / sizeof (struct ifreq); // get the number of returned ifs
00999 
01000   for (size_t i = 0;
01001        i < num_ifs_found;
01002        i++)
01003     {
01004         struct sockaddr_in *addr =
01005             reinterpret_cast<sockaddr_in *> (&pcur->ifr_addr);
01006         if (addr->sin_addr.s_addr != 0)
01007         {
01008             addrs[count].set ((u_short) 0,
01009                               addr->sin_addr.s_addr,
01010                               0);
01011             ++count;
01012         }
01013         ++pcur;
01014     }
01015 
01016 # if defined (ACE_HAS_IPV6)
01017 
01018   if (handle_ipv6 != ACE_INVALID_HANDLE)
01019     {
01020       struct if_laddrreq *lifs = 0;
01021       ACE_NEW_RETURN (lifs,
01022                       struct if_laddrreq[num_ifs],
01023                       -1);
01024       ACE_OS::memset (lifs, 0, num_ifs * sizeof (struct if_laddrreq));
01025 
01026       ACE_Auto_Array_Ptr<struct if_laddrreq> p_lifs (lifs);
01027 
01028       if (p_lifs.get() == 0)
01029         {
01030           ACE_OS::close (handle);
01031           ACE_OS::close (handle_ipv6);
01032           errno = ENOMEM;
01033           return -1;
01034         }
01035 
01036       struct if_laddrconf lifcfg;
01037       ACE_OS::memset (&lifcfg, 0, sizeof (struct if_laddrconf));
01038 
01039       lifcfg.iflc_req = p_lifs.get ();
01040       lifcfg.iflc_len = num_ifs * sizeof (struct if_laddrreq);
01041 
01042       if (ACE_OS::ioctl (handle_ipv6,
01043                          SIOCGLIFCONF,
01044                          (char *) &lifcfg) == -1)
01045         {
01046           ACE_OS::close (handle);
01047           ACE_ERROR_RETURN ((LM_ERROR,
01048                              ACE_TEXT ("%p\n"),
01049                              ACE_TEXT ("ACE::get_ip_interfaces:")
01050                              ACE_TEXT ("ioctl - SIOCGLIFCONF failed")),
01051                             -1);
01052         }
01053 
01054       ACE_OS::close (handle_ipv6);
01055 
01056       struct if_laddrreq *plcur = p_lifs.get ();
01057       num_ifs_found = lifcfg.iflc_len / sizeof (struct if_laddrreq);
01058 
01059       for (size_t i = 0;
01060            i < num_ifs_found;
01061            i++)
01062         {
01063             struct sockaddr_in *addr =
01064                 reinterpret_cast<sockaddr_in *> (&plcur->iflr_addr);
01065             if (!IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
01066             {
01067                 addrs[count].set(addr, sizeof(struct sockaddr_in6));
01068                 ++count;
01069             }
01070             ++plcur;
01071         }
01072     }
01073 # endif /* ACE_HAS_IPV6 */
01074   return 0;
01075 }
01076 #elif defined (_AIX)
01077 static int
01078 get_ip_interfaces_aix (size_t &count,
01079                        ACE_INET_Addr *&addrs)
01080 {
01081   ACE_HANDLE handle = ACE::get_handle();
01082   size_t num_ifs = 0;
01083   struct ifconf ifc;
01084 
01085   if (handle == ACE_INVALID_HANDLE)
01086     ACE_ERROR_RETURN ((LM_ERROR,
01087                        ACE_TEXT ("%p\n"),
01088                        ACE_TEXT ("ACE::get_ip_interfaces_aix:")),
01089                       -1);
01090 
01091   if (ACE_OS::ioctl (handle,
01092                      SIOCGSIZIFCONF,
01093                      (caddr_t)&ifc.ifc_len) == -1)
01094   {
01095       ACE_OS::close (handle);
01096       ACE_ERROR_RETURN((LM_ERROR,
01097                         ACE_TEXT ("%p\n"),
01098                         ACE_TEXT ("get ifconf size")),
01099                        -1);
01100   }
01101 
01102   ACE_NEW_RETURN (ifc.ifc_buf,char [ifc.ifc_len], -1);
01103 
01104   ACE_Auto_Array_Ptr<char> safe_buf (ifc.ifc_buf);
01105   ACE_OS::memset (safe_buf.get(), 0, ifc.ifc_len);
01106 
01107   if (ACE_OS::ioctl(handle, SIOCGIFCONF, (caddr_t)&ifc) == -1)
01108   {
01109       ACE_OS::close (handle);
01110       ACE_ERROR_RETURN((LM_ERROR,
01111                         ACE_TEXT ("%p\n"),
01112                         ACE_TEXT ("get ifconf")),
01113                        -1);
01114   }
01115 
01116   ACE_OS::close (handle);
01117 
01118   char *buf_start = safe_buf.get();
01119   char *buf_end = buf_start + ifc.ifc_len;
01120 
01121   num_ifs = 0;
01122   for (char *ptr = buf_start; ptr < buf_end; )
01123     {
01124       struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
01125       ptr += IFNAMSIZ;
01126       ptr += req->ifr_addr.sa_len;
01127      if (req->ifr_addr.sa_family == AF_INET
01128 # if defined (ACE_HAS_IPV6)
01129         || req->ifr_addr.sa_family == AF_INET6
01130 # endif
01131         )
01132        ++num_ifs;
01133     }
01134   ACE_NEW_RETURN (addrs,ACE_INET_Addr[num_ifs], -1);
01135 
01136   for (char * ptr = buf_start;  ptr < buf_end; )
01137   {
01138     struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
01139     // skip the interface name
01140     ptr += IFNAMSIZ;
01141     if (req->ifr_addr.sa_family == AF_INET
01142 # if defined (ACE_HAS_IPV6)
01143         || req->ifr_addr.sa_family == AF_INET6
01144 # endif
01145         )
01146       {
01147         sockaddr_in *addr = (sockaddr_in*)&req->ifr_addr;
01148         addrs[count++].set(addr, addr->sin_len);
01149       }
01150     ptr += req->ifr_addr.sa_len;
01151   }
01152 
01153   return 0;
01154 }
01155 
01156 #elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600) && !defined (ACE_HAS_VXWORKS551_MEDUSA)
01157 int
01158 get_ip_interfaces_vxworks_lt600 (size_t &count,
01159                                  ACE_INET_Addr *&addrs)
01160 {
01161   count = 0;
01162   // Loop through each address structure
01163 
01164 # if defined (ACE_HAS_IPV6) && defined (TAILQ_ENTRY)
01165 #   define ia_next ia_link.tqe_next
01166 # endif /* TAILQ_ENTRY */
01167 
01168   for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
01169     {
01170       ++count;
01171     }
01172 
01173   // Now create and initialize output array.
01174   ACE_NEW_RETURN (addrs,
01175                   ACE_INET_Addr[count],
01176                   -1); // caller must free
01177   count = 0;
01178   for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
01179     {
01180       struct ifnet* ifp = ia->ia_ifa.ifa_ifp;
01181       if (ifp != 0)
01182         {
01183           // Get the current interface name
01184           char interface[64];
01185           ACE_OS::sprintf(interface, "%s%d", ifp->if_name, ifp->if_unit);
01186 
01187           // Get the address for the current interface
01188           char address [INET_ADDR_LEN];
01189           STATUS status = ifAddrGet(interface, address);
01190 
01191           if (status == OK)
01192             {
01193               // Concatenate a ':' at the end. This is because in
01194               // ACE_INET_Addr::string_to_addr, the ip_address is
01195               // obtained using ':' as the delimiter. Since, using
01196               // ifAddrGet(), we just get the IP address, I am adding
01197               // a ":" to get with the general case.
01198               ACE_OS::strcat (address, ":");
01199               addrs[count].set (address);
01200             }
01201           else
01202             {
01203               ACE_ERROR_RETURN ((LM_ERROR,
01204                                  ACE_TEXT ("ACE::get_ip_interface failed\n")
01205                                  ACE_TEXT ("Couldnt get the IP Address\n")),
01206                                  -1);
01207             }
01208           ++count;
01209         }
01210     }
01211   return 0;
01212 }
01213 #endif // ACE_WIN32 || ACE_HAS_GETIFADDRS || __hpux || _AIX || ACE_VXWORKS < 0x600
01214 
01215 
01216 // return an array of all configured IP interfaces on this host, count
01217 // rc = 0 on success (count == number of interfaces else -1 caller is
01218 // responsible for calling delete [] on parray
01219 
01220 int
01221 ACE::get_ip_interfaces (size_t &count,
01222                         ACE_INET_Addr *&addrs)
01223 {
01224   ACE_TRACE ("ACE::get_ip_interfaces");
01225 
01226   count = 0;
01227   addrs = 0;
01228 
01229 #if defined (ACE_WIN32)
01230   return get_ip_interfaces_win32 (count, addrs);
01231 #elif defined (ACE_HAS_GETIFADDRS)
01232   return get_ip_interfaces_getifaddrs (count, addrs);
01233 #elif defined (__hpux)
01234   return get_ip_interfaces_hpux (count, addrs);
01235 #elif defined (_AIX)
01236   return get_ip_interfaces_aix (count, addrs);
01237 #elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600) && !defined (ACE_HAS_VXWORKS551_MEDUSA)
01238   return get_ip_interfaces_vxworks_lt600 (count, addrs);
01239 #elif (defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (ACE_OPENVMS) || (defined (ACE_VXWORKS) && (ACE_VXWORKS == 0x650)) || defined (ACE_HAS_RTEMS)) && !defined (ACE_LACKS_NETWORKING)
01240   // COMMON (SVR4 and BSD) UNIX CODE
01241 
01242   // Call specific routine as necessary.
01243   ACE_HANDLE handle = ACE::get_handle();
01244 
01245   if (handle == ACE_INVALID_HANDLE)
01246     ACE_ERROR_RETURN ((LM_ERROR,
01247                        ACE_TEXT ("%p\n"),
01248                        ACE_TEXT ("ACE::get_ip_interfaces:open")),
01249                       -1);
01250 
01251   size_t num_ifs, num_ifs_found;
01252 
01253   if (ACE::count_interfaces (handle, num_ifs))
01254     {
01255       ACE_OS::close (handle);
01256       return -1;
01257     }
01258 
01259   // ioctl likes to have an extra ifreq structure to mark the end of
01260   // what it returned, so increase the num_ifs by one.
01261   ++num_ifs;
01262 
01263   struct IFREQ *ifs = 0;
01264   ACE_NEW_RETURN (ifs,
01265                   struct IFREQ[num_ifs],
01266                   -1);
01267   ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct IFREQ));
01268 
01269   ACE_Auto_Array_Ptr<struct IFREQ> p_ifs (ifs);
01270 
01271   if (p_ifs.get() == 0)
01272     {
01273       ACE_OS::close (handle);
01274       errno = ENOMEM;
01275       return -1;
01276     }
01277 
01278   struct IFCONF ifcfg;
01279   ACE_OS::memset (&ifcfg, 0, sizeof (struct IFCONF));
01280 
01281 # ifdef SETFAMILY
01282   ifcfg.IFC_FAMILY = AF_UNSPEC;  // request all families be returned
01283   ifcfg.IFC_FLAGS = 0;
01284 # endif
01285 
01286   ifcfg.IFC_REQ = p_ifs.get ();
01287   ifcfg.IFC_LEN = num_ifs * sizeof (struct IFREQ);
01288 
01289   if (ACE_OS::ioctl (handle,
01290                      SIOCGIFCONF_CMD,
01291                      (caddr_t) &ifcfg) == -1)
01292     {
01293       ACE_OS::close (handle);
01294       ACE_ERROR_RETURN ((LM_ERROR,
01295                          ACE_TEXT ("%p\n"),
01296                          ACE_TEXT ("ACE::get_ip_interfaces:")
01297                          ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
01298                         -1);
01299     }
01300 
01301   ACE_OS::close (handle);
01302 
01303   // Now create and initialize output array.
01304 
01305   ACE_NEW_RETURN (addrs,
01306                   ACE_INET_Addr[num_ifs],
01307                   -1); // caller must free
01308 
01309   struct IFREQ *pcur = p_ifs.get ();
01310   num_ifs_found = ifcfg.IFC_LEN / sizeof (struct IFREQ); // get the number of returned ifs
01311 
01312   // Pull the address out of each INET interface.  Not every interface
01313   // is for IP, so be careful to count properly.  When setting the
01314   // INET_Addr, note that the 3rd arg (0) says to leave the byte order
01315   // (already in net byte order from the interface structure) as is.
01316   count = 0;
01317 
01318   for (size_t i = 0;
01319        i < num_ifs_found;
01320        i++)
01321     {
01322       if (pcur->IFR_ADDR.SA_FAMILY == AF_INET
01323 #  if defined (ACE_HAS_IPV6)
01324           || pcur->IFR_ADDR.SA_FAMILY == AF_INET6
01325 #  endif
01326           )
01327 
01328         {
01329 # if !defined(_UNICOS)
01330           struct sockaddr_in *addr =
01331             reinterpret_cast<sockaddr_in *> (&pcur->IFR_ADDR);
01332 
01333           // Sometimes the kernel returns 0.0.0.0 as an IPv4 interface
01334           // address; skip those...
01335           if (addr->sin_addr.s_addr != 0
01336 #  if defined (ACE_HAS_IPV6)
01337               || (addr->sin_family == AF_INET6 &&
01338                   !IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
01339 #  endif
01340               )
01341             {
01342               int addrlen = static_cast<int> (sizeof (struct sockaddr_in));
01343 #  if defined (ACE_HAS_IPV6)
01344               if (addr->sin_family == AF_INET6)
01345                 addrlen = static_cast<int> (sizeof (struct sockaddr_in6));
01346 #  endif
01347               addrs[count].set (addr, addrlen);
01348               ++count;
01349             }
01350 # else /* ! _UNICOS */
01351           // need to explicitly copy on the Cray, since the bitfields kinda
01352           // screw things up here
01353           struct sockaddr_in inAddr;
01354 
01355           inAddr.sin_len = pcur->IFR_ADDR.sa_len;
01356           inAddr.sin_family = pcur->IFR_ADDR.sa_family;
01357           memcpy((void *)&(inAddr.sin_addr),
01358                  (const void *)&(pcur->IFR_ADDR.sa_data[8]),
01359                  sizeof(struct in_addr));
01360 
01361           if (inAddr.sin_addr.s_addr != 0)
01362             {
01363               addrs[count].set(&inAddr, sizeof(struct sockaddr_in));
01364               ++count;
01365             }
01366 # endif /* ! _UNICOS */
01367         }
01368 
01369 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS)
01370       ++pcur;
01371 #else
01372       if (pcur->ifr_addr.sa_len <= sizeof (struct sockaddr))
01373         {
01374            ++pcur;
01375         }
01376       else
01377         {
01378            pcur = (struct ifreq *)
01379                (pcur->ifr_addr.sa_len + (caddr_t) &pcur->ifr_addr);
01380         }
01381 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
01382     }
01383 
01384 # if defined (ACE_HAS_IPV6)
01385   // Retrieve IPv6 local interfaces by scanning /proc/net/if_inet6 if
01386   // it exists.  If we cannot open it then ignore possible IPv6
01387   // interfaces, we did our best;-)
01388   FILE* fp;
01389   char addr_p[8][5];
01390   char s_ipaddr[64];
01391   int scopeid;
01392   struct addrinfo hints, *res0;
01393   int error;
01394 
01395   ACE_OS::memset (&hints, 0, sizeof (hints));
01396   hints.ai_flags = AI_NUMERICHOST;
01397   hints.ai_family = AF_INET6;
01398 
01399   if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
01400     {
01401       while (fscanf (fp,
01402                      "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*8s\n",
01403                      addr_p[0], addr_p[1], addr_p[2], addr_p[3],
01404                      addr_p[4], addr_p[5], addr_p[6], addr_p[7], &scopeid) != EOF)
01405         {
01406           // Format the address intoa proper IPv6 decimal address specification and
01407           // resolve the resulting text using getaddrinfo().
01408 
01409           const char* ip_fmt = "%s:%s:%s:%s:%s:%s:%s:%s%%%d";
01410           ACE_OS::sprintf (s_ipaddr,
01411                            ip_fmt,
01412                            addr_p[0], addr_p[1], addr_p[2], addr_p[3],
01413                            addr_p[4], addr_p[5], addr_p[6], addr_p[7], scopeid);
01414 
01415           error = getaddrinfo (s_ipaddr, 0, &hints, &res0);
01416           if (error)
01417             continue;
01418 
01419           if (res0->ai_family == AF_INET6 &&
01420                 !IN6_IS_ADDR_UNSPECIFIED (&reinterpret_cast<sockaddr_in6 *> (res0->ai_addr)->sin6_addr))
01421             {
01422               addrs[count].set(reinterpret_cast<sockaddr_in *> (res0->ai_addr), res0->ai_addrlen);
01423               ++count;
01424             }
01425           freeaddrinfo (res0);
01426 
01427         }
01428       ACE_OS::fclose (fp);
01429     }
01430 # endif /* ACE_HAS_IPV6 */
01431 
01432   return 0;
01433 #else
01434   ACE_UNUSED_ARG (count);
01435   ACE_UNUSED_ARG (addrs);
01436   ACE_NOTSUP_RETURN (-1);                      // no implementation
01437 #endif /* ACE_WIN32 */
01438 }
01439 
01440 // Helper routine for get_ip_interfaces, differs by UNIX platform so
01441 // put into own subroutine.  perform some ioctls to retrieve ifconf
01442 // list of ifreq structs.
01443 
01444 int
01445 ACE::count_interfaces (ACE_HANDLE handle,
01446                        size_t &how_many)
01447 {
01448 #if defined (ACE_WIN32) || defined (ACE_HAS_GETIFADDRS) || defined (__hpux) || defined (_AIX) || (defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600))
01449   // none of these platforms make use of count_interfaces
01450   ACE_UNUSED_ARG (handle);
01451   ACE_UNUSED_ARG (how_many);
01452   ACE_NOTSUP_RETURN (-1); // no implementation
01453 
01454 #elif defined (SIOCGIFNUM)
01455 # if defined (SIOCGLIFNUM)
01456   int cmd = SIOCGLIFNUM;
01457   struct lifnum if_num = {AF_UNSPEC,0,0};
01458 # else
01459   int cmd = SIOCGIFNUM;
01460   int if_num = 0;
01461 # endif /* SIOCGLIFNUM */
01462   if (ACE_OS::ioctl (handle, cmd, (caddr_t)&if_num) == -1)
01463     ACE_ERROR_RETURN ((LM_ERROR,
01464                        ACE_TEXT ("%p\n"),
01465                        ACE_TEXT ("ACE::count_interfaces:")
01466                        ACE_TEXT ("ioctl - SIOCGLIFNUM failed")),
01467                       -1);
01468 # if defined (SIOCGLIFNUM)
01469   how_many = if_num.lifn_count;
01470 # else
01471   how_many = if_num;
01472 # endif /* SIOCGLIFNUM */
01473 return 0;
01474 
01475 #elif (defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS)) && !defined (ACE_LACKS_NETWORKING)
01476   // Note: DEC CXX doesn't define "unix".  BSD compatible OS: HP UX,
01477   // AIX, SunOS 4.x perform some ioctls to retrieve ifconf list of
01478   // ifreq structs no SIOCGIFNUM on SunOS 4.x, so use guess and scan
01479   // algorithm
01480 
01481   // Probably hard to put this many ifs in a unix box..
01482   const int MAX_IF = 50;
01483 
01484   // HACK - set to an unreasonable number
01485   int num_ifs = MAX_IF;
01486 
01487   struct ifconf ifcfg;
01488   size_t ifreq_size = num_ifs * sizeof (struct ifreq);
01489   struct ifreq *p_ifs =
01490     (struct ifreq *) ACE_OS::malloc (ifreq_size);
01491 
01492   if (!p_ifs)
01493     {
01494       errno = ENOMEM;
01495       return -1;
01496     }
01497 
01498   ACE_OS::memset (p_ifs, 0, ifreq_size);
01499   ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
01500 
01501   ifcfg.ifc_req = p_ifs;
01502   ifcfg.ifc_len = ifreq_size;
01503 
01504   if (ACE_OS::ioctl (handle,
01505                      SIOCGIFCONF_CMD,
01506                      (caddr_t) &ifcfg) == -1)
01507     {
01508       ACE_OS::free (ifcfg.ifc_req);
01509       ACE_ERROR_RETURN ((LM_ERROR,
01510                          ACE_TEXT ("%p\n"),
01511                          ACE_TEXT ("ACE::count_interfaces:")
01512                          ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
01513                         -1);
01514     }
01515 
01516   int if_count = 0, i;
01517 
01518   // get if address out of ifreq buffers.  ioctl puts a blank-named
01519   // interface to mark the end of the returned interfaces.
01520   for (i = 0;
01521        i < num_ifs;
01522        i++)
01523     {
01524       /* In OpenBSD, the length of the list is returned. */
01525       ifcfg.ifc_len -= sizeof (struct ifreq);
01526       if (ifcfg.ifc_len < 0)
01527         break;
01528 
01529       ++if_count;
01530 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS)
01531       ++p_ifs;
01532 #else
01533      if (p_ifs->ifr_addr.sa_len <= sizeof (struct sockaddr))
01534        {
01535           ++p_ifs;
01536        }
01537        else
01538        {
01539           p_ifs = (struct ifreq *)
01540               (p_ifs->ifr_addr.sa_len + (caddr_t) &p_ifs->ifr_addr);
01541        }
01542 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
01543     }
01544 
01545   ACE_OS::free (ifcfg.ifc_req);
01546 
01547 # if defined (ACE_HAS_IPV6)
01548   FILE* fp = 0;
01549 
01550   if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
01551     {
01552       // Scan the lines according to the expected format but don't really read any input
01553       while (fscanf (fp, "%*32s %*02x %*02x %*02x %*02x %*8s\n") != EOF)
01554         {
01555           ++if_count;
01556         }
01557       ACE_OS::fclose (fp);
01558     }
01559 # endif /* ACE_HAS_IPV6 */
01560 
01561   how_many = if_count;
01562   return 0;
01563 #else
01564   ACE_UNUSED_ARG (handle);
01565   ACE_UNUSED_ARG (how_many);
01566   ACE_NOTSUP_RETURN (-1); // no implementation
01567 #endif /* sparc && SIOCGIFNUM */
01568 }
01569 
01570 // Routine to return a handle from which ioctl() requests can be made.
01571 
01572 ACE_HANDLE
01573 ACE::get_handle (void)
01574 {
01575   // Solaris 2.x
01576   ACE_HANDLE handle = ACE_INVALID_HANDLE;
01577 #if defined (sparc)
01578   handle = ACE_OS::open ("/dev/udp", O_RDONLY);
01579 #elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (__hpux) || (defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS)
01580   // Note: DEC CXX doesn't define "unix" BSD compatible OS: HP UX,
01581   // AIX, SunOS 4.x
01582 
01583   handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
01584 #endif /* sparc */
01585   return handle;
01586 }
01587 
01588 
01589 #if defined (ACE_HAS_IPV6)
01590 static int
01591 ip_check (int &ipvn_enabled, int pf)
01592 {
01593   // We only get to this point if ipvn_enabled was -1 in the caller.
01594   // Perform Double-Checked Locking Optimization.
01595   ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
01596                             *ACE_Static_Object_Lock::instance (), 0));
01597 
01598   if (ipvn_enabled == -1)
01599     {
01600       // Determine if the kernel has IPv6 support by attempting to
01601       // create a PF_INET socket and see if it fails.
01602       ACE_HANDLE const s = ACE_OS::socket (pf, SOCK_DGRAM, 0);
01603       if (s == ACE_INVALID_HANDLE)
01604         {
01605           ipvn_enabled = 0;
01606         }
01607       else
01608         {
01609           ipvn_enabled = 1;
01610           ACE_OS::closesocket (s);
01611         }
01612     }
01613   return ipvn_enabled;
01614 }
01615 #endif /* ACE_HAS_IPV6 */
01616 
01617 bool
01618 ACE::ipv4_enabled (void)
01619 {
01620 #if defined (ACE_HAS_IPV6)
01621   return static_cast<bool> (ace_ipv4_enabled == -1 ?
01622                             ::ip_check (ace_ipv4_enabled, PF_INET) :
01623                             ace_ipv4_enabled);
01624 #else
01625  // Assume it's always enabled since ACE requires some version of
01626  // TCP/IP to exist.
01627   return true;
01628 #endif  /* ACE_HAS_IPV6*/
01629 }
01630 
01631 int
01632 ACE::ipv6_enabled (void)
01633 {
01634 #if defined (ACE_HAS_IPV6)
01635   return ace_ipv6_enabled == -1 ?
01636     ::ip_check (ace_ipv6_enabled, PF_INET6) :
01637     ace_ipv6_enabled;
01638 #else /* ACE_HAS_IPV6 */
01639   return 0;
01640 #endif /* !ACE_HAS_IPV6 */
01641 }
01642 
01643 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:18:42 2010 for ACE by  doxygen 1.4.7