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"
10 #include "ace/OS_NS_stdlib.h"
11 #include "ace/OS_NS_string.h"
12 #include "ace/OS_NS_sys_socket.h"
13 #include "ace/OS_NS_netdb.h"
14 #include "ace/OS_NS_unistd.h"
15 #include "ace/os_include/net/os_if.h"
17 #if defined (ACE_HAS_IPV6)
18 # include "ace/Guard_T.h"
19 # include "ace/Recursive_Thread_Mutex.h"
20 #endif /* ACE_HAS_IPV6 */
22 #if defined (ACE_HAS_GETIFADDRS)
23 # include "ace/os_include/os_ifaddrs.h"
24 #endif /* ACE_HAS_GETIFADDRS */
26 #if defined (ACE_VXWORKS) && (ACE_VXWORKS <= 0x670) && defined (__RTP__) && defined (ACE_HAS_IPV6)
27 const struct in6_addr in6addr_any
= IN6ADDR_ANY_INIT
;
28 const struct in6_addr in6addr_nodelocal_allnodes
= IN6ADDR_NODELOCAL_ALLNODES_INIT
;
29 const struct in6_addr in6addr_linklocal_allnodes
= IN6ADDR_LINKLOCAL_ALLNODES_INIT
;
30 const struct in6_addr in6addr_linklocal_allrouters
= IN6ADDR_LINKLOCAL_ALLROUTERS_INIT
;
31 #endif /* ACE_VXWORKS <= 0x670 && __RTP__ && ACE_HAS_IPV6 */
33 #if defined (ACE_WIN32)
34 # include "ace/OS_NS_stdio.h"
37 #if defined (ACE_HAS_IPV6)
39 // These defines support a generic usage based on
40 // the various SIGCF*IF ioctl implementations
42 # if defined (SIOCGLIFCONF)
43 # define SIOCGIFCONF_CMD SIOCGLIFCONF
45 # define IFCONF lifconf
46 # define IFC_REQ lifc_req
47 # define IFC_LEN lifc_len
48 # define IFC_BUF lifc_buf
49 # define IFR_ADDR lifr_addr
50 # define IFR_NAME lifr_name
51 # define IFR_FLAGS lifr_flags
53 # define IFC_FAMILY lifc_family
54 # define IFC_FLAGS lifc_flags
55 # define SA_FAMILY ss_family
57 # define SIOCGIFCONF_CMD SIOCGIFCONF
59 # define IFCONF ifconf
60 # define IFC_REQ ifc_req
61 # define IFC_LEN ifc_len
62 # define IFC_BUF ifc_buf
63 # define IFR_ADDR ifr_addr
64 # define IFR_NAME ifr_name
65 # define IFR_FLAGS ifr_flags
67 # define SA_FAMILY sa_family
68 # endif /* SIOCGLIFCONF */
70 # if defined (ACE_HAS_THREADS)
71 # include "ace/Object_Manager.h"
72 # endif /* ACE_HAS_THREADS */
77 // Used internally so not exported.
79 // Does this box have ipv4 turned on?
80 int ace_ipv4_enabled
= -1;
82 // Does this box have ipv6 turned on?
83 int ace_ipv6_enabled
= -1;
85 #else /* ACE_HAS_IPV6 */
86 # define SIOCGIFCONF_CMD SIOCGIFCONF
88 # define IFCONF ifconf
89 # define IFC_REQ ifc_req
90 # define IFC_LEN ifc_len
91 # define IFC_BUF ifc_buf
92 # define IFR_ADDR ifr_addr
93 # define IFR_NAME ifr_name
94 # define IFR_FLAGS ifr_flags
96 # define SA_FAMILY sa_family
97 #endif /* ACE_HAS_IPV6 */
99 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
101 // Bind socket to an unused port.
104 ACE::bind_port (ACE_HANDLE handle
, ACE_UINT32 ip_addr
, int address_family
)
106 ACE_TRACE ("ACE::bind_port");
110 #if defined (ACE_HAS_IPV6)
111 if (address_family
!= PF_INET6
)
112 // What do we do if it is PF_"INET6? Since it's 4 bytes, it must be an
113 // IPV4 address. Is there a difference? Why is this test done? dhinton
114 #else /* ACE_HAS_IPV6 */
115 ACE_UNUSED_ARG (address_family
);
116 #endif /* !ACE_HAS_IPV6 */
117 addr
= ACE_INET_Addr ((u_short
)0, ip_addr
);
118 #if defined (ACE_HAS_IPV6)
119 else if (ip_addr
!= INADDR_ANY
)
120 // address_family == PF_INET6 and a non default IP address means to bind
121 // to the IPv4-mapped IPv6 address
122 addr
.set ((u_short
)0, ip_addr
, 1, 1);
123 #endif /* ACE_HAS_IPV6 */
125 // The OS kernel should select a free port for us.
126 return ACE_OS::bind (handle
,
127 (sockaddr
*)addr
.get_addr(),
132 ACE::get_bcast_addr (ACE_UINT32
&bcast_addr
,
133 const ACE_TCHAR
*host_name
,
134 ACE_UINT32 host_addr
,
137 ACE_TRACE ("ACE::get_bcast_addr");
139 #if defined (ACE_LACKS_GET_BCAST_ADDR)
140 ACE_UNUSED_ARG (bcast_addr
);
141 ACE_UNUSED_ARG (host_name
);
142 ACE_UNUSED_ARG (host_addr
);
143 ACE_UNUSED_ARG (handle
);
144 ACE_NOTSUP_RETURN (-1);
145 #elif !defined(ACE_WIN32)
146 ACE_HANDLE s
= handle
;
148 if (s
== ACE_INVALID_HANDLE
)
149 s
= ACE_OS::socket (AF_INET
, SOCK_STREAM
, 0);
151 if (s
== ACE_INVALID_HANDLE
)
152 ACELIB_ERROR_RETURN ((LM_ERROR
,
154 ACE_TEXT ("ACE_OS::socket")),
160 ifc
.ifc_len
= sizeof buf
;
163 // Get interface structure and initialize the addresses using UNIX
165 if (ACE_OS::ioctl (s
, SIOCGIFCONF_CMD
, (char *) &ifc
) == -1)
166 ACELIB_ERROR_RETURN ((LM_ERROR
,
168 ACE_TEXT ("ACE::get_bcast_addr:")
169 ACE_TEXT ("ioctl (get interface configuration)")),
172 struct ifreq
*ifr
= ifc
.ifc_req
;
174 struct sockaddr_in ip_addr
;
176 // Get host ip address if necessary.
179 hostent
*hp
= ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name
));
184 ACE_OS::memcpy ((char *) &ip_addr
.sin_addr
.s_addr
,
185 # ifdef ACE_HOSTENT_H_ADDR
186 (char *) hp
->ACE_HOSTENT_H_ADDR
,
194 ACE_OS::memset ((void *) &ip_addr
, 0, sizeof ip_addr
);
195 ACE_OS::memcpy ((void *) &ip_addr
.sin_addr
,
197 sizeof ip_addr
.sin_addr
);
200 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__)
201 for (int n
= ifc
.ifc_len
/ sizeof (struct ifreq
) ; n
> 0;
204 // see mk_broadcast@SOCK_Dgram_Bcast.cpp
205 for (int nbytes
= ifc
.ifc_len
; nbytes
>= (int) sizeof (struct ifreq
) &&
206 ((ifr
->ifr_addr
.sa_len
> sizeof (struct sockaddr
)) ?
207 (nbytes
>= (int) sizeof (ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
) : 1);
208 ((ifr
->ifr_addr
.sa_len
> sizeof (struct sockaddr
)) ?
209 (nbytes
-= sizeof (ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
,
210 ifr
= (struct ifreq
*)
211 ((caddr_t
) &ifr
->ifr_addr
+ ifr
->ifr_addr
.sa_len
)) :
212 (nbytes
-= sizeof (struct ifreq
), ifr
++)))
213 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__) */
215 struct sockaddr_in if_addr
;
217 // Compare host ip address with interface ip address.
218 ACE_OS::memcpy (&if_addr
,
222 if (ip_addr
.sin_addr
.s_addr
!= if_addr
.sin_addr
.s_addr
)
225 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
227 ACELIB_ERROR ((LM_ERROR
,
229 ACE_TEXT ("ACE::get_bcast_addr:")
230 ACE_TEXT ("Not AF_INET")));
234 struct ifreq flags
= *ifr
;
235 struct ifreq if_req
= *ifr
;
237 if (ACE_OS::ioctl (s
, SIOCGIFFLAGS
, (char *) &flags
) == -1)
239 ACELIB_ERROR ((LM_ERROR
,
241 ACE_TEXT ("ACE::get_bcast_addr:")
242 ACE_TEXT (" ioctl (get interface flags)")));
246 if (ACE_BIT_DISABLED (flags
.ifr_flags
, IFF_UP
))
248 ACELIB_ERROR ((LM_ERROR
,
250 ACE_TEXT ("ACE::get_bcast_addr:")
251 ACE_TEXT ("Network interface is not up")));
255 if (ACE_BIT_ENABLED (flags
.ifr_flags
, IFF_LOOPBACK
))
258 if (ACE_BIT_ENABLED (flags
.ifr_flags
, IFF_BROADCAST
))
260 if (ACE_OS::ioctl (s
,
262 (char *) &if_req
) == -1)
263 ACELIB_ERROR ((LM_ERROR
,
265 ACE_TEXT ("ACE::get_bcast_addr:")
266 ACE_TEXT ("ioctl (get broadaddr)")));
269 ACE_OS::memcpy (&ip_addr
,
270 &if_req
.ifr_broadaddr
,
271 sizeof if_req
.ifr_broadaddr
);
273 ACE_OS::memcpy ((void *) &host_addr
,
274 (void *) &ip_addr
.sin_addr
,
277 if (handle
== ACE_INVALID_HANDLE
)
280 bcast_addr
= host_addr
;
285 ACELIB_ERROR ((LM_ERROR
,
287 ACE_TEXT ("ACE::get_bcast_addr:")
288 ACE_TEXT ("Broadcast is not enabled for this interface.")));
290 if (handle
== ACE_INVALID_HANDLE
)
293 bcast_addr
= host_addr
;
299 ACE_UNUSED_ARG (handle
);
300 ACE_UNUSED_ARG (host_addr
);
301 ACE_UNUSED_ARG (host_name
);
302 bcast_addr
= (ACE_UINT32 (INADDR_BROADCAST
));
304 #endif /* !ACE_WIN32 */
308 ACE::get_fqdn (ACE_INET_Addr
const & addr
,
312 #ifndef ACE_LACKS_GETNAMEINFO
314 const socklen_t addr_size
=
316 (addr
.get_type () == PF_INET6
) ? sizeof (sockaddr_in6
) :
318 sizeof (sockaddr_in
);
320 if (ACE_OS::getnameinfo ((const sockaddr
*) addr
.get_addr (),
322 static_cast<ACE_SOCKET_LEN
> (len
),
323 0, 0, NI_NAMEREQD
) != 0)
327 ACELIB_DEBUG ((LM_DEBUG
,
328 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
329 ACE_TEXT ("canonical host name is %C\n"),
333 #else // below, ACE_LACKS_GETNAMEINFO
334 int h_error
; // Not the same as errno!
336 ACE_HOSTENT_DATA buf
;
339 int ip_addr_size
= 0;
340 if (addr
.get_type () == AF_INET
)
342 sockaddr_in
* const sock_addr
=
343 reinterpret_cast<sockaddr_in
*> (addr
.get_addr ());
344 ip_addr_size
= sizeof sock_addr
->sin_addr
;
345 ip_addr
= (char*) &sock_addr
->sin_addr
;
350 sockaddr_in6
* sock_addr
=
351 reinterpret_cast<sockaddr_in6
*> (addr
.get_addr ());
353 ip_addr_size
= sizeof sock_addr
->sin6_addr
;
354 ip_addr
= (char*) &sock_addr
->sin6_addr
;
356 # endif /* ACE_HAS_IPV6 */
358 // get the host entry for the address in question
359 hostent
* const hp
= ACE_OS::gethostbyaddr_r (ip_addr
,
366 // if it's not found in the host file or the DNS datase, there is nothing
367 // much we can do. embed the IP address
368 if (hp
== 0 || hp
->h_name
== 0)
372 ACELIB_DEBUG ((LM_DEBUG
,
373 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
374 ACE_TEXT ("canonical host name is %C\n"),
377 // check if the canonical name is the FQDN
378 if (!ACE_OS::strchr(hp
->h_name
, '.'))
385 // for every address and for every alias within the address, check and
386 // see if we can locate a FQDN
387 for (p
= hp
->h_addr_list
; *p
!= 0; ++p
)
389 for (q
= hp
->h_aliases
; *q
!= 0; ++q
)
391 if (ACE_OS::strchr(*q
, '.'))
393 // we got an FQDN from an alias. use this
394 if (ACE_OS::strlen (*q
) >= len
)
395 // the hostname is too huge to fit into a
396 // buffer of size MAXHOSTNAMELEN
397 // should we check other aliases as well
398 // before bailing out prematurely?
399 // for right now, let's do it. this (short name)
400 // is atleast better than embedding the IP
401 // address in the profile
405 ACELIB_DEBUG ((LM_DEBUG
,
406 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
407 ACE_TEXT ("found fqdn within alias as %C\n"),
409 ACE_OS::strcpy (hostname
, *q
);
417 // The canonical name may be an FQDN when we reach here.
418 // Alternatively, the canonical name (a non FQDN) may be the best
420 if (ACE_OS::strlen (hp
->h_name
) >= len
)
422 // The hostname is too large to fit into a buffer of size
428 ACE_OS::strcpy (hostname
, hp
->h_name
);
432 #endif /* ACE_LACKS_GETNAMEINFO */
435 #if defined (ACE_WIN32)
438 get_ip_interfaces_win32 (size_t &count
,
439 ACE_INET_Addr
*&addrs
)
441 int i
, n_interfaces
, status
;
443 INTERFACE_INFO info
[64];
446 // Get an (overlapped) DGRAM socket to test with
447 sock
= socket (AF_INET
, SOCK_DGRAM
, 0);
448 if (sock
== INVALID_SOCKET
)
452 status
= WSAIoctl(sock
,
453 SIO_GET_INTERFACE_LIST
,
462 if (status
== SOCKET_ERROR
)
465 n_interfaces
= bytes
/ sizeof(INTERFACE_INFO
);
467 // SIO_GET_INTERFACE_LIST does not work for IPv6
468 // Instead recent versions of Winsock2 add the new opcode
469 // SIO_ADDRESS_LIST_QUERY.
470 // If this is not available forget about IPv6 local interfaces:-/
471 int n_v6_interfaces
= 0;
473 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
475 LPSOCKET_ADDRESS_LIST v6info
;
477 DWORD buflen
= sizeof (SOCKET_ADDRESS_LIST
) + (63 * sizeof (SOCKET_ADDRESS
));
478 ACE_NEW_RETURN (buffer
,
481 v6info
= reinterpret_cast<LPSOCKET_ADDRESS_LIST
> (buffer
);
483 // Get an (overlapped) DGRAM socket to test with.
484 // If it fails only return IPv4 interfaces.
485 sock
= socket (AF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
486 if (sock
!= INVALID_SOCKET
)
488 status
= WSAIoctl(sock
,
489 SIO_ADDRESS_LIST_QUERY
,
498 if (status
!= SOCKET_ERROR
)
499 n_v6_interfaces
= v6info
->iAddressCount
;
501 # endif /* ACE_HAS_IPV6 */
503 ACE_NEW_RETURN (addrs
,
504 ACE_INET_Addr
[n_interfaces
+ n_v6_interfaces
],
507 // Now go through the list and transfer the good ones to the list of
508 // because they're down or don't have an IP address.
509 for (count
= 0, i
= 0; i
< n_interfaces
; ++i
)
511 LPINTERFACE_INFO lpii
;
512 struct sockaddr_in
*addrp
= 0;
515 if (!(lpii
->iiFlags
& IFF_UP
))
518 // We assume IPv4 addresses here
519 addrp
= reinterpret_cast<struct sockaddr_in
*> (&lpii
->iiAddress
.AddressIn
);
520 if (addrp
->sin_addr
.s_addr
== INADDR_ANY
)
523 // Set the address for the caller.
524 addrs
[count
].set(addrp
, sizeof(sockaddr_in
));
528 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
529 // Now go through the list and transfer the good ones to the list of
530 // because they're down or don't have an IP address.
531 for (i
= 0; i
< n_v6_interfaces
; i
++)
533 struct sockaddr_in6
*addr6p
;
535 if (v6info
->Address
[i
].lpSockaddr
->sa_family
!= AF_INET6
)
538 addr6p
= reinterpret_cast<struct sockaddr_in6
*> (v6info
->Address
[i
].lpSockaddr
);
539 if (IN6_IS_ADDR_UNSPECIFIED(&addr6p
->sin6_addr
)) // IN6ADDR_ANY?
542 // Set the address for the caller.
543 addrs
[count
].set(reinterpret_cast<struct sockaddr_in
*> (addr6p
), sizeof(sockaddr_in6
));
547 delete [] buffer
; // Clean up
548 # endif /* ACE_HAS_IPV6 */
559 #elif defined (ACE_HAS_GETIFADDRS)
561 get_ip_interfaces_getifaddrs (size_t &count
,
562 ACE_INET_Addr
*&addrs
)
564 // Take advantage of the BSD getifaddrs function that simplifies
565 // access to connected interfaces.
566 struct ifaddrs
*ifap
= 0;
567 struct ifaddrs
*p_if
= 0;
569 if (::getifaddrs (&ifap
) != 0)
572 // Count number of interfaces.
574 for (p_if
= ifap
; p_if
!= 0; p_if
= p_if
->ifa_next
)
577 // Now create and initialize output array.
578 ACE_NEW_RETURN (addrs
,
579 ACE_INET_Addr
[num_ifs
],
580 -1); // caller must free
582 // Pull the address out of each INET interface. Not every interface
583 // is for IP, so be careful to count properly. When setting the
584 // INET_Addr, note that the 3rd arg (0) says to leave the byte order
585 // (already in net byte order from the interface structure) as is.
590 p_if
= p_if
->ifa_next
)
592 if (p_if
->ifa_addr
== 0)
595 // Check to see if it's up.
596 if ((p_if
->ifa_flags
& IFF_UP
) != IFF_UP
)
599 if (p_if
->ifa_addr
->sa_family
== AF_INET
)
601 struct sockaddr_in
*addr
=
602 reinterpret_cast<sockaddr_in
*> (p_if
->ifa_addr
);
604 // Sometimes the kernel returns 0.0.0.0 as the interface
605 // address, skip those...
606 if (addr
->sin_addr
.s_addr
!= INADDR_ANY
)
608 addrs
[count
].set ((u_short
) 0,
609 addr
->sin_addr
.s_addr
,
614 # if defined (ACE_HAS_IPV6)
615 else if (p_if
->ifa_addr
->sa_family
== AF_INET6
)
617 struct sockaddr_in6
*addr
=
618 reinterpret_cast<sockaddr_in6
*> (p_if
->ifa_addr
);
620 // Skip the ANY address
621 if (!IN6_IS_ADDR_UNSPECIFIED(&addr
->sin6_addr
))
623 addrs
[count
].set(reinterpret_cast<struct sockaddr_in
*> (addr
),
624 sizeof(sockaddr_in6
));
628 # endif /* ACE_HAS_IPV6 */
631 ::freeifaddrs (ifap
);
635 #endif // ACE_WIN32 || ACE_HAS_GETIFADDRS
638 // return an array of all configured IP interfaces on this host, count
639 // rc = 0 on success (count == number of interfaces else -1 caller is
640 // responsible for calling delete [] on parray
643 ACE::get_ip_interfaces (size_t &count
, ACE_INET_Addr
*&addrs
)
645 ACE_TRACE ("ACE::get_ip_interfaces");
650 #if defined (ACE_WIN32)
651 return get_ip_interfaces_win32 (count
, addrs
);
652 #elif defined (ACE_HAS_GETIFADDRS)
653 return get_ip_interfaces_getifaddrs (count
, addrs
);
654 #elif (defined (__unix) || defined (__unix__) || (defined (ACE_VXWORKS) && !defined (ACE_HAS_GETIFADDRS))) && !defined (ACE_LACKS_NETWORKING)
655 // COMMON (SVR4 and BSD) UNIX CODE
657 // Call specific routine as necessary.
658 ACE_HANDLE handle
= ACE::get_handle();
660 if (handle
== ACE_INVALID_HANDLE
)
661 ACELIB_ERROR_RETURN ((LM_ERROR
,
663 ACE_TEXT ("ACE::get_ip_interfaces:open")),
668 if (ACE::count_interfaces (handle
, num_ifs
))
670 ACE_OS::close (handle
);
674 // ioctl likes to have an extra ifreq structure to mark the end of
675 // what it returned, so increase the num_ifs by one.
678 struct IFREQ
*ifs
= 0;
680 struct IFREQ
[num_ifs
],
682 ACE_OS::memset (ifs
, 0, num_ifs
* sizeof (struct IFREQ
));
684 ACE_Auto_Array_Ptr
<struct IFREQ
> p_ifs (ifs
);
686 if (p_ifs
.get() == 0)
688 ACE_OS::close (handle
);
694 ACE_OS::memset (&ifcfg
, 0, sizeof (struct IFCONF
));
697 ifcfg
.IFC_FAMILY
= AF_UNSPEC
; // request all families be returned
701 ifcfg
.IFC_REQ
= p_ifs
.get ();
702 ifcfg
.IFC_LEN
= num_ifs
* sizeof (struct IFREQ
);
704 if (ACE_OS::ioctl (handle
,
706 (caddr_t
) &ifcfg
) == -1)
708 ACE_OS::close (handle
);
709 ACELIB_ERROR_RETURN ((LM_ERROR
,
711 ACE_TEXT ("ACE::get_ip_interfaces:")
712 ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
716 ACE_OS::close (handle
);
718 // Now create and initialize output array.
720 ACE_NEW_RETURN (addrs
,
721 ACE_INET_Addr
[num_ifs
],
722 -1); // caller must free
724 struct IFREQ
*pcur
= p_ifs
.get ();
725 size_t num_ifs_found
= ifcfg
.IFC_LEN
/ sizeof (struct IFREQ
); // get the number of returned ifs
727 // Pull the address out of each INET interface. Not every interface
728 // is for IP, so be careful to count properly. When setting the
729 // INET_Addr, note that the 3rd arg (0) says to leave the byte order
730 // (already in net byte order from the interface structure) as is.
737 if (pcur
->IFR_ADDR
.SA_FAMILY
== AF_INET
738 # if defined (ACE_HAS_IPV6)
739 || pcur
->IFR_ADDR
.SA_FAMILY
== AF_INET6
744 struct sockaddr_in
*addr
=
745 reinterpret_cast<sockaddr_in
*> (&pcur
->IFR_ADDR
);
747 // Sometimes the kernel returns 0.0.0.0 as an IPv4 interface
748 // address; skip those...
749 if (addr
->sin_addr
.s_addr
!= 0
750 # if defined (ACE_HAS_IPV6)
751 || (addr
->sin_family
== AF_INET6
&&
752 !IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6
*>(addr
)->sin6_addr
))
756 int addrlen
= static_cast<int> (sizeof (struct sockaddr_in
));
757 # if defined (ACE_HAS_IPV6)
758 if (addr
->sin_family
== AF_INET6
)
759 addrlen
= static_cast<int> (sizeof (struct sockaddr_in6
));
761 addrs
[count
].set (addr
, addrlen
);
766 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__)
769 if (pcur
->ifr_addr
.sa_len
<= sizeof (struct sockaddr
))
775 pcur
= (struct ifreq
*)
776 (pcur
->ifr_addr
.sa_len
+ (caddr_t
) &pcur
->ifr_addr
);
778 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__) */
781 # if defined (ACE_HAS_IPV6) && !defined (ACE_LACKS_FSCANF)
782 // Retrieve IPv6 local interfaces by scanning /proc/net/if_inet6 if
783 // it exists. If we cannot open it then ignore possible IPv6
784 // interfaces, we did our best;-)
789 struct addrinfo hints
, *res0
;
792 ACE_OS::memset (&hints
, 0, sizeof (hints
));
793 hints
.ai_flags
= AI_NUMERICHOST
;
794 hints
.ai_family
= AF_INET6
;
796 if ((fp
= ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
799 "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*8s\n",
800 addr_p
[0], addr_p
[1], addr_p
[2], addr_p
[3],
801 addr_p
[4], addr_p
[5], addr_p
[6], addr_p
[7], &scopeid
) != EOF
)
803 // Format the address intoa proper IPv6 decimal address specification and
804 // resolve the resulting text using getaddrinfo().
806 const char* ip_fmt
= "%s:%s:%s:%s:%s:%s:%s:%s%%%d";
807 ACE_OS::snprintf (s_ipaddr
, 64, ip_fmt
,
808 addr_p
[0], addr_p
[1], addr_p
[2], addr_p
[3],
809 addr_p
[4], addr_p
[5], addr_p
[6], addr_p
[7],
812 error
= ACE_OS::getaddrinfo (s_ipaddr
, 0, &hints
, &res0
);
816 if (res0
->ai_family
== AF_INET6
&&
817 !IN6_IS_ADDR_UNSPECIFIED (&reinterpret_cast<sockaddr_in6
*> (res0
->ai_addr
)->sin6_addr
))
819 addrs
[count
].set(reinterpret_cast<sockaddr_in
*> (res0
->ai_addr
), res0
->ai_addrlen
);
822 ACE_OS::freeaddrinfo (res0
);
826 # endif /* ACE_HAS_IPV6 && !ACE_LACKS_FSCANF */
830 ACE_UNUSED_ARG (count
);
831 ACE_UNUSED_ARG (addrs
);
832 ACE_NOTSUP_RETURN (-1); // no implementation
833 #endif /* ACE_WIN32 */
836 // Helper routine for get_ip_interfaces, differs by UNIX platform so
837 // put into own subroutine. perform some ioctls to retrieve ifconf
838 // list of ifreq structs.
841 ACE::count_interfaces (ACE_HANDLE handle
, size_t &how_many
)
843 #if defined (SIOCGIFNUM)
844 # if defined (SIOCGLIFNUM)
845 int cmd
= SIOCGLIFNUM
;
846 struct lifnum if_num
= {AF_UNSPEC
,0,0};
848 int cmd
= SIOCGIFNUM
;
850 # endif /* SIOCGLIFNUM */
851 if (ACE_OS::ioctl (handle
, cmd
, (caddr_t
)&if_num
) == -1)
852 ACELIB_ERROR_RETURN ((LM_ERROR
,
854 ACE_TEXT ("ACE::count_interfaces:")
855 ACE_TEXT ("ioctl - SIOCGLIFNUM failed")),
857 # if defined (SIOCGLIFNUM)
858 how_many
= if_num
.lifn_count
;
861 # endif /* SIOCGLIFNUM */
864 #elif (defined (__unix) || defined (__unix__) || (defined (ACE_VXWORKS) && !defined (ACE_HAS_GETIFADDRS))) && !defined (ACE_LACKS_NETWORKING)
865 // Note: DEC CXX doesn't define "unix". BSD compatible OS: HP UX,
866 // SunOS 4.x perform some ioctls to retrieve ifconf list of
867 // ifreq structs no SIOCGIFNUM on SunOS 4.x, so use guess and scan
870 // Probably hard to put this many ifs in a unix box..
871 int const MAX_INTERFACES
= 50;
873 // HACK - set to an unreasonable number
874 int const num_ifs
= MAX_INTERFACES
;
877 size_t ifreq_size
= num_ifs
* sizeof (struct ifreq
);
880 #if defined (ACE_HAS_ALLOC_HOOKS)
881 p_ifs
= (struct IFREQ
*)ACE_Allocator::instance()->malloc (ifreq_size
);
883 p_ifs
= (struct ifreq
*) ACE_OS::malloc (ifreq_size
);
884 #endif /* ACE_HAS_ALLOC_HOOKS */
892 ACE_OS::memset (p_ifs
, 0, ifreq_size
);
893 ACE_OS::memset (&ifcfg
, 0, sizeof (struct ifconf
));
895 ifcfg
.ifc_req
= p_ifs
;
896 ifcfg
.ifc_len
= ifreq_size
;
898 if (ACE_OS::ioctl (handle
,
900 (caddr_t
) &ifcfg
) == -1)
902 #if defined (ACE_HAS_ALLOC_HOOKS)
903 ACE_Allocator::instance()->free (ifcfg
.ifc_req
);
905 ACE_OS::free (ifcfg
.ifc_req
);
906 #endif /* ACE_HAS_ALLOC_HOOKS */
908 ACELIB_ERROR_RETURN ((LM_ERROR
,
910 ACE_TEXT ("ACE::count_interfaces:")
911 ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
918 // get if address out of ifreq buffers. ioctl puts a blank-named
919 // interface to mark the end of the returned interfaces.
924 /* In OpenBSD, the length of the list is returned. */
925 ifcfg
.ifc_len
-= sizeof (struct ifreq
);
926 if (ifcfg
.ifc_len
< 0)
930 # if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__)
933 if (p_ifs
->ifr_addr
.sa_len
<= sizeof (struct sockaddr
))
939 p_ifs
= (struct ifreq
*)
940 (p_ifs
->ifr_addr
.sa_len
+ (caddr_t
) &p_ifs
->ifr_addr
);
942 # endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (__Lynx__) */
945 #if defined (ACE_HAS_ALLOC_HOOKS)
946 ACE_Allocator::instance()->free (ifcfg
.ifc_req
);
948 ACE_OS::free (ifcfg
.ifc_req
);
949 #endif /* ACE_HAS_ALLOC_HOOKS */
951 # if defined (ACE_HAS_IPV6)
954 if ((fp
= ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
956 // Scan the lines according to the expected format but don't really read any input
957 while (fscanf (fp
, "%*32s %*02x %*02x %*02x %*02x %*8s\n") != EOF
)
963 # endif /* ACE_HAS_IPV6 && !ACE_LACKS_FSCANF */
968 ACE_UNUSED_ARG (handle
);
969 ACE_UNUSED_ARG (how_many
);
970 ACE_NOTSUP_RETURN (-1); // no implementation
971 #endif /* sparc && SIOCGIFNUM */
974 // Routine to return a handle from which ioctl() requests can be made.
978 ACE_HANDLE handle
= ACE_INVALID_HANDLE
;
979 #if defined (__unix) || defined (__unix__) || (defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600))
980 // Note: DEC CXX doesn't define "unix" BSD compatible OS: SunOS 4.x
981 handle
= ACE_OS::socket (PF_INET
, SOCK_DGRAM
, 0);
986 #if defined (ACE_HAS_IPV6)
988 ip_check (int &ipvn_enabled
, int pf
)
990 // We only get to this point if ipvn_enabled was -1 in the caller.
991 // Perform Double-Checked Locking Optimization.
992 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex
, ace_mon
,
993 *ACE_Static_Object_Lock::instance (), 0));
995 if (ipvn_enabled
== -1)
997 #if defined (ACE_WIN32)
998 static bool recursing
= false;
999 if (recursing
) return 1;
1001 // as of the release of Windows 2008, even hosts that have IPv6 interfaces disabled
1002 // will still permit the creation of a PF_INET6 socket, thus rendering the socket
1003 // creation test inconsistent. The recommended solution is to get the list of
1004 // endpoint addresses and see if any match the desired family.
1005 ACE_INET_Addr
*if_addrs
= 0;
1008 // assume enabled to avoid recursion during interface lookup.
1010 ACE::get_ip_interfaces (if_cnt
, if_addrs
);
1014 for (size_t i
= 0; !found
&& i
< if_cnt
; i
++)
1016 found
= (if_addrs
[i
].get_type () == pf
);
1020 // If the list of interfaces is empty, we've tried too quickly. Assume enabled, but don't cache the result
1021 if (!if_cnt
) return 1;
1023 ipvn_enabled
= found
? 1 : 0;
1025 // Determine if the kernel has IPv6 support by attempting to
1026 // create a PF_INET6 socket and see if it fails.
1027 ACE_HANDLE
const s
= ACE_OS::socket (pf
, SOCK_DGRAM
, 0);
1028 if (s
== ACE_INVALID_HANDLE
)
1035 ACE_OS::closesocket (s
);
1039 return ipvn_enabled
;
1041 #endif /* ACE_HAS_IPV6 */
1044 ACE::ipv4_enabled ()
1046 #if defined (ACE_HAS_IPV6)
1047 return static_cast<bool> (ace_ipv4_enabled
== -1 ?
1048 ::ip_check (ace_ipv4_enabled
, PF_INET
) :
1051 // Assume it's always enabled since ACE requires some version of
1054 #endif /* ACE_HAS_IPV6*/
1058 ACE::ipv6_enabled ()
1060 #if defined (ACE_HAS_IPV6)
1061 return ace_ipv6_enabled
== -1 ?
1062 ::ip_check (ace_ipv6_enabled
, PF_INET6
) :
1064 #else /* ACE_HAS_IPV6 */
1066 #endif /* !ACE_HAS_IPV6 */
1069 ACE_END_VERSIONED_NAMESPACE_DECL