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/SString.h"
6 #include "ace/OS_Memory.h"
7 #include "ace/OS_NS_stdio.h"
9 #include "ace/OS_NS_stdlib.h"
10 #include "ace/OS_NS_string.h"
11 #include "ace/OS_NS_sys_socket.h"
12 #include "ace/OS_NS_netdb.h"
13 #include "ace/OS_NS_unistd.h"
14 #include "ace/os_include/net/os_if.h"
16 #if defined (ACE_HAS_IPV6)
17 # include "ace/Guard_T.h"
18 # include "ace/Recursive_Thread_Mutex.h"
19 #endif /* ACE_HAS_IPV6 */
21 #if defined (ACE_HAS_GETIFADDRS)
22 # include "ace/os_include/os_ifaddrs.h"
23 #endif /* ACE_HAS_GETIFADDRS */
25 #if defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x670) && defined (__RTP__) && defined (ACE_HAS_IPV6)
26 const struct in6_addr in6addr_any
= IN6ADDR_ANY_INIT
;
27 const struct in6_addr in6addr_nodelocal_allnodes
= IN6ADDR_NODELOCAL_ALLNODES_INIT
;
28 const struct in6_addr in6addr_linklocal_allnodes
= IN6ADDR_LINKLOCAL_ALLNODES_INIT
;
29 const struct in6_addr in6addr_linklocal_allrouters
= IN6ADDR_LINKLOCAL_ALLROUTERS_INIT
;
30 #endif /* ACE_VXWORKS <= 0x670 && __RTP__ && ACE_HAS_IPV6 */
32 #if defined (ACE_WIN32)
33 # include "ace/OS_NS_stdio.h"
36 #if defined (ACE_HAS_IPV6)
38 // These defines support a generic usage based on
39 // the various SIGCF*IF ioctl implementations
41 # if defined (SIOCGLIFCONF)
42 # define SIOCGIFCONF_CMD SIOCGLIFCONF
44 # define IFCONF lifconf
45 # define IFC_REQ lifc_req
46 # define IFC_LEN lifc_len
47 # define IFC_BUF lifc_buf
48 # define IFR_ADDR lifr_addr
49 # define IFR_NAME lifr_name
50 # define IFR_FLAGS lifr_flags
52 # define IFC_FAMILY lifc_family
53 # define IFC_FLAGS lifc_flags
54 # define SA_FAMILY ss_family
56 # define SIOCGIFCONF_CMD SIOCGIFCONF
58 # define IFCONF ifconf
59 # define IFC_REQ ifc_req
60 # define IFC_LEN ifc_len
61 # define IFC_BUF ifc_buf
62 # define IFR_ADDR ifr_addr
63 # define IFR_NAME ifr_name
64 # define IFR_FLAGS ifr_flags
66 # define SA_FAMILY sa_family
67 # endif /* SIOCGLIFCONF */
69 # if defined (ACE_HAS_THREADS)
70 # include "ace/Object_Manager.h"
71 # endif /* ACE_HAS_THREADS */
76 // Used internally so not exported.
78 // Does this box have ipv4 turned on?
79 int ace_ipv4_enabled
= -1;
81 // Does this box have ipv6 turned on?
82 int ace_ipv6_enabled
= -1;
84 #else /* ACE_HAS_IPV6 */
85 # define SIOCGIFCONF_CMD SIOCGIFCONF
87 # define IFCONF ifconf
88 # define IFC_REQ ifc_req
89 # define IFC_LEN ifc_len
90 # define IFC_BUF ifc_buf
91 # define IFR_ADDR ifr_addr
92 # define IFR_NAME ifr_name
93 # define IFR_FLAGS ifr_flags
95 # define SA_FAMILY sa_family
96 #endif /* ACE_HAS_IPV6 */
98 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
100 // Bind socket to an unused port.
103 ACE::bind_port (ACE_HANDLE handle
, ACE_UINT32 ip_addr
, int address_family
)
105 ACE_TRACE ("ACE::bind_port");
109 #if defined (ACE_HAS_IPV6)
110 if (address_family
!= PF_INET6
)
111 // What do we do if it is PF_"INET6? Since it's 4 bytes, it must be an
112 // IPV4 address. Is there a difference? Why is this test done? dhinton
113 #else /* ACE_HAS_IPV6 */
114 ACE_UNUSED_ARG (address_family
);
115 #endif /* !ACE_HAS_IPV6 */
116 addr
= ACE_INET_Addr ((u_short
)0, ip_addr
);
117 #if defined (ACE_HAS_IPV6)
118 else if (ip_addr
!= INADDR_ANY
)
119 // address_family == PF_INET6 and a non default IP address means to bind
120 // to the IPv4-mapped IPv6 address
121 addr
.set ((u_short
)0, ip_addr
, 1, 1);
122 #endif /* ACE_HAS_IPV6 */
124 // The OS kernel should select a free port for us.
125 return ACE_OS::bind (handle
,
126 (sockaddr
*)addr
.get_addr(),
131 ACE::get_bcast_addr (ACE_UINT32
&bcast_addr
,
132 const ACE_TCHAR
*host_name
,
133 ACE_UINT32 host_addr
,
136 ACE_TRACE ("ACE::get_bcast_addr");
138 #if defined (ACE_LACKS_GET_BCAST_ADDR)
139 ACE_UNUSED_ARG (bcast_addr
);
140 ACE_UNUSED_ARG (host_name
);
141 ACE_UNUSED_ARG (host_addr
);
142 ACE_UNUSED_ARG (handle
);
143 ACE_NOTSUP_RETURN (-1);
144 #elif !defined(ACE_WIN32)
145 ACE_HANDLE s
= handle
;
147 if (s
== ACE_INVALID_HANDLE
)
148 s
= ACE_OS::socket (AF_INET
, SOCK_STREAM
, 0);
150 if (s
== ACE_INVALID_HANDLE
)
151 ACELIB_ERROR_RETURN ((LM_ERROR
,
153 ACE_TEXT ("ACE_OS::socket")),
159 ifc
.ifc_len
= sizeof buf
;
162 // Get interface structure and initialize the addresses using UNIX
164 if (ACE_OS::ioctl (s
, SIOCGIFCONF_CMD
, (char *) &ifc
) == -1)
165 ACELIB_ERROR_RETURN ((LM_ERROR
,
167 ACE_TEXT ("ACE::get_bcast_addr:")
168 ACE_TEXT ("ioctl (get interface configuration)")),
171 struct ifreq
*ifr
= ifc
.ifc_req
;
173 struct sockaddr_in ip_addr
;
175 // Get host ip address if necessary.
178 hostent
*hp
= ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name
));
183 ACE_OS::memcpy ((char *) &ip_addr
.sin_addr
.s_addr
,
184 # ifdef ACE_HOSTENT_H_ADDR
185 (char *) hp
->ACE_HOSTENT_H_ADDR
,
193 ACE_OS::memset ((void *) &ip_addr
, 0, sizeof ip_addr
);
194 ACE_OS::memcpy ((void *) &ip_addr
.sin_addr
,
196 sizeof ip_addr
.sin_addr
);
199 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__)
200 for (int n
= ifc
.ifc_len
/ sizeof (struct ifreq
) ; n
> 0;
203 // see mk_broadcast@SOCK_Dgram_Bcast.cpp
204 for (int nbytes
= ifc
.ifc_len
; nbytes
>= (int) sizeof (struct ifreq
) &&
205 ((ifr
->ifr_addr
.sa_len
> sizeof (struct sockaddr
)) ?
206 (nbytes
>= (int) sizeof (ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
) : 1);
207 ((ifr
->ifr_addr
.sa_len
> sizeof (struct sockaddr
)) ?
208 (nbytes
-= sizeof (ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
,
209 ifr
= (struct ifreq
*)
210 ((caddr_t
) &ifr
->ifr_addr
+ ifr
->ifr_addr
.sa_len
)) :
211 (nbytes
-= sizeof (struct ifreq
), ifr
++)))
212 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__) */
214 struct sockaddr_in if_addr
;
216 // Compare host ip address with interface ip address.
217 ACE_OS::memcpy (&if_addr
,
221 if (ip_addr
.sin_addr
.s_addr
!= if_addr
.sin_addr
.s_addr
)
224 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
226 ACELIB_ERROR ((LM_ERROR
,
228 ACE_TEXT ("ACE::get_bcast_addr:")
229 ACE_TEXT ("Not AF_INET")));
233 struct ifreq flags
= *ifr
;
234 struct ifreq if_req
= *ifr
;
236 if (ACE_OS::ioctl (s
, SIOCGIFFLAGS
, (char *) &flags
) == -1)
238 ACELIB_ERROR ((LM_ERROR
,
240 ACE_TEXT ("ACE::get_bcast_addr:")
241 ACE_TEXT (" ioctl (get interface flags)")));
245 if (ACE_BIT_DISABLED (flags
.ifr_flags
, IFF_UP
))
247 ACELIB_ERROR ((LM_ERROR
,
249 ACE_TEXT ("ACE::get_bcast_addr:")
250 ACE_TEXT ("Network interface is not up")));
254 if (ACE_BIT_ENABLED (flags
.ifr_flags
, IFF_LOOPBACK
))
257 if (ACE_BIT_ENABLED (flags
.ifr_flags
, IFF_BROADCAST
))
259 if (ACE_OS::ioctl (s
,
261 (char *) &if_req
) == -1)
262 ACELIB_ERROR ((LM_ERROR
,
264 ACE_TEXT ("ACE::get_bcast_addr:")
265 ACE_TEXT ("ioctl (get broadaddr)")));
268 ACE_OS::memcpy (&ip_addr
,
269 &if_req
.ifr_broadaddr
,
270 sizeof if_req
.ifr_broadaddr
);
272 ACE_OS::memcpy ((void *) &host_addr
,
273 (void *) &ip_addr
.sin_addr
,
276 if (handle
== ACE_INVALID_HANDLE
)
279 bcast_addr
= host_addr
;
284 ACELIB_ERROR ((LM_ERROR
,
286 ACE_TEXT ("ACE::get_bcast_addr:")
287 ACE_TEXT ("Broadcast is not enabled for this interface.")));
289 if (handle
== ACE_INVALID_HANDLE
)
292 bcast_addr
= host_addr
;
298 ACE_UNUSED_ARG (handle
);
299 ACE_UNUSED_ARG (host_addr
);
300 ACE_UNUSED_ARG (host_name
);
301 bcast_addr
= (ACE_UINT32 (INADDR_BROADCAST
));
303 #endif /* !ACE_WIN32 */
307 ACE::get_fqdn (ACE_INET_Addr
const & addr
,
311 #ifndef ACE_LACKS_GETNAMEINFO
313 const socklen_t addr_size
=
315 (addr
.get_type () == PF_INET6
) ? sizeof (sockaddr_in6
) :
317 sizeof (sockaddr_in
);
319 if (ACE_OS::getnameinfo ((const sockaddr
*) addr
.get_addr (),
321 static_cast<ACE_SOCKET_LEN
> (len
),
322 0, 0, NI_NAMEREQD
) != 0)
326 ACELIB_DEBUG ((LM_DEBUG
,
327 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
328 ACE_TEXT ("canonical host name is %C\n"),
332 #else // below, ACE_LACKS_GETNAMEINFO
333 int h_error
; // Not the same as errno!
335 ACE_HOSTENT_DATA buf
;
338 int ip_addr_size
= 0;
339 if (addr
.get_type () == AF_INET
)
341 sockaddr_in
* const sock_addr
=
342 reinterpret_cast<sockaddr_in
*> (addr
.get_addr ());
343 ip_addr_size
= sizeof sock_addr
->sin_addr
;
344 ip_addr
= (char*) &sock_addr
->sin_addr
;
349 sockaddr_in6
* sock_addr
=
350 reinterpret_cast<sockaddr_in6
*> (addr
.get_addr ());
352 ip_addr_size
= sizeof sock_addr
->sin6_addr
;
353 ip_addr
= (char*) &sock_addr
->sin6_addr
;
355 # endif /* ACE_HAS_IPV6 */
357 // get the host entry for the address in question
358 hostent
* const hp
= ACE_OS::gethostbyaddr_r (ip_addr
,
365 // if it's not found in the host file or the DNS datase, there is nothing
366 // much we can do. embed the IP address
367 if (hp
== 0 || hp
->h_name
== 0)
371 ACELIB_DEBUG ((LM_DEBUG
,
372 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
373 ACE_TEXT ("canonical host name is %C\n"),
376 // check if the canonical name is the FQDN
377 if (!ACE_OS::strchr(hp
->h_name
, '.'))
384 // for every address and for every alias within the address, check and
385 // see if we can locate a FQDN
386 for (p
= hp
->h_addr_list
; *p
!= 0; ++p
)
388 for (q
= hp
->h_aliases
; *q
!= 0; ++q
)
390 if (ACE_OS::strchr(*q
, '.'))
392 // we got an FQDN from an alias. use this
393 if (ACE_OS::strlen (*q
) >= len
)
394 // the hostname is too huge to fit into a
395 // buffer of size MAXHOSTNAMELEN
396 // should we check other aliases as well
397 // before bailing out prematurely?
398 // for right now, let's do it. this (short name)
399 // is atleast better than embedding the IP
400 // address in the profile
404 ACELIB_DEBUG ((LM_DEBUG
,
405 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
406 ACE_TEXT ("found fqdn within alias as %C\n"),
408 ACE_OS::strcpy (hostname
, *q
);
416 // The canonical name may be an FQDN when we reach here.
417 // Alternatively, the canonical name (a non FQDN) may be the best
419 if (ACE_OS::strlen (hp
->h_name
) >= len
)
421 // The hostname is too large to fit into a buffer of size
427 ACE_OS::strcpy (hostname
, hp
->h_name
);
431 #endif /* ACE_LACKS_GETNAMEINFO */
434 #if defined (ACE_WIN32)
437 get_ip_interfaces_win32 (size_t &count
,
438 ACE_INET_Addr
*&addrs
)
440 int i
, n_interfaces
, status
;
442 INTERFACE_INFO info
[64];
445 // Get an (overlapped) DGRAM socket to test with
446 sock
= socket (AF_INET
, SOCK_DGRAM
, 0);
447 if (sock
== INVALID_SOCKET
)
451 status
= WSAIoctl(sock
,
452 SIO_GET_INTERFACE_LIST
,
461 if (status
== SOCKET_ERROR
)
464 n_interfaces
= bytes
/ sizeof(INTERFACE_INFO
);
466 // SIO_GET_INTERFACE_LIST does not work for IPv6
467 // Instead recent versions of Winsock2 add the new opcode
468 // SIO_ADDRESS_LIST_QUERY.
469 // If this is not available forget about IPv6 local interfaces:-/
470 int n_v6_interfaces
= 0;
472 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
474 LPSOCKET_ADDRESS_LIST v6info
;
476 DWORD buflen
= sizeof (SOCKET_ADDRESS_LIST
) + (63 * sizeof (SOCKET_ADDRESS
));
477 ACE_NEW_RETURN (buffer
,
480 v6info
= reinterpret_cast<LPSOCKET_ADDRESS_LIST
> (buffer
);
482 // Get an (overlapped) DGRAM socket to test with.
483 // If it fails only return IPv4 interfaces.
484 sock
= socket (AF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
485 if (sock
!= INVALID_SOCKET
)
487 status
= WSAIoctl(sock
,
488 SIO_ADDRESS_LIST_QUERY
,
497 if (status
!= SOCKET_ERROR
)
498 n_v6_interfaces
= v6info
->iAddressCount
;
500 # endif /* ACE_HAS_IPV6 */
502 ACE_NEW_RETURN (addrs
,
503 ACE_INET_Addr
[n_interfaces
+ n_v6_interfaces
],
506 // Now go through the list and transfer the good ones to the list of
507 // because they're down or don't have an IP address.
508 for (count
= 0, i
= 0; i
< n_interfaces
; ++i
)
510 LPINTERFACE_INFO lpii
;
511 struct sockaddr_in
*addrp
= 0;
514 if (!(lpii
->iiFlags
& IFF_UP
))
517 // We assume IPv4 addresses here
518 addrp
= reinterpret_cast<struct sockaddr_in
*> (&lpii
->iiAddress
.AddressIn
);
519 if (addrp
->sin_addr
.s_addr
== INADDR_ANY
)
522 // Set the address for the caller.
523 addrs
[count
].set(addrp
, sizeof(sockaddr_in
));
527 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
528 // Now go through the list and transfer the good ones to the list of
529 // because they're down or don't have an IP address.
530 for (i
= 0; i
< n_v6_interfaces
; i
++)
532 struct sockaddr_in6
*addr6p
;
534 if (v6info
->Address
[i
].lpSockaddr
->sa_family
!= AF_INET6
)
537 addr6p
= reinterpret_cast<struct sockaddr_in6
*> (v6info
->Address
[i
].lpSockaddr
);
538 if (IN6_IS_ADDR_UNSPECIFIED(&addr6p
->sin6_addr
)) // IN6ADDR_ANY?
541 // Set the address for the caller.
542 addrs
[count
].set(reinterpret_cast<struct sockaddr_in
*> (addr6p
), sizeof(sockaddr_in6
));
546 delete [] buffer
; // Clean up
547 # endif /* ACE_HAS_IPV6 */
558 #elif defined (ACE_HAS_GETIFADDRS)
560 get_ip_interfaces_getifaddrs (size_t &count
,
561 ACE_INET_Addr
*&addrs
)
563 // Take advantage of the BSD getifaddrs function that simplifies
564 // access to connected interfaces.
565 struct ifaddrs
*ifap
= 0;
566 struct ifaddrs
*p_if
= 0;
568 if (::getifaddrs (&ifap
) != 0)
571 // Count number of interfaces.
573 for (p_if
= ifap
; p_if
!= 0; p_if
= p_if
->ifa_next
)
576 // Now create and initialize output array.
577 ACE_NEW_RETURN (addrs
,
578 ACE_INET_Addr
[num_ifs
],
579 -1); // caller must free
581 // Pull the address out of each INET interface. Not every interface
582 // is for IP, so be careful to count properly. When setting the
583 // INET_Addr, note that the 3rd arg (0) says to leave the byte order
584 // (already in net byte order from the interface structure) as is.
589 p_if
= p_if
->ifa_next
)
591 if (p_if
->ifa_addr
== 0)
594 // Check to see if it's up.
595 if ((p_if
->ifa_flags
& IFF_UP
) != IFF_UP
)
598 if (p_if
->ifa_addr
->sa_family
== AF_INET
)
600 struct sockaddr_in
*addr
=
601 reinterpret_cast<sockaddr_in
*> (p_if
->ifa_addr
);
603 // Sometimes the kernel returns 0.0.0.0 as the interface
604 // address, skip those...
605 if (addr
->sin_addr
.s_addr
!= INADDR_ANY
)
607 addrs
[count
].set ((u_short
) 0,
608 addr
->sin_addr
.s_addr
,
613 # if defined (ACE_HAS_IPV6)
614 else if (p_if
->ifa_addr
->sa_family
== AF_INET6
)
616 struct sockaddr_in6
*addr
=
617 reinterpret_cast<sockaddr_in6
*> (p_if
->ifa_addr
);
619 // Skip the ANY address
620 if (!IN6_IS_ADDR_UNSPECIFIED(&addr
->sin6_addr
))
622 addrs
[count
].set(reinterpret_cast<struct sockaddr_in
*> (addr
),
623 sizeof(sockaddr_in6
));
627 # endif /* ACE_HAS_IPV6 */
630 ::freeifaddrs (ifap
);
634 #endif // ACE_WIN32 || ACE_HAS_GETIFADDRS
637 // return an array of all configured IP interfaces on this host, count
638 // rc = 0 on success (count == number of interfaces else -1 caller is
639 // responsible for calling delete [] on parray
642 ACE::get_ip_interfaces (size_t &count
, ACE_INET_Addr
*&addrs
)
644 ACE_TRACE ("ACE::get_ip_interfaces");
649 #if defined (ACE_WIN32)
650 return get_ip_interfaces_win32 (count
, addrs
);
651 #elif defined (ACE_HAS_GETIFADDRS)
652 return get_ip_interfaces_getifaddrs (count
, addrs
);
653 #elif (defined (__unix) || defined (__unix__) || (defined (ACE_VXWORKS) && !defined (ACE_HAS_GETIFADDRS))) && !defined (ACE_LACKS_NETWORKING)
654 // COMMON (SVR4 and BSD) UNIX CODE
656 // Call specific routine as necessary.
657 ACE_HANDLE handle
= ACE::get_handle();
659 if (handle
== ACE_INVALID_HANDLE
)
660 ACELIB_ERROR_RETURN ((LM_ERROR
,
662 ACE_TEXT ("ACE::get_ip_interfaces:open")),
667 if (ACE::count_interfaces (handle
, num_ifs
))
669 ACE_OS::close (handle
);
673 // ioctl likes to have an extra ifreq structure to mark the end of
674 // what it returned, so increase the num_ifs by one.
677 struct IFREQ
*ifs
= 0;
679 struct IFREQ
[num_ifs
],
681 ACE_OS::memset (ifs
, 0, num_ifs
* sizeof (struct IFREQ
));
683 std::unique_ptr
<struct IFREQ
[]> p_ifs (ifs
);
685 if (p_ifs
.get() == 0)
687 ACE_OS::close (handle
);
693 ACE_OS::memset (&ifcfg
, 0, sizeof (struct IFCONF
));
696 ifcfg
.IFC_FAMILY
= AF_UNSPEC
; // request all families be returned
700 ifcfg
.IFC_REQ
= p_ifs
.get ();
701 ifcfg
.IFC_LEN
= num_ifs
* sizeof (struct IFREQ
);
703 if (ACE_OS::ioctl (handle
,
705 (caddr_t
) &ifcfg
) == -1)
707 ACE_OS::close (handle
);
708 ACELIB_ERROR_RETURN ((LM_ERROR
,
710 ACE_TEXT ("ACE::get_ip_interfaces:")
711 ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
715 ACE_OS::close (handle
);
717 // Now create and initialize output array.
719 ACE_NEW_RETURN (addrs
,
720 ACE_INET_Addr
[num_ifs
],
721 -1); // caller must free
723 struct IFREQ
*pcur
= p_ifs
.get ();
724 size_t num_ifs_found
= ifcfg
.IFC_LEN
/ sizeof (struct IFREQ
); // get the number of returned ifs
726 // Pull the address out of each INET interface. Not every interface
727 // is for IP, so be careful to count properly. When setting the
728 // INET_Addr, note that the 3rd arg (0) says to leave the byte order
729 // (already in net byte order from the interface structure) as is.
736 if (pcur
->IFR_ADDR
.SA_FAMILY
== AF_INET
737 # if defined (ACE_HAS_IPV6)
738 || pcur
->IFR_ADDR
.SA_FAMILY
== AF_INET6
743 struct sockaddr_in
*addr
=
744 reinterpret_cast<sockaddr_in
*> (&pcur
->IFR_ADDR
);
746 // Sometimes the kernel returns 0.0.0.0 as an IPv4 interface
747 // address; skip those...
748 if (addr
->sin_addr
.s_addr
!= 0
749 # if defined (ACE_HAS_IPV6)
750 || (addr
->sin_family
== AF_INET6
&&
751 !IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6
*>(addr
)->sin6_addr
))
755 int addrlen
= static_cast<int> (sizeof (struct sockaddr_in
));
756 # if defined (ACE_HAS_IPV6)
757 if (addr
->sin_family
== AF_INET6
)
758 addrlen
= static_cast<int> (sizeof (struct sockaddr_in6
));
760 addrs
[count
].set (addr
, addrlen
);
765 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__)
768 if (pcur
->ifr_addr
.sa_len
<= sizeof (struct sockaddr
))
774 pcur
= (struct ifreq
*)
775 (pcur
->ifr_addr
.sa_len
+ (caddr_t
) &pcur
->ifr_addr
);
777 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__) */
780 # if defined (ACE_HAS_IPV6) && !defined (ACE_LACKS_FSCANF)
781 // Retrieve IPv6 local interfaces by scanning /proc/net/if_inet6 if
782 // it exists. If we cannot open it then ignore possible IPv6
783 // interfaces, we did our best;-)
788 struct addrinfo hints
, *res0
;
791 ACE_OS::memset (&hints
, 0, sizeof (hints
));
792 hints
.ai_flags
= AI_NUMERICHOST
;
793 hints
.ai_family
= AF_INET6
;
795 if ((fp
= ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
798 "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*8s\n",
799 addr_p
[0], addr_p
[1], addr_p
[2], addr_p
[3],
800 addr_p
[4], addr_p
[5], addr_p
[6], addr_p
[7], &scopeid
) != EOF
)
802 // Format the address intoa proper IPv6 decimal address specification and
803 // resolve the resulting text using getaddrinfo().
805 const char* ip_fmt
= "%s:%s:%s:%s:%s:%s:%s:%s%%%d";
806 ACE_OS::snprintf (s_ipaddr
, 64, ip_fmt
,
807 addr_p
[0], addr_p
[1], addr_p
[2], addr_p
[3],
808 addr_p
[4], addr_p
[5], addr_p
[6], addr_p
[7],
811 error
= ACE_OS::getaddrinfo (s_ipaddr
, 0, &hints
, &res0
);
815 if (res0
->ai_family
== AF_INET6
&&
816 !IN6_IS_ADDR_UNSPECIFIED (&reinterpret_cast<sockaddr_in6
*> (res0
->ai_addr
)->sin6_addr
))
818 addrs
[count
].set(reinterpret_cast<sockaddr_in
*> (res0
->ai_addr
), res0
->ai_addrlen
);
821 ACE_OS::freeaddrinfo (res0
);
825 # endif /* ACE_HAS_IPV6 && !ACE_LACKS_FSCANF */
829 ACE_UNUSED_ARG (count
);
830 ACE_UNUSED_ARG (addrs
);
831 ACE_NOTSUP_RETURN (-1); // no implementation
832 #endif /* ACE_WIN32 */
835 // Helper routine for get_ip_interfaces, differs by UNIX platform so
836 // put into own subroutine. perform some ioctls to retrieve ifconf
837 // list of ifreq structs.
840 ACE::count_interfaces (ACE_HANDLE handle
, size_t &how_many
)
842 #if defined (SIOCGIFNUM)
843 # if defined (SIOCGLIFNUM)
844 int cmd
= SIOCGLIFNUM
;
845 struct lifnum if_num
= {AF_UNSPEC
,0,0};
847 int cmd
= SIOCGIFNUM
;
849 # endif /* SIOCGLIFNUM */
850 if (ACE_OS::ioctl (handle
, cmd
, (caddr_t
)&if_num
) == -1)
851 ACELIB_ERROR_RETURN ((LM_ERROR
,
853 ACE_TEXT ("ACE::count_interfaces:")
854 ACE_TEXT ("ioctl - SIOCGLIFNUM failed")),
856 # if defined (SIOCGLIFNUM)
857 how_many
= if_num
.lifn_count
;
860 # endif /* SIOCGLIFNUM */
863 #elif (defined (__unix) || defined (__unix__) || (defined (ACE_VXWORKS) && !defined (ACE_HAS_GETIFADDRS))) && !defined (ACE_LACKS_NETWORKING)
864 // Note: DEC CXX doesn't define "unix". BSD compatible OS: HP UX,
865 // SunOS 4.x perform some ioctls to retrieve ifconf list of
866 // ifreq structs no SIOCGIFNUM on SunOS 4.x, so use guess and scan
869 // Probably hard to put this many ifs in a unix box..
870 int const MAX_INTERFACES
= 50;
872 // HACK - set to an unreasonable number
873 int const num_ifs
= MAX_INTERFACES
;
876 size_t ifreq_size
= num_ifs
* sizeof (struct ifreq
);
879 #if defined (ACE_HAS_ALLOC_HOOKS)
880 p_ifs
= (struct IFREQ
*)ACE_Allocator::instance()->malloc (ifreq_size
);
882 p_ifs
= (struct ifreq
*) ACE_OS::malloc (ifreq_size
);
883 #endif /* ACE_HAS_ALLOC_HOOKS */
891 ACE_OS::memset (p_ifs
, 0, ifreq_size
);
892 ACE_OS::memset (&ifcfg
, 0, sizeof (struct ifconf
));
894 ifcfg
.ifc_req
= p_ifs
;
895 ifcfg
.ifc_len
= ifreq_size
;
897 if (ACE_OS::ioctl (handle
,
899 (caddr_t
) &ifcfg
) == -1)
901 #if defined (ACE_HAS_ALLOC_HOOKS)
902 ACE_Allocator::instance()->free (ifcfg
.ifc_req
);
904 ACE_OS::free (ifcfg
.ifc_req
);
905 #endif /* ACE_HAS_ALLOC_HOOKS */
907 ACELIB_ERROR_RETURN ((LM_ERROR
,
909 ACE_TEXT ("ACE::count_interfaces:")
910 ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
917 // get if address out of ifreq buffers. ioctl puts a blank-named
918 // interface to mark the end of the returned interfaces.
923 /* In OpenBSD, the length of the list is returned. */
924 ifcfg
.ifc_len
-= sizeof (struct ifreq
);
925 if (ifcfg
.ifc_len
< 0)
929 # if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__)
932 if (p_ifs
->ifr_addr
.sa_len
<= sizeof (struct sockaddr
))
938 p_ifs
= (struct ifreq
*)
939 (p_ifs
->ifr_addr
.sa_len
+ (caddr_t
) &p_ifs
->ifr_addr
);
941 # endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__) */
944 #if defined (ACE_HAS_ALLOC_HOOKS)
945 ACE_Allocator::instance()->free (ifcfg
.ifc_req
);
947 ACE_OS::free (ifcfg
.ifc_req
);
948 #endif /* ACE_HAS_ALLOC_HOOKS */
950 # if defined (ACE_HAS_IPV6)
953 if ((fp
= ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
955 // Scan the lines according to the expected format but don't really read any input
956 while (fscanf (fp
, "%*32s %*02x %*02x %*02x %*02x %*8s\n") != EOF
)
962 # endif /* ACE_HAS_IPV6 && !ACE_LACKS_FSCANF */
967 ACE_UNUSED_ARG (handle
);
968 ACE_UNUSED_ARG (how_many
);
969 ACE_NOTSUP_RETURN (-1); // no implementation
970 #endif /* sparc && SIOCGIFNUM */
973 // Routine to return a handle from which ioctl() requests can be made.
977 ACE_HANDLE handle
= ACE_INVALID_HANDLE
;
978 #if defined (__unix) || defined (__unix__) || (defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600))
979 // Note: DEC CXX doesn't define "unix" BSD compatible OS: SunOS 4.x
980 handle
= ACE_OS::socket (PF_INET
, SOCK_DGRAM
, 0);
985 #if defined (ACE_HAS_IPV6)
987 ip_check (int &ipvn_enabled
, int pf
)
989 // We only get to this point if ipvn_enabled was -1 in the caller.
990 // Perform Double-Checked Locking Optimization.
991 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
,
992 *ACE_Static_Object_Lock::instance (), 0));
994 if (ipvn_enabled
== -1)
996 #if defined (ACE_WIN32)
997 static bool recursing
= false;
998 if (recursing
) return 1;
1000 // as of the release of Windows 2008, even hosts that have IPv6 interfaces disabled
1001 // will still permit the creation of a PF_INET6 socket, thus rendering the socket
1002 // creation test inconsistent. The recommended solution is to get the list of
1003 // endpoint addresses and see if any match the desired family.
1004 ACE_INET_Addr
*if_addrs
= 0;
1007 // assume enabled to avoid recursion during interface lookup.
1009 ACE::get_ip_interfaces (if_cnt
, if_addrs
);
1013 for (size_t i
= 0; !found
&& i
< if_cnt
; i
++)
1015 found
= (if_addrs
[i
].get_type () == pf
);
1019 // If the list of interfaces is empty, we've tried too quickly. Assume enabled, but don't cache the result
1020 if (!if_cnt
) return 1;
1022 ipvn_enabled
= found
? 1 : 0;
1024 // Determine if the kernel has IPv6 support by attempting to
1025 // create a PF_INET6 socket and see if it fails.
1026 ACE_HANDLE
const s
= ACE_OS::socket (pf
, SOCK_DGRAM
, 0);
1027 if (s
== ACE_INVALID_HANDLE
)
1034 ACE_OS::closesocket (s
);
1038 return ipvn_enabled
;
1040 #endif /* ACE_HAS_IPV6 */
1043 ACE::ipv4_enabled ()
1045 #if defined (ACE_HAS_IPV6)
1046 return static_cast<bool> (ace_ipv4_enabled
== -1 ?
1047 ::ip_check (ace_ipv4_enabled
, PF_INET
) :
1050 // Assume it's always enabled since ACE requires some version of
1053 #endif /* ACE_HAS_IPV6*/
1057 ACE::ipv6_enabled ()
1059 #if defined (ACE_HAS_IPV6)
1060 return ace_ipv6_enabled
== -1 ?
1061 ::ip_check (ace_ipv6_enabled
, PF_INET6
) :
1063 #else /* ACE_HAS_IPV6 */
1065 #endif /* !ACE_HAS_IPV6 */
1068 ACE_END_VERSIONED_NAMESPACE_DECL