[7297] Fixed profession spells sorting in trainer spell list at client.
[getmangos.git] / dep / ACE_wrappers / ace / Sock_Connect.cpp
blob99815ce797ccb38e74bc1082d53beb371255d2d8
1 // $Id: Sock_Connect.cpp 82276 2008-07-09 17:35:49Z jtc $
3 #include "ace/Sock_Connect.h"
4 #include "ace/INET_Addr.h"
5 #include "ace/Log_Msg.h"
6 #include "ace/Handle_Set.h"
7 #include "ace/Auto_Ptr.h"
8 #include "ace/SString.h"
9 #include "ace/OS_Memory.h"
10 #include "ace/OS_NS_stdio.h"
11 #include "ace/ACE.h"
13 #if defined (sparc)
14 # include "ace/OS_NS_fcntl.h"
15 #endif // sparc
17 #include "ace/OS_NS_stdlib.h"
18 #include "ace/OS_NS_string.h"
19 #include "ace/OS_NS_sys_socket.h"
20 #include "ace/OS_NS_netdb.h"
21 #include "ace/OS_NS_unistd.h"
22 #include "ace/os_include/net/os_if.h"
24 #if defined (ACE_HAS_IPV6)
25 # include "ace/Guard_T.h"
26 # include "ace/Recursive_Thread_Mutex.h"
27 # if defined (_AIX)
28 # include /**/ <netinet/in6_var.h>
29 # endif /* _AIX */
30 #endif /* ACE_HAS_IPV6 */
32 # if defined (ACE_HAS_GETIFADDRS)
33 # if defined (ACE_VXWORKS)
34 # include /**/ <net/ifaddrs.h>
35 # else
36 # include /**/ <ifaddrs.h>
37 # endif /*ACE_VXWORKS */
38 # endif /* ACE_HAS_GETIFADDRS */
40 #if defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600)
41 #include /**/ <inetLib.h>
42 #include /**/ <netinet/in_var.h>
43 #if defined (ACE_HAS_IPV6)
44 #include /**/ <ifLib.h>
45 extern "C" {
46 extern struct in_ifaddr* in_ifaddr;
47 extern LIST_HEAD(in_ifaddrhashhead, in_ifaddr) *in_ifaddrhashtbl;
49 #endif /* ACE_HAS_IPV6 */
50 #include "ace/OS_NS_stdio.h"
51 #endif /* ACE_VXWORKS < 0x600 */
53 #if defined (ACE_VXWORKS) && ((ACE_VXWORKS == 0x630) || (ACE_VXWORKS == 0x640)) && defined (__RTP__) && defined (ACE_HAS_IPV6)
54 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
55 const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
56 const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
57 const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
58 #endif /* ACE_VXWORKS == 0x630 && __RTP__ && ACE_HAS_IPV6 */
60 #if defined (ACE_HAS_WINCE)
61 #include /**/ <Iphlpapi.h>
62 // The following code is suggested by microsoft as a workaround to the fact
63 // that on Windows CE, these constants are exported as function addresses
64 // rather than simply values.
65 # include /**/ <ws2tcpip.h>
66 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
67 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
68 #endif // ACE_HAS_WINCE
70 #if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
71 # include "ace/OS_NS_stdio.h"
72 #endif
74 #if defined (ACE_HAS_IPV6)
76 // These defines support a generic usage based on
77 // the various SIGCF*IF ioctl implementations
79 # if defined (SIOCGLIFCONF)
80 # define SIOCGIFCONF_CMD SIOCGLIFCONF
81 # if defined (__hpux)
82 # define IFREQ if_laddrreq
83 # define IFCONF if_laddrconf
84 # define IFC_REQ iflc_req
85 # define IFC_LEN iflc_len
86 # define IFC_BUF iflc_buf
87 # define IFR_ADDR iflr_addr
88 # define IFR_NAME iflr_name
89 # define IFR_FLAGS iflr_flags
90 # undef SETFAMILY
91 # define SA_FAMILY sa_family
92 # else
93 # define IFREQ lifreq
94 # define IFCONF lifconf
95 # define IFC_REQ lifc_req
96 # define IFC_LEN lifc_len
97 # define IFC_BUF lifc_buf
98 # define IFR_ADDR lifr_addr
99 # define IFR_NAME lifr_name
100 # define IFR_FLAGS lifr_flags
101 # define SETFAMILY
102 # define IFC_FAMILY lifc_family
103 # define IFC_FLAGS lifc_flags
104 # define SA_FAMILY ss_family
105 # endif
106 # else
107 # define SIOCGIFCONF_CMD SIOCGIFCONF
108 # define IFREQ ifreq
109 # define IFCONF ifconf
110 # define IFC_REQ ifc_req
111 # define IFC_LEN ifc_len
112 # define IFC_BUF ifc_buf
113 # define IFR_ADDR ifr_addr
114 # define IFR_NAME ifr_name
115 # define IFR_FLAGS ifr_flags
116 # undef SETFAMILY
117 # define SA_FAMILY sa_family
118 # endif /* SIOCGLIFCONF */
120 # if defined (ACE_HAS_THREADS)
121 # include "ace/Object_Manager.h"
122 # endif /* ACE_HAS_THREADS */
124 namespace
126 // private:
127 // Used internally so not exported.
129 // Does this box have ipv4 turned on?
130 int ace_ipv4_enabled = -1;
132 // Does this box have ipv6 turned on?
133 int ace_ipv6_enabled = -1;
136 #else /* ACE_HAS_IPV6 */
137 # define SIOCGIFCONF_CMD SIOCGIFCONF
138 # define IFREQ ifreq
139 # define IFCONF ifconf
140 # define IFC_REQ ifc_req
141 # define IFC_LEN ifc_len
142 # define IFC_BUF ifc_buf
143 # define IFR_ADDR ifr_addr
144 # define IFR_NAME ifr_name
145 # define IFR_FLAGS ifr_flags
146 # undef SETFAMILY
147 # define SA_FAMILY sa_family
148 #endif /* ACE_HAS_IPV6 */
150 // This is a hack to work around a problem with Visual Age C++ 5 and 6 on AIX.
151 // Without this, the compiler auto-instantiates the ACE_Auto_Array_Ptr for
152 // ifreq (contained in this module) but only adds the #include for <net/if.h>
153 // and not the one for <sys/socket.h> which is also needed. Although we
154 // don't need the template defined here, it makes the compiler pull in
155 // <sys/socket.h> and the build runs clean.
156 #if defined (AIX) && defined (__IBMCPP__) && (__IBMCPP__ >= 500) && (__IBMCPP__ < 700)
157 static ACE_Auto_Array_Ptr<sockaddr> force_compiler_to_include_socket_h;
158 #endif /* AIX && __IBMCPP__ >= 500 */
161 ACE_RCSID (ace,
162 Sock_Connect,
163 "$Id: Sock_Connect.cpp 82276 2008-07-09 17:35:49Z jtc $")
166 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
168 // Bind socket to an unused port.
171 ACE::bind_port (ACE_HANDLE handle, ACE_UINT32 ip_addr, int address_family)
173 ACE_TRACE ("ACE::bind_port");
175 ACE_INET_Addr addr;
177 #if defined (ACE_HAS_IPV6)
178 if (address_family != PF_INET6)
179 // What do we do if it is PF_"INET6? Since it's 4 bytes, it must be an
180 // IPV4 address. Is there a difference? Why is this test done? dhinton
181 #else /* ACE_HAS_IPV6 */
182 ACE_UNUSED_ARG (address_family);
183 #endif /* !ACE_HAS_IPV6 */
184 addr = ACE_INET_Addr ((u_short)0, ip_addr);
185 #if defined (ACE_HAS_IPV6)
186 else if (ip_addr != INADDR_ANY)
187 // address_family == PF_INET6 and a non default IP address means to bind
188 // to the IPv4-mapped IPv6 address
189 addr.set ((u_short)0, ip_addr, 1, 1);
190 #endif /* ACE_HAS_IPV6 */
192 // The OS kernel should select a free port for us.
193 return ACE_OS::bind (handle,
194 (sockaddr*)addr.get_addr(),
195 addr.get_size());
199 ACE::get_bcast_addr (ACE_UINT32 &bcast_addr,
200 const ACE_TCHAR *host_name,
201 ACE_UINT32 host_addr,
202 ACE_HANDLE handle)
204 ACE_TRACE ("ACE::get_bcast_addr");
206 #if defined (ACE_LACKS_GET_BCAST_ADDR)
207 ACE_UNUSED_ARG (bcast_addr);
208 ACE_UNUSED_ARG (host_name);
209 ACE_UNUSED_ARG (host_addr);
210 ACE_UNUSED_ARG (handle);
211 ACE_NOTSUP_RETURN (-1);
212 #elif !defined(ACE_WIN32) && !defined(__INTERIX)
213 ACE_HANDLE s = handle;
215 if (s == ACE_INVALID_HANDLE)
216 s = ACE_OS::socket (AF_INET, SOCK_STREAM, 0);
218 if (s == ACE_INVALID_HANDLE)
219 ACE_ERROR_RETURN ((LM_ERROR,
220 ACE_TEXT ("%p\n"),
221 ACE_TEXT ("ACE_OS::socket")),
222 -1);
224 struct ifconf ifc;
225 char buf[BUFSIZ];
227 ifc.ifc_len = sizeof buf;
228 ifc.ifc_buf = buf;
230 // Get interface structure and initialize the addresses using UNIX
231 // techniques
232 if (ACE_OS::ioctl (s, SIOCGIFCONF_CMD, (char *) &ifc) == -1)
233 ACE_ERROR_RETURN ((LM_ERROR,
234 ACE_TEXT ("%p\n"),
235 ACE_TEXT ("ACE::get_bcast_addr:")
236 ACE_TEXT ("ioctl (get interface configuration)")),
237 -1);
239 struct ifreq *ifr = ifc.ifc_req;
241 struct sockaddr_in ip_addr;
243 // Get host ip address if necessary.
244 if (host_name)
246 hostent *hp = ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name));
248 if (hp == 0)
249 return -1;
250 else
251 #if !defined(_UNICOS)
252 ACE_OS::memcpy ((char *) &ip_addr.sin_addr.s_addr,
253 (char *) hp->h_addr,
254 hp->h_length);
255 #else /* _UNICOS */
257 ACE_UINT64 haddr; // a place to put the address
258 char * haddrp = (char *) &haddr; // convert to char pointer
259 ACE_OS::memcpy(haddrp,(char *) hp->h_addr,hp->h_length);
260 ip_addr.sin_addr.s_addr = haddr;
262 #endif /* ! _UNICOS */
264 else
266 ACE_OS::memset ((void *) &ip_addr, 0, sizeof ip_addr);
267 #if !defined(_UNICOS)
268 ACE_OS::memcpy ((void *) &ip_addr.sin_addr,
269 (void*) &host_addr,
270 sizeof ip_addr.sin_addr);
271 #else /* _UNICOS */
272 ip_addr.sin_addr.s_addr = host_addr; // just copy to the bitfield
273 #endif /* ! _UNICOS */
276 #if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
277 for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
278 n--, ifr++)
279 #else
280 // see mk_broadcast@SOCK_Dgram_Bcast.cpp
281 for (int nbytes = ifc.ifc_len; nbytes >= (int) sizeof (struct ifreq) &&
282 ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
283 (nbytes >= (int) sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len) : 1);
284 ((ifr->ifr_addr.sa_len > sizeof (struct sockaddr)) ?
285 (nbytes -= sizeof (ifr->ifr_name) + ifr->ifr_addr.sa_len,
286 ifr = (struct ifreq *)
287 ((caddr_t) &ifr->ifr_addr + ifr->ifr_addr.sa_len)) :
288 (nbytes -= sizeof (struct ifreq), ifr++)))
289 #endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
291 struct sockaddr_in if_addr;
293 // Compare host ip address with interface ip address.
294 ACE_OS::memcpy (&if_addr,
295 &ifr->ifr_addr,
296 sizeof if_addr);
298 if (ip_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
299 continue;
301 if (ifr->ifr_addr.sa_family != AF_INET)
303 ACE_ERROR ((LM_ERROR,
304 ACE_TEXT ("%p\n"),
305 ACE_TEXT ("ACE::get_bcast_addr:")
306 ACE_TEXT ("Not AF_INET")));
307 continue;
310 struct ifreq flags = *ifr;
311 struct ifreq if_req = *ifr;
313 if (ACE_OS::ioctl (s, SIOCGIFFLAGS, (char *) &flags) == -1)
315 ACE_ERROR ((LM_ERROR,
316 ACE_TEXT ("%p\n"),
317 ACE_TEXT ("ACE::get_bcast_addr:")
318 ACE_TEXT (" ioctl (get interface flags)")));
319 continue;
322 if (ACE_BIT_DISABLED (flags.ifr_flags, IFF_UP))
324 ACE_ERROR ((LM_ERROR,
325 ACE_TEXT ("%p\n"),
326 ACE_TEXT ("ACE::get_bcast_addr:")
327 ACE_TEXT ("Network interface is not up")));
328 continue;
331 if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_LOOPBACK))
332 continue;
334 if (ACE_BIT_ENABLED (flags.ifr_flags, IFF_BROADCAST))
336 if (ACE_OS::ioctl (s,
337 SIOCGIFBRDADDR,
338 (char *) &if_req) == -1)
339 ACE_ERROR ((LM_ERROR,
340 ACE_TEXT ("%p\n"),
341 ACE_TEXT ("ACE::get_bcast_addr:")
342 ACE_TEXT ("ioctl (get broadaddr)")));
343 else
345 ACE_OS::memcpy (&ip_addr,
346 &if_req.ifr_broadaddr,
347 sizeof if_req.ifr_broadaddr);
349 ACE_OS::memcpy ((void *) &host_addr,
350 (void *) &ip_addr.sin_addr,
351 sizeof host_addr);
353 if (handle == ACE_INVALID_HANDLE)
354 ACE_OS::close (s);
356 bcast_addr = host_addr;
357 return 0;
360 else
361 ACE_ERROR ((LM_ERROR,
362 ACE_TEXT ("%p\n"),
363 ACE_TEXT ("ACE::get_bcast_addr:")
364 ACE_TEXT ("Broadcast is not enable for this interface.")));
366 if (handle == ACE_INVALID_HANDLE)
367 ACE_OS::close (s);
369 bcast_addr = host_addr;
370 return 0;
373 return 0;
374 #else
375 ACE_UNUSED_ARG (handle);
376 ACE_UNUSED_ARG (host_addr);
377 ACE_UNUSED_ARG (host_name);
378 bcast_addr = (ACE_UINT32 (INADDR_BROADCAST));
379 return 0;
380 #endif /* !ACE_WIN32 && !__INTERIX */
384 ACE::get_fqdn (ACE_INET_Addr const & addr,
385 char hostname[],
386 size_t len)
388 int h_error; // Not the same as errno!
389 hostent hentry;
390 ACE_HOSTENT_DATA buf;
392 char * ip_addr = 0;
393 int ip_addr_size = 0;
394 if (addr.get_type () == AF_INET)
396 sockaddr_in * const sock_addr =
397 reinterpret_cast<sockaddr_in *> (addr.get_addr ());
398 ip_addr_size = sizeof sock_addr->sin_addr;
399 ip_addr = (char*) &sock_addr->sin_addr;
401 #ifdef ACE_HAS_IPV6
402 else
404 sockaddr_in6 * sock_addr =
405 reinterpret_cast<sockaddr_in6 *> (addr.get_addr ());
407 ip_addr_size = sizeof sock_addr->sin6_addr;
408 ip_addr = (char*) &sock_addr->sin6_addr;
410 #endif /* ACE_HAS_IPV6 */
412 // get the host entry for the address in question
413 hostent * const hp = ACE_OS::gethostbyaddr_r (ip_addr,
414 ip_addr_size,
415 addr.get_type (),
416 &hentry,
417 buf,
418 &h_error);
420 // if it's not found in the host file or the DNS datase, there is nothing
421 // much we can do. embed the IP address
422 if (hp == 0 || hp->h_name == 0)
423 return -1;
425 if (ACE::debug())
426 ACE_DEBUG ((LM_DEBUG,
427 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
428 ACE_TEXT ("canonical host name is %s\n"),
429 ACE_TEXT_CHAR_TO_TCHAR (hp->h_name)));
431 // check if the canonical name is the FQDN
432 if (!ACE_OS::strchr(hp->h_name, '.'))
434 // list of address
435 char** p;
436 // list of aliases
437 char** q;
439 // for every address and for every alias within the address, check and
440 // see if we can locate a FQDN
441 for (p = hp->h_addr_list; *p != 0; ++p)
443 for (q = hp->h_aliases; *q != 0; ++q)
445 if (ACE_OS::strchr(*q, '.'))
447 // we got an FQDN from an alias. use this
448 if (ACE_OS::strlen (*q) >= len)
449 // the hostname is too huge to fit into a
450 // buffer of size MAXHOSTNAMELEN
451 // should we check other aliases as well
452 // before bailing out prematurely?
453 // for right now, let's do it. this (short name)
454 // is atleast better than embedding the IP
455 // address in the profile
456 continue;
458 if (ACE::debug ())
459 ACE_DEBUG ((LM_DEBUG,
460 ACE_TEXT ("(%P|%t) - ACE::get_fqdn, ")
461 ACE_TEXT ("found fqdn within alias as %s\n"),
462 ACE_TEXT_CHAR_TO_TCHAR(*q)));
463 ACE_OS::strcpy (hostname, *q);
465 return 0;
471 // The canonical name may be an FQDN when we reach here.
472 // Alternatively, the canonical name (a non FQDN) may be the best
473 // we can do.
474 if (ACE_OS::strlen (hp->h_name) >= len)
476 // The hostname is too large to fit into a buffer of size
477 // MAXHOSTNAMELEN.
478 return -2;
480 else
482 ACE_OS::strcpy (hostname, hp->h_name);
485 return 0;
488 #if defined (ACE_WIN32)
490 static int
491 get_ip_interfaces_win32 (size_t &count,
492 ACE_INET_Addr *&addrs)
494 # if defined (ACE_HAS_WINCE)
495 // moved the ACE_HAS_WINCE impl ahaid of ACE_HAS_WINSOCK2 because
496 // WINCE in fact has winsock2, but doesn't properly support the
497 // WSAIoctl for obtaining IPv6 address info.
498 PIP_ADAPTER_ADDRESSES AdapterAddresses = 0;
499 ULONG OutBufferLength = 0;
500 ULONG RetVal = 0;
501 unsigned char *octet_buffer = 0;
503 RetVal =
504 GetAdaptersAddresses(AF_UNSPEC,
507 AdapterAddresses,
508 &OutBufferLength);
510 if (RetVal != ERROR_BUFFER_OVERFLOW)
512 return -1;
515 ACE_NEW_RETURN (octet_buffer, unsigned char[OutBufferLength],-1);
516 AdapterAddresses = (IP_ADAPTER_ADDRESSES *)octet_buffer;
518 RetVal =
519 GetAdaptersAddresses(AF_UNSPEC,
522 AdapterAddresses,
523 &OutBufferLength);
525 if (RetVal != NO_ERROR)
527 delete [] octet_buffer;
528 return -1;
531 // If successful, output some information from the data we received
532 PIP_ADAPTER_ADDRESSES AdapterList = AdapterAddresses;
533 while (AdapterList)
535 if (AdapterList->OperStatus == IfOperStatusUp)
537 if (AdapterList->IfIndex != 0)
538 ++count;
539 if (AdapterList->Ipv6IfIndex != 0)
540 ++count;
542 AdapterList = AdapterList->Next;
545 AdapterList = AdapterAddresses;
547 ACE_NEW_RETURN (addrs, ACE_INET_Addr[count],-1);
548 count = 0;
549 for (AdapterList = AdapterAddresses;
550 AdapterList != 0;
551 AdapterList = AdapterList->Next)
553 if (AdapterList->OperStatus != IfOperStatusUp)
554 continue;
556 IP_ADAPTER_UNICAST_ADDRESS *uni = 0;
557 if (AdapterList->IfIndex != 0)
558 for (uni = AdapterList->FirstUnicastAddress;
559 uni != 0;
560 uni = uni->Next)
562 SOCKET_ADDRESS *sa_addr = &uni->Address;
563 if (sa_addr->lpSockaddr->sa_family == AF_INET)
565 sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
566 addrs[count].set(sin,sa_addr->iSockaddrLength);
567 ++count;
568 break;
571 if (AdapterList->Ipv6IfIndex != 0)
573 for (uni = AdapterList->FirstUnicastAddress;
574 uni != 0;
575 uni = uni->Next)
577 SOCKET_ADDRESS *sa_addr = &uni->Address;
578 if (sa_addr->lpSockaddr->sa_family == AF_INET6)
580 sockaddr_in *sin = (sockaddr_in*)sa_addr->lpSockaddr;
581 addrs[count].set(sin,sa_addr->iSockaddrLength);
582 ++count;
583 break;
589 delete [] octet_buffer;
590 return 0;
592 # elif defined (ACE_HAS_PHARLAP)
593 // PharLap ETS has its own kernel routines to rummage through the device
594 // configs and extract the interface info, but only for Pharlap RT.
595 # if !defined (ACE_HAS_PHARLAP_RT)
596 ACE_NOTSUP_RETURN (-1);
597 # endif /* ACE_HAS_PHARLAP_RT */
599 // Locate all of the IP devices in the system, saving a DEVHANDLE
600 // for each. Then allocate the ACE_INET_Addrs needed and fetch all
601 // the IP addresses. To locate the devices, try the available
602 // device name roots and increment the device number until the
603 // kernel says there are no more of that type.
604 const size_t ACE_MAX_ETS_DEVICES = 64; // Arbitrary, but should be enough.
605 DEVHANDLE ip_dev[ACE_MAX_ETS_DEVICES];
606 EK_TCPIPCFG *devp;
607 size_t i, j;
608 ACE_TCHAR dev_name[16];
610 count = 0;
611 for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
613 // Ethernet.
614 ACE_OS::sprintf (dev_name,
615 "ether%d",
617 ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
618 if (ip_dev[count] == 0)
619 break;
621 for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
623 // SLIP.
624 ACE_OS::sprintf (dev_name,
625 "sl%d",
627 ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
628 if (ip_dev[count] == 0)
629 break;
631 for (i = 0; count < ACE_MAX_ETS_DEVICES; i++, ++count)
633 // PPP.
634 ACE_OS::sprintf (dev_name,
635 "ppp%d",
637 ip_dev[count] = EtsTCPGetDeviceHandle (dev_name);
638 if (ip_dev[count] == 0)
639 break;
642 if (count > 0)
643 ACE_NEW_RETURN (addrs,
644 ACE_INET_Addr[count],
645 -1);
646 else
647 addrs = 0;
649 for (i = 0, j = 0; i < count; i++)
651 devp = EtsTCPGetDeviceCfg (ip_dev[i]);
652 if (devp != 0)
654 addrs[j].set (0,
655 devp->nwIPAddress,
656 0); // Already in net order.
657 ++j;
659 // There's no call to close the DEVHANDLE.
662 count = j;
663 if (count == 0 && addrs != 0)
665 delete [] addrs;
666 addrs = 0;
669 return 0;
672 # else
673 // All non-CE, non-Pharlap Windows. Must support Winsock2.
675 int i, n_interfaces, status;
677 INTERFACE_INFO info[64];
678 SOCKET sock;
680 // Get an (overlapped) DGRAM socket to test with
681 sock = socket (AF_INET, SOCK_DGRAM, 0);
682 if (sock == INVALID_SOCKET)
683 return -1;
685 DWORD bytes;
686 status = WSAIoctl(sock,
687 SIO_GET_INTERFACE_LIST,
690 info,
691 sizeof(info),
692 &bytes,
695 closesocket (sock);
696 if (status == SOCKET_ERROR)
697 return -1;
699 n_interfaces = bytes / sizeof(INTERFACE_INFO);
701 // SIO_GET_INTERFACE_LIST does not work for IPv6
702 // Instead recent versions of Winsock2 add the new opcode
703 // SIO_ADDRESS_LIST_QUERY.
704 // If this is not available forget about IPv6 local interfaces:-/
705 int n_v6_interfaces = 0;
707 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
709 LPSOCKET_ADDRESS_LIST v6info;
710 char *buffer;
711 DWORD buflen = sizeof (SOCKET_ADDRESS_LIST) + (63 * sizeof (SOCKET_ADDRESS));
712 ACE_NEW_RETURN (buffer,
713 char[buflen],
714 -1);
715 v6info = reinterpret_cast<LPSOCKET_ADDRESS_LIST> (buffer);
717 // Get an (overlapped) DGRAM socket to test with.
718 // If it fails only return IPv4 interfaces.
719 sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
720 if (sock != INVALID_SOCKET)
722 status = WSAIoctl(sock,
723 SIO_ADDRESS_LIST_QUERY,
726 v6info,
727 buflen,
728 &bytes,
731 closesocket (sock);
732 if (status != SOCKET_ERROR)
733 n_v6_interfaces = v6info->iAddressCount;
735 # endif /* ACE_HAS_IPV6 */
737 ACE_NEW_RETURN (addrs,
738 ACE_INET_Addr[n_interfaces + n_v6_interfaces],
739 -1);
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 (count = 0, i = 0; i < n_interfaces; ++i)
745 LPINTERFACE_INFO lpii;
746 struct sockaddr_in *addrp = 0;
748 lpii = &info[i];
749 if (!(lpii->iiFlags & IFF_UP))
750 continue;
752 // We assume IPv4 addresses here
753 addrp = reinterpret_cast<struct sockaddr_in *> (&lpii->iiAddress.AddressIn);
754 if (addrp->sin_addr.s_addr == INADDR_ANY)
755 continue;
757 // Set the address for the caller.
758 addrs[count].set(addrp, sizeof(sockaddr_in));
759 ++count;
762 # if defined (ACE_HAS_IPV6) && defined (SIO_ADDRESS_LIST_QUERY)
763 // Now go through the list and transfer the good ones to the list of
764 // because they're down or don't have an IP address.
765 for (i = 0; i < n_v6_interfaces; i++)
767 struct sockaddr_in6 *addr6p;
769 if (v6info->Address[i].lpSockaddr->sa_family != AF_INET6)
770 continue;
772 addr6p = reinterpret_cast<struct sockaddr_in6 *> (v6info->Address[i].lpSockaddr);
773 if (IN6_IS_ADDR_UNSPECIFIED(&addr6p->sin6_addr)) // IN6ADDR_ANY?
774 continue;
776 // Set the address for the caller.
777 addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr6p), sizeof(sockaddr_in6));
778 ++count;
781 delete [] buffer; // Clean up
782 # endif /* ACE_HAS_IPV6 */
784 if (count == 0)
786 delete [] addrs;
787 addrs = 0;
790 return 0;
792 # endif /* ACE_HAS_WINCE */
794 #elif defined (ACE_HAS_GETIFADDRS)
795 static int
796 get_ip_interfaces_getifaddrs (size_t &count,
797 ACE_INET_Addr *&addrs)
799 // Take advantage of the BSD getifaddrs function that simplifies
800 // access to connected interfaces.
801 struct ifaddrs *ifap = 0;
802 struct ifaddrs *p_if = 0;
804 if (::getifaddrs (&ifap) != 0)
805 return -1;
807 // Count number of interfaces.
808 size_t num_ifs = 0;
809 for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
810 ++num_ifs;
812 // Now create and initialize output array.
813 ACE_NEW_RETURN (addrs,
814 ACE_INET_Addr[num_ifs],
815 -1); // caller must free
817 // Pull the address out of each INET interface. Not every interface
818 // is for IP, so be careful to count properly. When setting the
819 // INET_Addr, note that the 3rd arg (0) says to leave the byte order
820 // (already in net byte order from the interface structure) as is.
821 count = 0;
823 for (p_if = ifap;
824 p_if != 0;
825 p_if = p_if->ifa_next)
827 if (p_if->ifa_addr &&
828 p_if->ifa_addr->sa_family == AF_INET)
830 struct sockaddr_in *addr =
831 reinterpret_cast<sockaddr_in *> (p_if->ifa_addr);
833 // Sometimes the kernel returns 0.0.0.0 as the interface
834 // address, skip those...
835 if (addr->sin_addr.s_addr != INADDR_ANY)
837 addrs[count].set ((u_short) 0,
838 addr->sin_addr.s_addr,
840 ++count;
843 # if defined (ACE_HAS_IPV6)
844 else if (p_if->ifa_addr &&
845 p_if->ifa_addr->sa_family == AF_INET6)
847 struct sockaddr_in6 *addr =
848 reinterpret_cast<sockaddr_in6 *> (p_if->ifa_addr);
850 // Skip the ANY address
851 if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr))
853 addrs[count].set(reinterpret_cast<struct sockaddr_in *> (addr),
854 sizeof(sockaddr_in6));
855 ++count;
858 # endif /* ACE_HAS_IPV6 */
861 ::freeifaddrs (ifap);
863 return 0;
865 #elif defined (__hpux)
866 static int
867 get_ip_interfaces_hpux (size_t &count,
868 ACE_INET_Addr *&addrs)
870 size_t num_ifs = 0;
871 size_t num_ifs_found = 0;
873 // Call specific routine as necessary.
874 ACE_HANDLE handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
875 ACE_HANDLE handle_ipv6 = ACE_INVALID_HANDLE;
877 if (handle == ACE_INVALID_HANDLE)
878 ACE_ERROR_RETURN ((LM_ERROR,
879 ACE_TEXT ("%p\n"),
880 ACE_TEXT ("ACE::get_ip_interfaces:open")),
881 -1);
883 int result = 0;
884 int tmp_how_many = 0;
886 result = ACE_OS::ioctl (handle,
887 SIOCGIFNUM,
888 (caddr_t) &tmp_how_many);
889 if (result != -1)
890 num_ifs = (size_t)tmp_how_many;
892 # if defined (ACE_HAS_IPV6)
893 tmp_how_many = 0;
894 handle_ipv6 = ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0);
895 result = ACE_OS::ioctl (handle_ipv6,
896 SIOCGLIFNUM,
897 (caddr_t) &tmp_how_many);
898 if (result != -1)
899 num_ifs += (size_t)tmp_how_many;
900 # endif
902 if (num_ifs == 0)
904 ACE_OS::close (handle);
905 ACE_OS::close (handle_ipv6);
906 return -1;
909 // ioctl likes to have an extra IFREQ structure to mark the end of
910 // what it returned, so increase the num_ifs by one.
911 ++num_ifs;
913 //HPUX requires two passes, First for IPv4, then for IPv6
915 struct ifreq *ifs = 0;
916 ACE_NEW_RETURN (ifs,
917 struct ifreq[num_ifs],
918 -1);
919 ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct ifreq));
921 ACE_Auto_Array_Ptr<struct ifreq> p_ifs (ifs);
923 if (p_ifs.get() == 0)
925 ACE_OS::close (handle);
926 ACE_OS::close (handle_ipv6);
927 errno = ENOMEM;
928 return -1;
931 struct ifconf ifcfg;
932 ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
934 ifcfg.ifc_req = p_ifs.get ();
935 ifcfg.ifc_len = num_ifs * sizeof (struct ifreq);
937 if (ACE_OS::ioctl (handle,
938 SIOCGIFCONF,
939 (char *) &ifcfg) == -1)
941 ACE_OS::close (handle);
942 ACE_ERROR_RETURN ((LM_ERROR,
943 ACE_TEXT ("%p\n"),
944 ACE_TEXT ("ACE::get_ip_interfaces:")
945 ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
946 -1);
949 ACE_OS::close (handle);
951 // Now create and initialize output array.
953 ACE_NEW_RETURN (addrs,
954 ACE_INET_Addr[num_ifs],
955 -1); // caller must free
957 struct ifreq *pcur = p_ifs.get ();
958 num_ifs_found = ifcfg.ifc_len / sizeof (struct ifreq); // get the number of returned ifs
960 for (size_t i = 0;
961 i < num_ifs_found;
962 i++)
964 struct sockaddr_in *addr =
965 reinterpret_cast<sockaddr_in *> (&pcur->ifr_addr);
966 if (addr->sin_addr.s_addr != 0)
968 addrs[count].set ((u_short) 0,
969 addr->sin_addr.s_addr,
971 ++count;
973 ++pcur;
976 # if defined (ACE_HAS_IPV6)
978 if (handle_ipv6 != ACE_INVALID_HANDLE)
980 struct if_laddrreq *lifs = 0;
981 ACE_NEW_RETURN (lifs,
982 struct if_laddrreq[num_ifs],
983 -1);
984 ACE_OS::memset (lifs, 0, num_ifs * sizeof (struct if_laddrreq));
986 ACE_Auto_Array_Ptr<struct if_laddrreq> p_lifs (lifs);
988 if (p_lifs.get() == 0)
990 ACE_OS::close (handle);
991 ACE_OS::close (handle_ipv6);
992 errno = ENOMEM;
993 return -1;
996 struct if_laddrconf lifcfg;
997 ACE_OS::memset (&lifcfg, 0, sizeof (struct if_laddrconf));
999 lifcfg.iflc_req = p_lifs.get ();
1000 lifcfg.iflc_len = num_ifs * sizeof (struct if_laddrreq);
1002 if (ACE_OS::ioctl (handle_ipv6,
1003 SIOCGLIFCONF,
1004 (char *) &lifcfg) == -1)
1006 ACE_OS::close (handle);
1007 ACE_ERROR_RETURN ((LM_ERROR,
1008 ACE_TEXT ("%p\n"),
1009 ACE_TEXT ("ACE::get_ip_interfaces:")
1010 ACE_TEXT ("ioctl - SIOCGLIFCONF failed")),
1011 -1);
1014 ACE_OS::close (handle_ipv6);
1016 struct if_laddrreq *plcur = p_lifs.get ();
1017 num_ifs_found = lifcfg.iflc_len / sizeof (struct if_laddrreq);
1019 for (size_t i = 0;
1020 i < num_ifs_found;
1021 i++)
1023 struct sockaddr_in *addr =
1024 reinterpret_cast<sockaddr_in *> (&plcur->iflr_addr);
1025 if (!IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
1027 addrs[count].set(addr, sizeof(struct sockaddr_in6));
1028 ++count;
1030 ++plcur;
1033 # endif /* ACE_HAS_IPV6 */
1034 return 0;
1036 #elif defined (_AIX)
1037 static int
1038 get_ip_interfaces_aix (size_t &count,
1039 ACE_INET_Addr *&addrs)
1041 ACE_HANDLE handle = ACE::get_handle();
1042 size_t num_ifs = 0;
1043 struct ifconf ifc;
1045 if (handle == ACE_INVALID_HANDLE)
1046 ACE_ERROR_RETURN ((LM_ERROR,
1047 ACE_TEXT ("%p\n"),
1048 ACE_TEXT ("ACE::get_ip_interfaces_aix:")),
1049 -1);
1051 if (ACE_OS::ioctl (handle,
1052 SIOCGSIZIFCONF,
1053 (caddr_t)&ifc.ifc_len) == -1)
1055 ACE_OS::close (handle);
1056 ACE_ERROR_RETURN((LM_ERROR,
1057 ACE_TEXT ("%p\n"),
1058 ACE_TEXT ("get ifconf size")),
1059 -1);
1062 ACE_NEW_RETURN (ifc.ifc_buf,char [ifc.ifc_len], -1);
1064 ACE_Auto_Array_Ptr<char> safe_buf (ifc.ifc_buf);
1065 ACE_OS::memset (safe_buf.get(), 0, ifc.ifc_len);
1067 if (ACE_OS::ioctl(handle, SIOCGIFCONF, (caddr_t)&ifc) == -1)
1069 ACE_OS::close (handle);
1070 ACE_ERROR_RETURN((LM_ERROR,
1071 ACE_TEXT ("%p\n"),
1072 ACE_TEXT ("get ifconf")),
1073 -1);
1076 ACE_OS::close (handle);
1078 char *buf_start = safe_buf.get();
1079 char *buf_end = buf_start + ifc.ifc_len;
1081 num_ifs = 0;
1082 for (char *ptr = buf_start; ptr < buf_end; )
1084 struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
1085 ptr += IFNAMSIZ;
1086 ptr += req->ifr_addr.sa_len;
1087 if (req->ifr_addr.sa_family == AF_INET
1088 # if defined (ACE_HAS_IPV6)
1089 || req->ifr_addr.sa_family == AF_INET6
1090 # endif
1092 ++num_ifs;
1094 ACE_NEW_RETURN (addrs,ACE_INET_Addr[num_ifs], -1);
1096 for (char * ptr = buf_start; ptr < buf_end; )
1098 struct ifreq *req = reinterpret_cast<struct ifreq *>(ptr);
1099 // skip the interface name
1100 ptr += IFNAMSIZ;
1101 if (req->ifr_addr.sa_family == AF_INET
1102 # if defined (ACE_HAS_IPV6)
1103 || req->ifr_addr.sa_family == AF_INET6
1104 # endif
1107 sockaddr_in *addr = (sockaddr_in*)&req->ifr_addr;
1108 addrs[count++].set(addr, addr->sin_len);
1110 ptr += req->ifr_addr.sa_len;
1113 return 0;
1116 #elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600) && !defined (ACE_HAS_VXWORKS551_MEDUSA)
1118 get_ip_interfaces_vxworks_lt600 (size_t &count,
1119 ACE_INET_Addr *&addrs)
1121 count = 0;
1122 // Loop through each address structure
1124 # if defined (ACE_HAS_IPV6) && defined (TAILQ_ENTRY)
1125 # define ia_next ia_link.tqe_next
1126 # endif /* TAILQ_ENTRY */
1128 for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
1130 ++count;
1133 // Now create and initialize output array.
1134 ACE_NEW_RETURN (addrs,
1135 ACE_INET_Addr[count],
1136 -1); // caller must free
1137 count = 0;
1138 for (struct in_ifaddr* ia = in_ifaddr; ia != 0; ia = ia->ia_next)
1140 struct ifnet* ifp = ia->ia_ifa.ifa_ifp;
1141 if (ifp != 0)
1143 // Get the current interface name
1144 char interface[64];
1145 ACE_OS::sprintf(interface, "%s%d", ifp->if_name, ifp->if_unit);
1147 // Get the address for the current interface
1148 char address [INET_ADDR_LEN];
1149 STATUS status = ifAddrGet(interface, address);
1151 if (status == OK)
1153 // Concatenate a ':' at the end. This is because in
1154 // ACE_INET_Addr::string_to_addr, the ip_address is
1155 // obtained using ':' as the delimiter. Since, using
1156 // ifAddrGet(), we just get the IP address, I am adding
1157 // a ":" to get with the general case.
1158 ACE_OS::strcat (address, ":");
1159 addrs[count].set (address);
1161 else
1163 ACE_ERROR_RETURN ((LM_ERROR,
1164 ACE_TEXT ("ACE::get_ip_interface failed\n")
1165 ACE_TEXT ("Couldnt get the IP Address\n")),
1166 -1);
1168 ++count;
1171 return 0;
1173 #endif // ACE_WIN32 || ACE_HAS_GETIFADDRS || __hpux || _AIX || ACE_VXWORKS < 0x600
1176 // return an array of all configured IP interfaces on this host, count
1177 // rc = 0 on success (count == number of interfaces else -1 caller is
1178 // responsible for calling delete [] on parray
1181 ACE::get_ip_interfaces (size_t &count,
1182 ACE_INET_Addr *&addrs)
1184 ACE_TRACE ("ACE::get_ip_interfaces");
1186 count = 0;
1187 addrs = 0;
1189 #if defined (ACE_WIN32)
1190 return get_ip_interfaces_win32 (count, addrs);
1191 #elif defined (ACE_HAS_GETIFADDRS)
1192 return get_ip_interfaces_getifaddrs (count, addrs);
1193 #elif defined (__hpux)
1194 return get_ip_interfaces_hpux (count, addrs);
1195 #elif defined (_AIX)
1196 return get_ip_interfaces_aix (count, addrs);
1197 #elif defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600) && !defined (ACE_HAS_VXWORKS551_MEDUSA)
1198 return get_ip_interfaces_vxworks_lt600 (count, addrs);
1199 #elif (defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (ACE_OPENVMS) || (defined (ACE_VXWORKS) && (ACE_VXWORKS == 0x650)) || defined (ACE_HAS_RTEMS)) && !defined (ACE_LACKS_NETWORKING)
1200 // COMMON (SVR4 and BSD) UNIX CODE
1202 // Call specific routine as necessary.
1203 ACE_HANDLE handle = ACE::get_handle();
1205 if (handle == ACE_INVALID_HANDLE)
1206 ACE_ERROR_RETURN ((LM_ERROR,
1207 ACE_TEXT ("%p\n"),
1208 ACE_TEXT ("ACE::get_ip_interfaces:open")),
1209 -1);
1211 size_t num_ifs, num_ifs_found;
1213 if (ACE::count_interfaces (handle, num_ifs))
1215 ACE_OS::close (handle);
1216 return -1;
1219 // ioctl likes to have an extra ifreq structure to mark the end of
1220 // what it returned, so increase the num_ifs by one.
1221 ++num_ifs;
1223 struct IFREQ *ifs = 0;
1224 ACE_NEW_RETURN (ifs,
1225 struct IFREQ[num_ifs],
1226 -1);
1227 ACE_OS::memset (ifs, 0, num_ifs * sizeof (struct IFREQ));
1229 ACE_Auto_Array_Ptr<struct IFREQ> p_ifs (ifs);
1231 if (p_ifs.get() == 0)
1233 ACE_OS::close (handle);
1234 errno = ENOMEM;
1235 return -1;
1238 struct IFCONF ifcfg;
1239 ACE_OS::memset (&ifcfg, 0, sizeof (struct IFCONF));
1241 # ifdef SETFAMILY
1242 ifcfg.IFC_FAMILY = AF_UNSPEC; // request all families be returned
1243 ifcfg.IFC_FLAGS = 0;
1244 # endif
1246 ifcfg.IFC_REQ = p_ifs.get ();
1247 ifcfg.IFC_LEN = num_ifs * sizeof (struct IFREQ);
1249 if (ACE_OS::ioctl (handle,
1250 SIOCGIFCONF_CMD,
1251 (caddr_t) &ifcfg) == -1)
1253 ACE_OS::close (handle);
1254 ACE_ERROR_RETURN ((LM_ERROR,
1255 ACE_TEXT ("%p\n"),
1256 ACE_TEXT ("ACE::get_ip_interfaces:")
1257 ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
1258 -1);
1261 ACE_OS::close (handle);
1263 // Now create and initialize output array.
1265 ACE_NEW_RETURN (addrs,
1266 ACE_INET_Addr[num_ifs],
1267 -1); // caller must free
1269 struct IFREQ *pcur = p_ifs.get ();
1270 num_ifs_found = ifcfg.IFC_LEN / sizeof (struct IFREQ); // get the number of returned ifs
1272 // Pull the address out of each INET interface. Not every interface
1273 // is for IP, so be careful to count properly. When setting the
1274 // INET_Addr, note that the 3rd arg (0) says to leave the byte order
1275 // (already in net byte order from the interface structure) as is.
1276 count = 0;
1278 for (size_t i = 0;
1279 i < num_ifs_found;
1280 i++)
1282 if (pcur->IFR_ADDR.SA_FAMILY == AF_INET
1283 # if defined (ACE_HAS_IPV6)
1284 || pcur->IFR_ADDR.SA_FAMILY == AF_INET6
1285 # endif
1289 # if !defined(_UNICOS)
1290 struct sockaddr_in *addr =
1291 reinterpret_cast<sockaddr_in *> (&pcur->IFR_ADDR);
1293 // Sometimes the kernel returns 0.0.0.0 as an IPv4 interface
1294 // address; skip those...
1295 if (addr->sin_addr.s_addr != 0
1296 # if defined (ACE_HAS_IPV6)
1297 || (addr->sin_family == AF_INET6 &&
1298 !IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<sockaddr_in6 *>(addr)->sin6_addr))
1299 # endif
1302 int addrlen = static_cast<int> (sizeof (struct sockaddr_in));
1303 # if defined (ACE_HAS_IPV6)
1304 if (addr->sin_family == AF_INET6)
1305 addrlen = static_cast<int> (sizeof (struct sockaddr_in6));
1306 # endif
1307 addrs[count].set (addr, addrlen);
1308 ++count;
1310 # else /* ! _UNICOS */
1311 // need to explicitly copy on the Cray, since the bitfields kinda
1312 // screw things up here
1313 struct sockaddr_in inAddr;
1315 inAddr.sin_len = pcur->IFR_ADDR.sa_len;
1316 inAddr.sin_family = pcur->IFR_ADDR.sa_family;
1317 memcpy((void *)&(inAddr.sin_addr),
1318 (const void *)&(pcur->IFR_ADDR.sa_data[8]),
1319 sizeof(struct in_addr));
1321 if (inAddr.sin_addr.s_addr != 0)
1323 addrs[count].set(&inAddr, sizeof(struct sockaddr_in));
1324 ++count;
1326 # endif /* ! _UNICOS */
1329 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS)
1330 ++pcur;
1331 #else
1332 if (pcur->ifr_addr.sa_len <= sizeof (struct sockaddr))
1334 ++pcur;
1336 else
1338 pcur = (struct ifreq *)
1339 (pcur->ifr_addr.sa_len + (caddr_t) &pcur->ifr_addr);
1341 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
1344 # if defined (ACE_HAS_IPV6)
1345 // Retrieve IPv6 local interfaces by scanning /proc/net/if_inet6 if
1346 // it exists. If we cannot open it then ignore possible IPv6
1347 // interfaces, we did our best;-)
1348 FILE* fp;
1349 char addr_p[8][5];
1350 char s_ipaddr[64];
1351 int scopeid;
1352 struct addrinfo hints, *res0;
1353 int error;
1355 ACE_OS::memset (&hints, 0, sizeof (hints));
1356 hints.ai_flags = AI_NUMERICHOST;
1357 hints.ai_family = AF_INET6;
1359 if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
1361 while (fscanf (fp,
1362 "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*8s\n",
1363 addr_p[0], addr_p[1], addr_p[2], addr_p[3],
1364 addr_p[4], addr_p[5], addr_p[6], addr_p[7], &scopeid) != EOF)
1366 // Format the address intoa proper IPv6 decimal address specification and
1367 // resolve the resulting text using getaddrinfo().
1369 const char* ip_fmt = "%s:%s:%s:%s:%s:%s:%s:%s%%%d";
1370 ACE_OS::sprintf (s_ipaddr,
1371 ip_fmt,
1372 addr_p[0], addr_p[1], addr_p[2], addr_p[3],
1373 addr_p[4], addr_p[5], addr_p[6], addr_p[7], scopeid);
1375 error = getaddrinfo (s_ipaddr, 0, &hints, &res0);
1376 if (error)
1377 continue;
1379 if (res0->ai_family == AF_INET6 &&
1380 !IN6_IS_ADDR_UNSPECIFIED (&reinterpret_cast<sockaddr_in6 *> (res0->ai_addr)->sin6_addr))
1382 addrs[count].set(reinterpret_cast<sockaddr_in *> (res0->ai_addr), res0->ai_addrlen);
1383 ++count;
1385 freeaddrinfo (res0);
1388 ACE_OS::fclose (fp);
1390 # endif /* ACE_HAS_IPV6 */
1392 return 0;
1393 #else
1394 ACE_UNUSED_ARG (count);
1395 ACE_UNUSED_ARG (addrs);
1396 ACE_NOTSUP_RETURN (-1); // no implementation
1397 #endif /* ACE_WIN32 */
1400 // Helper routine for get_ip_interfaces, differs by UNIX platform so
1401 // put into own subroutine. perform some ioctls to retrieve ifconf
1402 // list of ifreq structs.
1405 ACE::count_interfaces (ACE_HANDLE handle,
1406 size_t &how_many)
1408 #if defined (ACE_WIN32) || defined (ACE_HAS_GETIFADDRS) || defined (__hpux) || defined (_AIX) || (defined (ACE_VXWORKS) && (ACE_VXWORKS < 0x600))
1409 // none of these platforms make use of count_interfaces
1410 ACE_UNUSED_ARG (handle);
1411 ACE_UNUSED_ARG (how_many);
1412 ACE_NOTSUP_RETURN (-1); // no implementation
1414 #elif defined (SIOCGIFNUM)
1415 # if defined (SIOCGLIFNUM)
1416 int cmd = SIOCGLIFNUM;
1417 struct lifnum if_num = {AF_UNSPEC,0,0};
1418 # else
1419 int cmd = SIOCGIFNUM;
1420 int if_num = 0;
1421 # endif /* SIOCGLIFNUM */
1422 if (ACE_OS::ioctl (handle, cmd, (caddr_t)&if_num) == -1)
1423 ACE_ERROR_RETURN ((LM_ERROR,
1424 ACE_TEXT ("%p\n"),
1425 ACE_TEXT ("ACE::count_interfaces:")
1426 ACE_TEXT ("ioctl - SIOCGLIFNUM failed")),
1427 -1);
1428 # if defined (SIOCGLIFNUM)
1429 how_many = if_num.lifn_count;
1430 # else
1431 how_many = if_num;
1432 # endif /* SIOCGLIFNUM */
1433 return 0;
1435 #elif (defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS)) && !defined (ACE_LACKS_NETWORKING)
1436 // Note: DEC CXX doesn't define "unix". BSD compatible OS: HP UX,
1437 // AIX, SunOS 4.x perform some ioctls to retrieve ifconf list of
1438 // ifreq structs no SIOCGIFNUM on SunOS 4.x, so use guess and scan
1439 // algorithm
1441 // Probably hard to put this many ifs in a unix box..
1442 const int MAX_IF = 50;
1444 // HACK - set to an unreasonable number
1445 int num_ifs = MAX_IF;
1447 struct ifconf ifcfg;
1448 size_t ifreq_size = num_ifs * sizeof (struct ifreq);
1449 struct ifreq *p_ifs =
1450 (struct ifreq *) ACE_OS::malloc (ifreq_size);
1452 if (!p_ifs)
1454 errno = ENOMEM;
1455 return -1;
1458 ACE_OS::memset (p_ifs, 0, ifreq_size);
1459 ACE_OS::memset (&ifcfg, 0, sizeof (struct ifconf));
1461 ifcfg.ifc_req = p_ifs;
1462 ifcfg.ifc_len = ifreq_size;
1464 if (ACE_OS::ioctl (handle,
1465 SIOCGIFCONF_CMD,
1466 (caddr_t) &ifcfg) == -1)
1468 ACE_OS::free (ifcfg.ifc_req);
1469 ACE_ERROR_RETURN ((LM_ERROR,
1470 ACE_TEXT ("%p\n"),
1471 ACE_TEXT ("ACE::count_interfaces:")
1472 ACE_TEXT ("ioctl - SIOCGIFCONF failed")),
1473 -1);
1476 int if_count = 0, i;
1478 // get if address out of ifreq buffers. ioctl puts a blank-named
1479 // interface to mark the end of the returned interfaces.
1480 for (i = 0;
1481 i < num_ifs;
1482 i++)
1484 /* In OpenBSD, the length of the list is returned. */
1485 ifcfg.ifc_len -= sizeof (struct ifreq);
1486 if (ifcfg.ifc_len < 0)
1487 break;
1489 ++if_count;
1490 #if !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_HAS_RTEMS)
1491 ++p_ifs;
1492 #else
1493 if (p_ifs->ifr_addr.sa_len <= sizeof (struct sockaddr))
1495 ++p_ifs;
1497 else
1499 p_ifs = (struct ifreq *)
1500 (p_ifs->ifr_addr.sa_len + (caddr_t) &p_ifs->ifr_addr);
1502 #endif /* !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) */
1505 ACE_OS::free (ifcfg.ifc_req);
1507 # if defined (ACE_HAS_IPV6)
1508 FILE* fp = 0;
1510 if ((fp = ACE_OS::fopen (ACE_TEXT ("/proc/net/if_inet6"), ACE_TEXT ("r"))) != 0)
1512 // Scan the lines according to the expected format but don't really read any input
1513 while (fscanf (fp, "%*32s %*02x %*02x %*02x %*02x %*8s\n") != EOF)
1515 ++if_count;
1517 ACE_OS::fclose (fp);
1519 # endif /* ACE_HAS_IPV6 */
1521 how_many = if_count;
1522 return 0;
1523 #else
1524 ACE_UNUSED_ARG (handle);
1525 ACE_UNUSED_ARG (how_many);
1526 ACE_NOTSUP_RETURN (-1); // no implementation
1527 #endif /* sparc && SIOCGIFNUM */
1530 // Routine to return a handle from which ioctl() requests can be made.
1532 ACE_HANDLE
1533 ACE::get_handle (void)
1535 // Solaris 2.x
1536 ACE_HANDLE handle = ACE_INVALID_HANDLE;
1537 #if defined (sparc)
1538 handle = ACE_OS::open ("/dev/udp", O_RDONLY);
1539 #elif defined (__unix) || defined (__unix__) || defined (__Lynx__) || defined (_AIX) || defined (__hpux) || (defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600)) || defined (ACE_OPENVMS) || defined (ACE_HAS_RTEMS)
1540 // Note: DEC CXX doesn't define "unix" BSD compatible OS: HP UX,
1541 // AIX, SunOS 4.x
1543 handle = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
1544 #endif /* sparc */
1545 return handle;
1549 #if defined (ACE_HAS_IPV6)
1550 static int
1551 ip_check (int &ipvn_enabled, int pf)
1553 // We only get to this point if ipvn_enabled was -1 in the caller.
1554 // Perform Double-Checked Locking Optimization.
1555 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
1556 *ACE_Static_Object_Lock::instance (), 0));
1558 if (ipvn_enabled == -1)
1560 // Determine if the kernel has IPv6 support by attempting to
1561 // create a PF_INET socket and see if it fails.
1562 ACE_HANDLE const s = ACE_OS::socket (pf, SOCK_DGRAM, 0);
1563 if (s == ACE_INVALID_HANDLE)
1565 ipvn_enabled = 0;
1567 else
1569 ipvn_enabled = 1;
1570 ACE_OS::closesocket (s);
1573 return ipvn_enabled;
1575 #endif /* ACE_HAS_IPV6 */
1577 bool
1578 ACE::ipv4_enabled (void)
1580 #if defined (ACE_HAS_IPV6)
1581 return static_cast<bool> (ace_ipv4_enabled == -1 ?
1582 ::ip_check (ace_ipv4_enabled, PF_INET) :
1583 ace_ipv4_enabled);
1584 #else
1585 // Assume it's always enabled since ACE requires some version of
1586 // TCP/IP to exist.
1587 return true;
1588 #endif /* ACE_HAS_IPV6*/
1592 ACE::ipv6_enabled (void)
1594 #if defined (ACE_HAS_IPV6)
1595 return ace_ipv6_enabled == -1 ?
1596 ::ip_check (ace_ipv6_enabled, PF_INET6) :
1597 ace_ipv6_enabled;
1598 #else /* ACE_HAS_IPV6 */
1599 return 0;
1600 #endif /* !ACE_HAS_IPV6 */
1603 ACE_END_VERSIONED_NAMESPACE_DECL