Correct feature names
[ACE_TAO.git] / ACE / ace / Sock_Connect.cpp
blob43606fa2f3cf61c334a1601785230db21da0c999
1 #include "ace/Sock_Connect.h"
2 #include "ace/INET_Addr.h"
3 #include "ace/Log_Category.h"
4 #include "ace/Handle_Set.h"
5 #include "ace/Auto_Ptr.h"
6 #include "ace/SString.h"
7 #include "ace/OS_Memory.h"
8 #include "ace/OS_NS_stdio.h"
9 #include "ace/ACE.h"
11 #if defined (sparc)
12 # include "ace/OS_NS_fcntl.h"
13 #endif // sparc
15 #include "ace/OS_NS_stdlib.h"
16 #include "ace/OS_NS_string.h"
17 #include "ace/OS_NS_sys_socket.h"
18 #include "ace/OS_NS_netdb.h"
19 #include "ace/OS_NS_unistd.h"
20 #include "ace/os_include/net/os_if.h"
22 #if defined (ACE_HAS_IPV6)
23 # include "ace/Guard_T.h"
24 # include "ace/Recursive_Thread_Mutex.h"
25 # if defined (_AIX)
26 # include /**/ <netinet/in6_var.h>
27 # endif /* _AIX */
28 #endif /* ACE_HAS_IPV6 */
30 #if defined (ACE_HAS_GETIFADDRS)
31 # include "ace/os_include/os_ifaddrs.h"
32 #endif /* ACE_HAS_GETIFADDRS */
34 #if defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x670) && defined (__RTP__) && defined (ACE_HAS_IPV6)
35 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
36 const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
37 const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
38 const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
39 #endif /* ACE_VXWORKS <= 0x670 && __RTP__ && ACE_HAS_IPV6 */
41 #if defined (ACE_HAS_WINCE)
42 #include /**/ <iphlpapi.h>
43 # if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && (_WIN32_WCE < 0x600) && defined (ACE_HAS_IPV6)
44 # include /**/ <ws2tcpip.h>
45 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
46 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
47 # endif
48 #endif // ACE_HAS_WINCE
50 #if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
51 # include "ace/OS_NS_stdio.h"
52 #endif
54 #if defined (ACE_HAS_IPV6)
56 // These defines support a generic usage based on
57 // the various SIGCF*IF ioctl implementations
59 # if defined (SIOCGLIFCONF)
60 # define SIOCGIFCONF_CMD SIOCGLIFCONF
61 # if defined (__hpux)
62 # define IFREQ if_laddrreq
63 # define IFCONF if_laddrconf
64 # define IFC_REQ iflc_req
65 # define IFC_LEN iflc_len
66 # define IFC_BUF iflc_buf
67 # define IFR_ADDR iflr_addr
68 # define IFR_NAME iflr_name
69 # define IFR_FLAGS iflr_flags
70 # undef SETFAMILY
71 # define SA_FAMILY sa_family
72 # else
73 # define IFREQ lifreq
74 # define IFCONF lifconf
75 # define IFC_REQ lifc_req
76 # define IFC_LEN lifc_len
77 # define IFC_BUF lifc_buf
78 # define IFR_ADDR lifr_addr
79 # define IFR_NAME lifr_name
80 # define IFR_FLAGS lifr_flags
81 # define SETFAMILY
82 # define IFC_FAMILY lifc_family
83 # define IFC_FLAGS lifc_flags
84 # define SA_FAMILY ss_family
85 # endif
86 # else
87 # define SIOCGIFCONF_CMD SIOCGIFCONF
88 # define IFREQ ifreq
89 # define IFCONF ifconf
90 # define IFC_REQ ifc_req
91 # define IFC_LEN ifc_len
92 # define IFC_BUF ifc_buf
93 # define IFR_ADDR ifr_addr
94 # define IFR_NAME ifr_name
95 # define IFR_FLAGS ifr_flags
96 # undef SETFAMILY
97 # define SA_FAMILY sa_family
98 # endif /* SIOCGLIFCONF */
100 # if defined (ACE_HAS_THREADS)
101 # include "ace/Object_Manager.h"
102 # endif /* ACE_HAS_THREADS */
104 namespace
106 // private:
107 // Used internally so not exported.
109 // Does this box have ipv4 turned on?
110 int ace_ipv4_enabled = -1;
112 // Does this box have ipv6 turned on?
113 int ace_ipv6_enabled = -1;
116 #else /* ACE_HAS_IPV6 */
117 # define SIOCGIFCONF_CMD SIOCGIFCONF
118 # define IFREQ ifreq
119 # define IFCONF ifconf
120 # define IFC_REQ ifc_req
121 # define IFC_LEN ifc_len
122 # define IFC_BUF ifc_buf
123 # define IFR_ADDR ifr_addr
124 # define IFR_NAME ifr_name
125 # define IFR_FLAGS ifr_flags
126 # undef SETFAMILY
127 # define SA_FAMILY sa_family
128 #endif /* ACE_HAS_IPV6 */
130 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
132 // Bind socket to an unused port.
135 ACE::bind_port (ACE_HANDLE handle, ACE_UINT32 ip_addr, int address_family)
137 ACE_TRACE ("ACE::bind_port");
139 ACE_INET_Addr addr;
141 #if defined (ACE_HAS_IPV6)
142 if (address_family != PF_INET6)
143 // What do we do if it is PF_"INET6? Since it's 4 bytes, it must be an
144 // IPV4 address. Is there a difference? Why is this test done? dhinton
145 #else /* ACE_HAS_IPV6 */
146 ACE_UNUSED_ARG (address_family);
147 #endif /* !ACE_HAS_IPV6 */
148 addr = ACE_INET_Addr ((u_short)0, ip_addr);
149 #if defined (ACE_HAS_IPV6)
150 else if (ip_addr != INADDR_ANY)
151 // address_family == PF_INET6 and a non default IP address means to bind
152 // to the IPv4-mapped IPv6 address
153 addr.set ((u_short)0, ip_addr, 1, 1);
154 #endif /* ACE_HAS_IPV6 */
156 // The OS kernel should select a free port for us.
157 return ACE_OS::bind (handle,
158 (sockaddr*)addr.get_addr(),
159 addr.get_size());
163 ACE::get_bcast_addr (ACE_UINT32 &bcast_addr,
164 const ACE_TCHAR *host_name,
165 ACE_UINT32 host_addr,
166 ACE_HANDLE handle)
168 ACE_TRACE ("ACE::get_bcast_addr");
170 #if defined (ACE_LACKS_GET_BCAST_ADDR)
171 ACE_UNUSED_ARG (bcast_addr);
172 ACE_UNUSED_ARG (host_name);
173 ACE_UNUSED_ARG (host_addr);
174 ACE_UNUSED_ARG (handle);
175 ACE_NOTSUP_RETURN (-1);
176 #elif !defined(ACE_WIN32) && !defined(__INTERIX)
177 ACE_HANDLE s = handle;
179 if (s == ACE_INVALID_HANDLE)
180 s = ACE_OS::socket (AF_INET, SOCK_STREAM, 0);
182 if (s == ACE_INVALID_HANDLE)
183 ACELIB_ERROR_RETURN ((LM_ERROR,
184 ACE_TEXT ("%p\n"),
185 ACE_TEXT ("ACE_OS::socket")),
186 -1);
188 struct ifconf ifc;
189 char buf[BUFSIZ];
191 ifc.ifc_len = sizeof buf;
192 ifc.ifc_buf = buf;
194 // Get interface structure and initialize the addresses using UNIX
195 // techniques
196 if (ACE_OS::ioctl (s, SIOCGIFCONF_CMD, (char *) &ifc) == -1)
197 ACELIB_ERROR_RETURN ((LM_ERROR,
198 ACE_TEXT ("%p\n"),
199 ACE_TEXT ("ACE::get_bcast_addr:")
200 ACE_TEXT ("ioctl (get interface configuration)")),
201 -1);
203 struct ifreq *ifr = ifc.ifc_req;
205 struct sockaddr_in ip_addr;
207 // Get host ip address if necessary.
208 if (host_name)
210 hostent *hp = ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name));
212 if (hp == 0)
213 return -1;
214 else
215 ACE_OS::memcpy ((char *) &ip_addr.sin_addr.s_addr,
216 # ifdef ACE_HOSTENT_H_ADDR
217 (char *) hp->ACE_HOSTENT_H_ADDR,
218 # else
219 (char *) hp->h_addr,
220 # endif
221 hp->h_length);
223 else
225 ACE_OS::memset ((void *) &ip_addr, 0, sizeof ip_addr);
226 ACE_OS::memcpy ((void *) &ip_addr.sin_addr,
227 (void*) &host_addr,
228 sizeof ip_addr.sin_addr);
231 #if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__)
232 for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
233 n--, ifr++)
234 #else
235 // see mk_broadcast@SOCK_Dgram_Bcast.cpp
236 for (int nbytes = ifc.ifc_len; nbytes >= (int) sizeof (struct ifreq) &&
237 ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
238 (nbytes >= (int) sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len) : 1);
239 ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
240 (nbytes -= sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len,
241 ifr = (struct ifreq *)
242 ((caddr_t) &ifr->ifr_addr + ifr->ifr_addr.sa_len)) :
243 (nbytes -= sizeof (struct ifreq), ifr++)))
244 #endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__) */
246 struct sockaddr_in if_addr;
248 // Compare host ip address with interface ip address.
249 ACE_OS::memcpy (&if_addr,
250 &ifr->ifr_addr,
251 sizeof if_addr);
253 if (ip_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
254 continue;
256 if (ifr->ifr_addr.sa_family != AF_INET)
258 ACELIB_ERROR ((LM_ERROR,
259 ACE_TEXT ("%p\n"),
260 ACE_TEXT ("ACE::get_bcast_addr:")
261 ACE_TEXT ("Not AF_INET")));
262 continue;
265 struct ifreq flags = *ifr;
266 struct ifreq if_req = *ifr;
268 if (ACE_OS::ioctl (s, SIOCGIFFLAGS, (char *) &flags) == -1)
270 ACELIB_ERROR ((LM_ERROR,
271 ACE_TEXT ("%p\n"),
272 ACE_TEXT ("ACE::get_bcast_addr:")
273 ACE_TEXT (" ioctl (get interface flags)")));
274 continue;
277 if (ACE_BIT_DISABLED (flags.ifr_flags, IFF_UP))
279 ACELIB_ERROR ((LM_ERROR,
280 ACE_TEXT ("%p\n"),
281 ACE_TEXT ("ACE::get_bcast_addr:")
282 ACE_TEXT ("Network interface is not up")));
283 continue;
286 if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_LOOPBACK))
287 continue;
289 if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_BROADCAST))
291 if (ACE_OS::ioctl (s,
292 SIOCGIFBRDADDR,
293 (char *) &if_req) == -1)
294 ACELIB_ERROR ((LM_ERROR,
295 ACE_TEXT ("%p\n"),
296 ACE_TEXT ("ACE::get_bcast_addr:")
297 ACE_TEXT ("ioctl (get broadaddr)")));
298 else
300 ACE_OS::memcpy (&ip_addr,
301 &if_req.ifr_broadaddr,
302 sizeof if_req.ifr_broadaddr);
304 ACE_OS::memcpy ((void *) &host_addr,
305 (void *) &ip_addr.sin_addr,
306 sizeof host_addr);
308 if (handle == ACE_INVALID_HANDLE)
309 ACE_OS::close (s);
311 bcast_addr = host_addr;
312 return 0;
315 else
316 ACELIB_ERROR ((LM_ERROR,
317 ACE_TEXT ("%p\n"),
318 ACE_TEXT ("ACE::get_bcast_addr:")
319 ACE_TEXT ("Broadcast is not enabled for this interface.")));
321 if (handle == ACE_INVALID_HANDLE)
322 ACE_OS::close (s);
324 bcast_addr = host_addr;
325 return 0;
328 return 0;
329 #else
330 ACE_UNUSED_ARG (handle);
331 ACE_UNUSED_ARG (host_addr);
332 ACE_UNUSED_ARG (host_name);
333 bcast_addr = (ACE_UINT32 (INADDR_BROADCAST));
334 return 0;
335 #endif /* !ACE_WIN32 && !__INTERIX */
339 ACE::get_fqdn (ACE_INET_Addr const & addr,
340 char hostname[],
341 size_t len)
343 #ifndef ACE_LACKS_GETNAMEINFO
345 const socklen_t addr_size =
346 # ifdef ACE_HAS_IPV6
347 (addr.get_type () == PF_INET6) ? sizeof (sockaddr_in6) :
348 # endif
349 sizeof (sockaddr_in);
351 if (ACE_OS::getnameinfo ((const sockaddr *) addr.get_addr (),
352 addr_size, hostname,
353 static_cast<ACE_SOCKET_LEN> (len),
354 0, 0, NI_NAMEREQD) != 0)
355 return -1;
357 if (ACE::debug ())
358 ACELIB_DEBUG ((LM_DEBUG,
359 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
360 ACE_TEXT ("canonical host name is %C\n"),
361 hostname));
363 return 0;
364 #else // below, ACE_LACKS_GETNAMEINFO
365 int h_error; // Not the same as errno!
366 hostent hentry;
367 ACE_HOSTENT_DATA buf;
369 char * ip_addr = 0;
370 int ip_addr_size = 0;
371 if (addr.get_type () == AF_INET)
373 sockaddr_in * const sock_addr =
374 reinterpret_cast<sockaddr_in *> (addr.get_addr ());
375 ip_addr_size = sizeof sock_addr->sin_addr;
376 ip_addr = (char*) &sock_addr->sin_addr;
378 # ifdef ACE_HAS_IPV6
379 else
381 sockaddr_in6 * sock_addr =
382 reinterpret_cast<sockaddr_in6 *> (addr.get_addr ());
384 ip_addr_size = sizeof sock_addr->sin6_addr;
385 ip_addr = (char*) &sock_addr->sin6_addr;
387 # endif /* ACE_HAS_IPV6 */
389 // get the host entry for the address in question
390 hostent * const hp = ACE_OS::gethostbyaddr_r (ip_addr,
391 ip_addr_size,
392 addr.get_type (),
393 &hentry,
394 buf,
395 &h_error);
397 // if it's not found in the host file or the DNS datase, there is nothing
398 // much we can do. embed the IP address
399 if (hp == 0 || hp->h_name == 0)
400 return -1;
402 if (ACE::debug())
403 ACELIB_DEBUG ((LM_DEBUG,
404 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
405 ACE_TEXT ("canonical host name is %C\n"),
406 hp->h_name));
408 // check if the canonical name is the FQDN
409 if (!ACE_OS::strchr(hp->h_name, '.'))
411 // list of address
412 char** p;
413 // list of aliases
414 char** q;
416 // for every address and for every alias within the address, check and
417 // see if we can locate a FQDN
418 for (p = hp->h_addr_list; *p != 0; ++p)
420 for (q = hp->h_aliases; *q != 0; ++q)
422 if (ACE_OS::strchr(*q, '.'))
424 // we got an FQDN from an alias. use this
425 if (ACE_OS::strlen (*q) >= len)
426 // the hostname is too huge to fit into a
427 // buffer of size MAXHOSTNAMELEN
428 // should we check other aliases as well
429 // before bailing out prematurely?
430 // for right now, let's do it. this (short name)
431 // is atleast better than embedding the IP
432 // address in the profile
433 continue;
435 if (ACE::debug ())
436 ACELIB_DEBUG ((LM_DEBUG,
437 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
438 ACE_TEXT ("found fqdn within alias as %C\n"),
439 *q));
440 ACE_OS::strcpy (hostname, *q);
442 return 0;
448 // The canonical name may be an FQDN when we reach here.
449 // Alternatively, the canonical name (a non FQDN) may be the best
450 // we can do.
451 if (ACE_OS::strlen (hp->h_name) >= len)
453 // The hostname is too large to fit into a buffer of size
454 // MAXHOSTNAMELEN.
455 return -2;
457 else
459 ACE_OS::strcpy (hostname, hp->h_name);
462 return 0;
463 #endif /* ACE_LACKS_GETNAMEINFO */
466 #if defined (ACE_WIN32)
468 static int
469 get_ip_interfaces_win32 (size_t &count,
470 ACE_INET_Addr *&addrs)
472 # if defined (ACE_HAS_WINCE) && defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
473 // moved the ACE_HAS_WINCE impl ahaid of ACE_HAS_WINSOCK2 because
474 // WINCE in fact has winsock2, but doesn't properly support the
475 // WSAIoctl for obtaining IPv6 address info.
476 PIP_ADAPTER_ADDRESSES AdapterAddresses = 0;
477 ULONG OutBufferLength = 0;
478 ULONG RetVal = 0;
479 unsigned char *octet_buffer = 0;
481 RetVal =
482 GetAdaptersAddresses(AF_UNSPEC,
485 AdapterAddresses,
486 &OutBufferLength);
488 if (RetVal != ERROR_BUFFER_OVERFLOW)
490 return -1;
493 ACE_NEW_RETURN (octet_buffer, unsigned char[OutBufferLength],-1);
494 AdapterAddresses = (IP_ADAPTER_ADDRESSES *)octet_buffer;
496 RetVal =
497 GetAdaptersAddresses(AF_UNSPEC,
500 AdapterAddresses,
501 &OutBufferLength);
503 if (RetVal != NO_ERROR)
505 delete [] octet_buffer;
506 return -1;
509 // If successful, output some information from the data we received
510 PIP_ADAPTER_ADDRESSES AdapterList = AdapterAddresses;
511 while (AdapterList)
513 if (AdapterList->OperStatus == IfOperStatusUp)
515 if (AdapterList->IfIndex != 0)
516 ++count;
517 if (AdapterList->Ipv6IfIndex != 0)
518 ++count;
520 AdapterList = AdapterList->Next;
523 AdapterList = AdapterAddresses;
525 ACE_NEW_RETURN (addrs, ACE_INET_Addr[count],-1);
526 count = 0;
527 for (AdapterList = AdapterAddresses;
528 AdapterList != 0;
529 AdapterList = AdapterList->Next)
531 if (AdapterList->OperStatus != IfOperStatusUp)
532 continue;
534 IP_ADAPTER_UNICAST_ADDRESS *uni = 0;
535 if (AdapterList->IfIndex != 0)
536 for (uni = AdapterList->FirstUnicastAddress;
537 uni != 0;
538 uni = uni->Next)
540 SOCKET_ADDRESS *sa_addr = &uni->Address;
541 if (sa_addr->lpSockaddr->sa_family == AF_INET)
543 sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
544 addrs[count].set(sin,sa_addr->iSockaddrLength);
545 ++count;
546 break;
549 if (AdapterList->Ipv6IfIndex != 0)
551 for (uni = AdapterList->FirstUnicastAddress;
552 uni != 0;
553 uni = uni->Next)
555 SOCKET_ADDRESS *sa_addr = &uni->Address;
556 if (sa_addr->lpSockaddr->sa_family == AF_INET6)
558 sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
559 addrs[count].set(sin,sa_addr->iSockaddrLength);
560 ++count;
561 break;
567 delete [] octet_buffer;
568 return 0;
570 # elif defined (ACE_HAS_PHARLAP)
571 // PharLap ETS has its own kernel routines to rummage through the device
572 // configs and extract the interface info, but only for Pharlap RT.
573 # if !defined (ACE_HAS_PHARLAP_RT)
574 ACE_NOTSUP_RETURN (-1);
575 # endif /* ACE_HAS_PHARLAP_RT */
577 // Locate all of the IP devices in the system, saving a DEVHANDLE
578 // for each. Then allocate the ACE_INET_Addrs needed and fetch all
579 // the IP addresses. To locate the devices, try the available
580 // device name roots and increment the device number until the
581 // kernel says there are no more of that type.
582 const size_t ACE_MAX_ETS_DEVICES = 64; // Arbitrary, but should be enough.
583 DEVHANDLE ip_dev[ACE_MAX_ETS_DEVICES];
584 EK_TCPIPCFG *devp = 0;
585 size_t i, j;
586 ACE_TCHAR dev_name[16];
588 count = 0;
589 for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
591 // Ethernet.
592 ACE_OS::sprintf (dev_name,
593 "ether%d",
595 ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
596 if (ip_dev[count] == 0)
597 break;
599 for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
601 // SLIP.
602 ACE_OS::sprintf (dev_name,
603 "sl%d",
605 ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
606 if (ip_dev[count] == 0)
607 break;
609 for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
611 // PPP.
612 ACE_OS::sprintf (dev_name,
613 "ppp%d",
615 ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
616 if (ip_dev[count] == 0)
617 break;
620 if (count > 0)
621 ACE_NEW_RETURN (addrs,
622 ACE_INET_Addr[count],
623 -1);
624 else
625 addrs = 0;
627 for (i = 0, j = 0; i < count; i++)
629 devp = EtsTCPGetDeviceCfg (ip_dev[i]);
630 if (devp != 0)
632 addrs[j].set (0,
633 devp->nwIPAddress,
634 0); // Already in net order.
635 ++j;
637 // There's no call to close the DEVHANDLE.
640 count = j;
641 if (count == 0 && addrs != 0)
643 delete [] addrs;
644 addrs = 0;
647 return 0;
650 # else
651 // All non-CE, non-Pharlap Windows. Must support Winsock2.
653 int i, n_interfaces, status;
655 INTERFACE_INFO info[64];
656 SOCKET sock;
658 // Get an (overlapped) DGRAM socket to test with
659 sock = socket (AF_INET, SOCK_DGRAM, 0);
660 if (sock == INVALID_SOCKET)
661 return -1;
663 DWORD bytes;
664 status = WSAIoctl(sock,
665 SIO_GET_INTERFACE_LIST,
668 info,
669 sizeof(info),
670 &bytes,
673 closesocket (sock);
674 if (status == SOCKET_ERROR)
675 return -1;
677 n_interfaces = bytes / sizeof(INTERFACE_INFO);
679 // SIO_GET_INTERFACE_LIST does not work for IPv6
680 // Instead recent versions of Winsock2 add the new opcode
681 // SIO_ADDRESS_LIST_QUERY.
682 // If this is not available forget about IPv6 local interfaces:-/
683 int n_v6_interfaces = 0;
685 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
687 LPSOCKET_ADDRESS_LIST v6info;
688 char *buffer;
689 DWORD buflen = sizeof (SOCKET_ADDRESS_LIST) + (63 * sizeof (SOCKET_ADDRESS));
690 ACE_NEW_RETURN (buffer,
691 char[buflen],
692 -1);
693 v6info = reinterpret_cast<LPSOCKET_ADDRESS_LIST> (buffer);
695 // Get an (overlapped) DGRAM socket to test with.
696 // If it fails only return IPv4 interfaces.
697 sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
698 if (sock != INVALID_SOCKET)
700 status = WSAIoctl(sock,
701 SIO_ADDRESS_LIST_QUERY,
704 v6info,
705 buflen,
706 &bytes,
709 closesocket (sock);
710 if (status != SOCKET_ERROR)
711 n_v6_interfaces = v6info->iAddressCount;
713 # endif /* ACE_HAS_IPV6 */
715 ACE_NEW_RETURN (addrs,
716 ACE_INET_Addr[n_interfaces + n_v6_interfaces],
717 -1);
719 // Now go through the list and transfer the good ones to the list of
720 // because they're down or don't have an IP address.
721 for (count = 0, i = 0; i < n_interfaces; ++i)
723 LPINTERFACE_INFO lpii;
724 struct sockaddr_in *addrp = 0;
726 lpii = &info[i];
727 if (!(lpii->iiFlags & IFF_UP))
728 continue;
730 // We assume IPv4 addresses here
731 addrp = reinterpret_cast<struct sockaddr_in *> (&lpii->iiAddress.AddressIn);
732 if (addrp->sin_addr.s_addr == INADDR_ANY)
733 continue;
735 // Set the address for the caller.
736 addrs[count].set(addrp, sizeof(sockaddr_in));
737 ++count;
740 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
741 // Now go through the list and transfer the good ones to the list of
742 // because they're down or don't have an IP address.
743 for (i = 0; i < n_v6_interfaces; i++)
745 struct sockaddr_in6 *addr6p;
747 if (v6info->Address[i].lpSockaddr->sa_family != AF_INET6)
748 continue;
750 addr6p = reinterpret_cast<struct sockaddr_in6 *> (v6info->Address[i].lpSockaddr);
751 if (IN6_IS_ADDR_UNSPECIFIED(&addr6p->sin6_addr)) // IN6ADDR_ANY?
752 continue;
754 // Set the address for the caller.
755 addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr6p), sizeof(sockaddr_in6));
756 ++count;
759 delete [] buffer; // Clean up
760 # endif /* ACE_HAS_IPV6 */
762 if (count == 0)
764 delete [] addrs;
765 addrs = 0;
768 return 0;
770 # endif /* ACE_HAS_WINCE */
773 #elif defined (ACE_HAS_GETIFADDRS)
774 static int
775 get_ip_interfaces_getifaddrs (size_t &count,
776 ACE_INET_Addr *&addrs)
778 // Take advantage of the BSD getifaddrs function that simplifies
779 // access to connected interfaces.
780 struct ifaddrs *ifap = 0;
781 struct ifaddrs *p_if = 0;
783 if (::getifaddrs (&ifap) != 0)
784 return -1;
786 // Count number of interfaces.
787 size_t num_ifs = 0;
788 for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
789 ++num_ifs;
791 // Now create and initialize output array.
792 ACE_NEW_RETURN (addrs,
793 ACE_INET_Addr[num_ifs],
794 -1); // caller must free
796 // Pull the address out of each INET interface. Not every interface
797 // is for IP, so be careful to count properly. When setting the
798 // INET_Addr, note that the 3rd arg (0) says to leave the byte order
799 // (already in net byte order from the interface structure) as is.
800 count = 0;
802 for (p_if = ifap;
803 p_if != 0;
804 p_if = p_if->ifa_next)
806 if (p_if->ifa_addr == 0)
807 continue;
809 // Check to see if it's up.
810 if ((p_if->ifa_flags & IFF_UP) != IFF_UP)
811 continue;
813 if (p_if->ifa_addr->sa_family == AF_INET)
815 struct sockaddr_in *addr =
816 reinterpret_cast<sockaddr_in *> (p_if->ifa_addr);
818 // Sometimes the kernel returns 0.0.0.0 as the interface
819 // address, skip those...
820 if (addr->sin_addr.s_addr != INADDR_ANY)
822 addrs[count].set ((u_short) 0,
823 addr->sin_addr.s_addr,
825 ++count;
828 # if defined (ACE_HAS_IPV6)
829 else if (p_if->ifa_addr->sa_family == AF_INET6)
831 struct sockaddr_in6 *addr =
832 reinterpret_cast<sockaddr_in6 *> (p_if->ifa_addr);
834 // Skip the ANY address
835 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr))
837 addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr),
838 sizeof(sockaddr_in6));
839 ++count;
842 # endif /* ACE_HAS_IPV6 */
845 ::freeifaddrs (ifap);
847 return 0;
849 #elif defined (__hpux)
850 static int
851 get_ip_interfaces_hpux (size_t &count,
852 ACE_INET_Addr *&addrs)
854 size_t num_ifs = 0;
855 size_t num_ifs_found = 0;
857 // Call specific routine as necessary.
858 ACE_HANDLE handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
859 ACE_HANDLE handle_ipv6 = ACE_INVALID_HANDLE;
861 if (handle == ACE_INVALID_HANDLE)
862 ACELIB_ERROR_RETURN ((LM_ERROR,
863 ACE_TEXT ("%p\n"),
864 ACE_TEXT ("ACE::get_ip_interfaces:open")),
865 -1);
867 int result = 0;
868 int tmp_how_many = 0;
870 result = ACE_OS::ioctl (handle,
871 SIOCGIFNUM,
872 (caddr_t) &tmp_how_many);
873 if (result != -1)
874 num_ifs = (size_t)tmp_how_many;
876 # if defined (ACE_HAS_IPV6)
877 tmp_how_many = 0;
878 handle_ipv6 = ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0);
879 result = ACE_OS::ioctl (handle_ipv6,
880 SIOCGLIFNUM,
881 (caddr_t) &tmp_how_many);
882 if (result != -1)
883 num_ifs += (size_t)tmp_how_many;
884 # endif
886 if (num_ifs == 0)
888 ACE_OS::close (handle);
889 ACE_OS::close (handle_ipv6);
890 return -1;
893 // ioctl likes to have an extra IFREQ structure to mark the end of
894 // what it returned, so increase the num_ifs by one.
895 ++num_ifs;
897 //HPUX requires two passes, First for IPv4, then for IPv6
899 struct ifreq *ifs = 0;
900 ACE_NEW_RETURN (ifs,
901 struct ifreq[num_ifs],
902 -1);
903 ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct ifreq));
905 ACE_Auto_Array_Ptr<struct ifreq> p_ifs (ifs);
907 if (p_ifs.get() == 0)
909 ACE_OS::close (handle);
910 ACE_OS::close (handle_ipv6);
911 errno = ENOMEM;
912 return -1;
915 struct ifconf ifcfg;
916 ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
918 ifcfg.ifc_req = p_ifs.get ();
919 ifcfg.ifc_len = num_ifs * sizeof (struct ifreq);
921 if (ACE_OS::ioctl (handle,
922 SIOCGIFCONF,
923 (char *) &ifcfg) == -1)
925 ACE_OS::close (handle);
926 ACELIB_ERROR_RETURN ((LM_ERROR,
927 ACE_TEXT ("%p\n"),
928 ACE_TEXT ("ACE::get_ip_interfaces:")
929 ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
930 -1);
933 ACE_OS::close (handle);
935 // Now create and initialize output array.
937 ACE_NEW_RETURN (addrs,
938 ACE_INET_Addr[num_ifs],
939 -1); // caller must free
941 struct ifreq *pcur = p_ifs.get ();
942 num_ifs_found = ifcfg.ifc_len / sizeof (struct ifreq); // get the number of returned ifs
944 for (size_t i = 0;
945 i < num_ifs_found;
946 i++)
948 struct sockaddr_in *addr =
949 reinterpret_cast<sockaddr_in *> (&pcur->ifr_addr);
950 if (addr->sin_addr.s_addr != 0)
952 addrs[count].set ((u_short) 0,
953 addr->sin_addr.s_addr,
955 ++count;
957 ++pcur;
960 # if defined (ACE_HAS_IPV6)
962 if (handle_ipv6 != ACE_INVALID_HANDLE)
964 struct if_laddrreq *lifs = 0;
965 ACE_NEW_RETURN (lifs,
966 struct if_laddrreq[num_ifs],
967 -1);
968 ACE_OS::memset (lifs, 0, num_ifs * sizeof (struct if_laddrreq));
970 ACE_Auto_Array_Ptr<struct if_laddrreq> p_lifs (lifs);
972 if (p_lifs.get() == 0)
974 ACE_OS::close (handle);
975 ACE_OS::close (handle_ipv6);
976 errno = ENOMEM;
977 return -1;
980 struct if_laddrconf lifcfg;
981 ACE_OS::memset (&lifcfg, 0, sizeof (struct if_laddrconf));
983 lifcfg.iflc_req = p_lifs.get ();
984 lifcfg.iflc_len = num_ifs * sizeof (struct if_laddrreq);
986 if (ACE_OS::ioctl (handle_ipv6,
987 SIOCGLIFCONF,
988 (char *) &lifcfg) == -1)
990 ACE_OS::close (handle);
991 ACELIB_ERROR_RETURN ((LM_ERROR,
992 ACE_TEXT ("%p\n"),
993 ACE_TEXT ("ACE::get_ip_interfaces:")
994 ACE_TEXT ("ioctl - SIOCGLIFCONF failed")),
995 -1);
998 ACE_OS::close (handle_ipv6);
1000 struct if_laddrreq *plcur = p_lifs.get ();
1001 num_ifs_found = lifcfg.iflc_len / sizeof (struct if_laddrreq);
1003 for (size_t i = 0;
1004 i < num_ifs_found;
1005 i++)
1007 struct sockaddr_in *addr =
1008 reinterpret_cast<sockaddr_in *> (&plcur->iflr_addr);
1009 if (!IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
1011 addrs[count].set(addr, sizeof(struct sockaddr_in6));
1012 ++count;
1014 ++plcur;
1017 # endif /* ACE_HAS_IPV6 */
1018 return 0;
1020 #elif defined (_AIX)
1021 static int
1022 get_ip_interfaces_aix (size_t &count,
1023 ACE_INET_Addr *&addrs)
1025 ACE_HANDLE handle = ACE::get_handle();
1026 size_t num_ifs = 0;
1027 struct ifconf ifc;
1029 if (handle == ACE_INVALID_HANDLE)
1030 ACELIB_ERROR_RETURN ((LM_ERROR,
1031 ACE_TEXT ("%p\n"),
1032 ACE_TEXT ("ACE::get_ip_interfaces_aix:")),
1033 -1);
1035 if (ACE_OS::ioctl (handle,
1036 SIOCGSIZIFCONF,
1037 (caddr_t)&ifc.ifc_len) == -1)
1039 ACE_OS::close (handle);
1040 ACELIB_ERROR_RETURN((LM_ERROR,
1041 ACE_TEXT ("%p\n"),
1042 ACE_TEXT ("get ifconf size")),
1043 -1);
1046 ACE_NEW_RETURN (ifc.ifc_buf,char [ifc.ifc_len], -1);
1048 ACE_Auto_Array_Ptr<char> safe_buf (ifc.ifc_buf);
1049 ACE_OS::memset (safe_buf.get(), 0, ifc.ifc_len);
1051 if (ACE_OS::ioctl(handle, SIOCGIFCONF, (caddr_t)&ifc) == -1)
1053 ACE_OS::close (handle);
1054 ACELIB_ERROR_RETURN((LM_ERROR,
1055 ACE_TEXT ("%p\n"),
1056 ACE_TEXT ("get ifconf")),
1057 -1);
1060 ACE_OS::close (handle);
1062 char *buf_start = safe_buf.get();
1063 char *buf_end = buf_start + ifc.ifc_len;
1065 num_ifs = 0;
1066 for (char *ptr = buf_start; ptr < buf_end; )
1068 struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
1069 ptr += IFNAMSIZ;
1070 ptr += req->ifr_addr.sa_len;
1071 if (req->ifr_addr.sa_family == AF_INET
1072 # if defined (ACE_HAS_IPV6)
1073 || req->ifr_addr.sa_family == AF_INET6
1074 # endif
1076 ++num_ifs;
1078 ACE_NEW_RETURN (addrs,ACE_INET_Addr[num_ifs], -1);
1080 for (char * ptr = buf_start; ptr < buf_end; )
1082 struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
1083 // skip the interface name
1084 ptr += IFNAMSIZ;
1085 if (req->ifr_addr.sa_family == AF_INET
1086 # if defined (ACE_HAS_IPV6)
1087 || req->ifr_addr.sa_family == AF_INET6
1088 # endif
1091 sockaddr_in *addr = (sockaddr_in*)&req->ifr_addr;
1092 addrs[count++].set(addr, addr->sin_len);
1094 ptr += req->ifr_addr.sa_len;
1097 return 0;
1100 #endif // ACE_WIN32 || ACE_HAS_GETIFADDRS || __hpux || _AIX
1103 // return an array of all configured IP interfaces on this host, count
1104 // rc = 0 on success (count == number of interfaces else -1 caller is
1105 // responsible for calling delete [] on parray
1108 ACE::get_ip_interfaces (size_t &count, ACE_INET_Addr *&addrs)
1110 ACE_TRACE ("ACE::get_ip_interfaces");
1112 count = 0;
1113 addrs = 0;
1115 #if defined (ACE_WIN32)
1116 return get_ip_interfaces_win32 (count, addrs);
1117 #elif defined (ACE_HAS_GETIFADDRS)
1118 return get_ip_interfaces_getifaddrs (count, addrs);
1119 #elif defined (__hpux)
1120 return get_ip_interfaces_hpux (count, addrs);
1121 #elif defined (_AIX)
1122 return get_ip_interfaces_aix (count, addrs);
1123 #elif (defined (__unix) || defined (__unix__) || defined (ACE_OPENVMS) || (defined (ACE_VXWORKS) && !defined (ACE_HAS_GETIFADDRS)) || defined (ACE_HAS_RTEMS)) && !defined (ACE_LACKS_NETWORKING)
1124 // COMMON (SVR4 and BSD) UNIX CODE
1126 // Call specific routine as necessary.
1127 ACE_HANDLE handle = ACE::get_handle();
1129 if (handle == ACE_INVALID_HANDLE)
1130 ACELIB_ERROR_RETURN ((LM_ERROR,
1131 ACE_TEXT ("%p\n"),
1132 ACE_TEXT ("ACE::get_ip_interfaces:open")),
1133 -1);
1135 size_t num_ifs = 0;
1137 if (ACE::count_interfaces (handle, num_ifs))
1139 ACE_OS::close (handle);
1140 return -1;
1143 // ioctl likes to have an extra ifreq structure to mark the end of
1144 // what it returned, so increase the num_ifs by one.
1145 ++num_ifs;
1147 struct IFREQ *ifs = 0;
1148 ACE_NEW_RETURN (ifs,
1149 struct IFREQ[num_ifs],
1150 -1);
1151 ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct IFREQ));
1153 ACE_Auto_Array_Ptr<struct IFREQ> p_ifs (ifs);
1155 if (p_ifs.get() == 0)
1157 ACE_OS::close (handle);
1158 errno = ENOMEM;
1159 return -1;
1162 struct IFCONF ifcfg;
1163 ACE_OS::memset (&ifcfg, 0, sizeof (struct IFCONF));
1165 # ifdef SETFAMILY
1166 ifcfg.IFC_FAMILY = AF_UNSPEC; // request all families be returned
1167 ifcfg.IFC_FLAGS = 0;
1168 # endif
1170 ifcfg.IFC_REQ = p_ifs.get ();
1171 ifcfg.IFC_LEN = num_ifs * sizeof (struct IFREQ);
1173 if (ACE_OS::ioctl (handle,
1174 SIOCGIFCONF_CMD,
1175 (caddr_t) &ifcfg) == -1)
1177 ACE_OS::close (handle);
1178 ACELIB_ERROR_RETURN ((LM_ERROR,
1179 ACE_TEXT ("%p\n"),
1180 ACE_TEXT ("ACE::get_ip_interfaces:")
1181 ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
1182 -1);
1185 ACE_OS::close (handle);
1187 // Now create and initialize output array.
1189 ACE_NEW_RETURN (addrs,
1190 ACE_INET_Addr[num_ifs],
1191 -1); // caller must free
1193 struct IFREQ *pcur = p_ifs.get ();
1194 size_t num_ifs_found = ifcfg.IFC_LEN / sizeof (struct IFREQ); // get the number of returned ifs
1196 // Pull the address out of each INET interface. Not every interface
1197 // is for IP, so be careful to count properly. When setting the
1198 // INET_Addr, note that the 3rd arg (0) says to leave the byte order
1199 // (already in net byte order from the interface structure) as is.
1200 count = 0;
1202 for (size_t i = 0;
1203 i < num_ifs_found;
1204 i++)
1206 if (pcur->IFR_ADDR.SA_FAMILY == AF_INET
1207 # if defined (ACE_HAS_IPV6)
1208 || pcur->IFR_ADDR.SA_FAMILY == AF_INET6
1209 # endif
1213 struct sockaddr_in *addr =
1214 reinterpret_cast<sockaddr_in *> (&pcur->IFR_ADDR);
1216 // Sometimes the kernel returns 0.0.0.0 as an IPv4 interface
1217 // address; skip those...
1218 if (addr->sin_addr.s_addr != 0
1219 # if defined (ACE_HAS_IPV6)
1220 || (addr->sin_family == AF_INET6 &&
1221 !IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
1222 # endif
1225 int addrlen = static_cast<int> (sizeof (struct sockaddr_in));
1226 # if defined (ACE_HAS_IPV6)
1227 if (addr->sin_family == AF_INET6)
1228 addrlen = static_cast<int> (sizeof (struct sockaddr_in6));
1229 # endif
1230 addrs[count].set (addr, addrlen);
1231 ++count;
1235 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS) && !defined (__Lynx__)
1236 ++pcur;
1237 #else
1238 if (pcur->ifr_addr.sa_len <= sizeof (struct sockaddr))
1240 ++pcur;
1242 else
1244 pcur = (struct ifreq *)
1245 (pcur->ifr_addr.sa_len + (caddr_t) &pcur->ifr_addr);
1247 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS) && !defined (__Lynx__) */
1250 # if defined (ACE_HAS_IPV6) && !defined (ACE_LACKS_FSCANF)
1251 // Retrieve IPv6 local interfaces by scanning /proc/net/if_inet6 if
1252 // it exists. If we cannot open it then ignore possible IPv6
1253 // interfaces, we did our best;-)
1254 FILE* fp = 0;
1255 char addr_p[8][5];
1256 char s_ipaddr[64];
1257 int scopeid;
1258 struct addrinfo hints, *res0;
1259 int error;
1261 ACE_OS::memset (&hints, 0, sizeof (hints));
1262 hints.ai_flags = AI_NUMERICHOST;
1263 hints.ai_family = AF_INET6;
1265 if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
1267 while (fscanf (fp,
1268 "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*8s\n",
1269 addr_p[0], addr_p[1], addr_p[2], addr_p[3],
1270 addr_p[4], addr_p[5], addr_p[6], addr_p[7], &scopeid) != EOF)
1272 // Format the address intoa proper IPv6 decimal address specification and
1273 // resolve the resulting text using getaddrinfo().
1275 const char* ip_fmt = "%s:%s:%s:%s:%s:%s:%s:%s%%%d";
1276 ACE_OS::snprintf (s_ipaddr, 64, ip_fmt,
1277 addr_p[0], addr_p[1], addr_p[2], addr_p[3],
1278 addr_p[4], addr_p[5], addr_p[6], addr_p[7],
1279 scopeid);
1281 error = ACE_OS::getaddrinfo (s_ipaddr, 0, &hints, &res0);
1282 if (error)
1283 continue;
1285 if (res0->ai_family == AF_INET6 &&
1286 !IN6_IS_ADDR_UNSPECIFIED (&reinterpret_cast<sockaddr_in6 *> (res0->ai_addr)->sin6_addr))
1288 addrs[count].set(reinterpret_cast<sockaddr_in *> (res0->ai_addr), res0->ai_addrlen);
1289 ++count;
1291 ACE_OS::freeaddrinfo (res0);
1294 ACE_OS::fclose (fp);
1296 # endif /* ACE_HAS_IPV6 && !ACE_LACKS_FSCANF */
1298 return 0;
1299 #else
1300 ACE_UNUSED_ARG (count);
1301 ACE_UNUSED_ARG (addrs);
1302 ACE_NOTSUP_RETURN (-1); // no implementation
1303 #endif /* ACE_WIN32 */
1306 // Helper routine for get_ip_interfaces, differs by UNIX platform so
1307 // put into own subroutine. perform some ioctls to retrieve ifconf
1308 // list of ifreq structs.
1311 ACE::count_interfaces (ACE_HANDLE handle, size_t &how_many)
1313 #if defined (SIOCGIFNUM)
1314 # if defined (SIOCGLIFNUM) && !defined (ACE_LACKS_STRUCT_LIFNUM)
1315 int cmd = SIOCGLIFNUM;
1316 struct lifnum if_num = {AF_UNSPEC,0,0};
1317 # else
1318 int cmd = SIOCGIFNUM;
1319 int if_num = 0;
1320 # endif /* SIOCGLIFNUM */
1321 if (ACE_OS::ioctl (handle, cmd, (caddr_t)&if_num) == -1)
1322 ACELIB_ERROR_RETURN ((LM_ERROR,
1323 ACE_TEXT ("%p\n"),
1324 ACE_TEXT ("ACE::count_interfaces:")
1325 ACE_TEXT ("ioctl - SIOCGLIFNUM failed")),
1326 -1);
1327 # if defined (SIOCGLIFNUM) && !defined (ACE_LACKS_STRUCT_LIFNUM)
1328 how_many = if_num.lifn_count;
1329 # else
1330 how_many = if_num;
1331 # endif /* SIOCGLIFNUM */
1332 return 0;
1334 #elif (defined (__unix) || defined (__unix__) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS) || (defined (ACE_VXWORKS) && !defined (ACE_HAS_GETIFADDRS))) && !defined (ACE_LACKS_NETWORKING)
1335 // Note: DEC CXX doesn't define "unix". BSD compatible OS: HP UX,
1336 // AIX, SunOS 4.x perform some ioctls to retrieve ifconf list of
1337 // ifreq structs no SIOCGIFNUM on SunOS 4.x, so use guess and scan
1338 // algorithm
1340 // Probably hard to put this many ifs in a unix box..
1341 int const MAX_INTERFACES = 50;
1343 // HACK - set to an unreasonable number
1344 int const num_ifs = MAX_INTERFACES;
1346 struct ifconf ifcfg;
1347 size_t ifreq_size = num_ifs * sizeof (struct ifreq);
1348 struct ifreq *p_ifs;
1350 #if defined (ACE_HAS_ALLOC_HOOKS)
1351 p_ifs = (struct IFREQ *)ACE_Allocator::instance()->malloc (ifreq_size);
1352 #else
1353 p_ifs = (struct ifreq *) ACE_OS::malloc (ifreq_size);
1354 #endif /* ACE_HAS_ALLOC_HOOKS */
1356 if (!p_ifs)
1358 errno = ENOMEM;
1359 return -1;
1362 ACE_OS::memset (p_ifs, 0, ifreq_size);
1363 ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
1365 ifcfg.ifc_req = p_ifs;
1366 ifcfg.ifc_len = ifreq_size;
1368 if (ACE_OS::ioctl (handle,
1369 SIOCGIFCONF_CMD,
1370 (caddr_t) &ifcfg) == -1)
1372 #if defined (ACE_HAS_ALLOC_HOOKS)
1373 ACE_Allocator::instance()->free (ifcfg.ifc_req);
1374 #else
1375 ACE_OS::free (ifcfg.ifc_req);
1376 #endif /* ACE_HAS_ALLOC_HOOKS */
1378 ACELIB_ERROR_RETURN ((LM_ERROR,
1379 ACE_TEXT ("%p\n"),
1380 ACE_TEXT ("ACE::count_interfaces:")
1381 ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
1382 -1);
1385 int if_count = 0;
1386 int i = 0;
1388 // get if address out of ifreq buffers. ioctl puts a blank-named
1389 // interface to mark the end of the returned interfaces.
1390 for (i = 0;
1391 i < num_ifs;
1392 i++)
1394 /* In OpenBSD, the length of the list is returned. */
1395 ifcfg.ifc_len -= sizeof (struct ifreq);
1396 if (ifcfg.ifc_len < 0)
1397 break;
1399 ++if_count;
1400 # if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS) && !defined (__Lynx__)
1401 ++p_ifs;
1402 # else
1403 if (p_ifs->ifr_addr.sa_len <= sizeof (struct sockaddr))
1405 ++p_ifs;
1407 else
1409 p_ifs = (struct ifreq *)
1410 (p_ifs->ifr_addr.sa_len + (caddr_t) &p_ifs->ifr_addr);
1412 # endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS) && !defined (__Lynx__) */
1415 #if defined (ACE_HAS_ALLOC_HOOKS)
1416 ACE_Allocator::instance()->free (ifcfg.ifc_req);
1417 #else
1418 ACE_OS::free (ifcfg.ifc_req);
1419 #endif /* ACE_HAS_ALLOC_HOOKS */
1421 # if defined (ACE_HAS_IPV6)
1422 FILE* fp = 0;
1424 if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
1426 // Scan the lines according to the expected format but don't really read any input
1427 while (fscanf (fp, "%*32s %*02x %*02x %*02x %*02x %*8s\n") != EOF)
1429 ++if_count;
1431 ACE_OS::fclose (fp);
1433 # endif /* ACE_HAS_IPV6 && !ACE_LACKS_FSCANF */
1435 how_many = if_count;
1436 return 0;
1437 #else
1438 ACE_UNUSED_ARG (handle);
1439 ACE_UNUSED_ARG (how_many);
1440 ACE_NOTSUP_RETURN (-1); // no implementation
1441 #endif /* sparc && SIOCGIFNUM */
1444 // Routine to return a handle from which ioctl() requests can be made.
1446 ACE_HANDLE
1447 ACE::get_handle (void)
1449 // Solaris 2.x
1450 ACE_HANDLE handle = ACE_INVALID_HANDLE;
1451 #if defined (sparc)
1452 handle = ACE_OS::open ("/dev/udp", O_RDONLY);
1453 #elif defined (__unix) || defined (__unix__) || defined (_AIX) || defined (__hpux) || (defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS)
1454 // Note: DEC CXX doesn't define "unix" BSD compatible OS: HP UX,
1455 // AIX, SunOS 4.x
1457 handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
1458 #endif /* sparc */
1459 return handle;
1463 #if defined (ACE_HAS_IPV6)
1464 static int
1465 ip_check (int &ipvn_enabled, int pf)
1467 // We only get to this point if ipvn_enabled was -1 in the caller.
1468 // Perform Double-Checked Locking Optimization.
1469 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
1470 *ACE_Static_Object_Lock::instance (), 0));
1472 if (ipvn_enabled == -1)
1475 #if defined (ACE_WIN32)
1476 // as of the release of Windows 2008, even hosts that have IPv6 interfaces disabled
1477 // will still permit the creation of a PF_INET6 socket, thus rendering the socket
1478 // creation test inconsistent. The recommended solution is to get the list of
1479 // endpoint addresses and see if any match the desired family.
1480 ACE_INET_Addr *if_addrs = 0;
1481 size_t if_cnt = 0;
1483 ipvn_enabled = 1; // assume enabled to avoid recursion during interface lookup.
1484 ACE::get_ip_interfaces (if_cnt, if_addrs);
1485 ipvn_enabled = 0;
1486 for (size_t i = 0; ipvn_enabled == 0 && i < if_cnt; i++)
1488 ipvn_enabled = (if_addrs[i].get_type () == pf);
1490 delete [] if_addrs;
1491 #else
1492 // Determine if the kernel has IPv6 support by attempting to
1493 // create a PF_INET6 socket and see if it fails.
1494 ACE_HANDLE const s = ACE_OS::socket (pf, SOCK_DGRAM, 0);
1495 if (s == ACE_INVALID_HANDLE)
1497 ipvn_enabled = 0;
1499 else
1501 ipvn_enabled = 1;
1502 ACE_OS::closesocket (s);
1504 #endif
1506 return ipvn_enabled;
1508 #endif /* ACE_HAS_IPV6 */
1510 bool
1511 ACE::ipv4_enabled (void)
1513 #if defined (ACE_HAS_IPV6)
1514 return static_cast<bool> (ace_ipv4_enabled == -1 ?
1515 ::ip_check (ace_ipv4_enabled, PF_INET) :
1516 ace_ipv4_enabled);
1517 #else
1518 // Assume it's always enabled since ACE requires some version of
1519 // TCP/IP to exist.
1520 return true;
1521 #endif /* ACE_HAS_IPV6*/
1525 ACE::ipv6_enabled (void)
1527 #if defined (ACE_HAS_IPV6)
1528 return ace_ipv6_enabled == -1 ?
1529 ::ip_check (ace_ipv6_enabled, PF_INET6) :
1530 ace_ipv6_enabled;
1531 #else /* ACE_HAS_IPV6 */
1532 return 0;
1533 #endif /* !ACE_HAS_IPV6 */
1536 ACE_END_VERSIONED_NAMESPACE_DECL