Correct feature names
[ACE_TAO.git] / ACE / ace / OS_NS_netdb.cpp
blobad949935525291086f505231ae899be77fb93f39
1 // -*- C++ -*-
2 #include "ace/OS_NS_netdb.h"
4 #if !defined (ACE_HAS_INLINED_OSCALLS)
5 # include "ace/OS_NS_netdb.inl"
6 #endif /* ACE_HAS_INLINED_OSCALLS */
8 #if defined (ACE_WIN32) && defined (ACE_HAS_PHARLAP)
9 # include "ace/OS_NS_stdio.h"
10 #endif
12 #include "ace/os_include/net/os_if.h"
13 #include "ace/Global_Macros.h"
14 #include "ace/OS_NS_arpa_inet.h"
15 #include "ace/OS_NS_stdlib.h"
16 #include "ace/OS_NS_stropts.h"
17 #include "ace/OS_NS_sys_socket.h"
18 #include "ace/OS_NS_unistd.h"
20 #if defined (ACE_LINUX) && !defined (ACE_LACKS_NETWORKING)
21 # include "ace/os_include/os_ifaddrs.h"
22 #endif /* ACE_LINUX && !ACE_LACKS_NETWORKING */
24 #ifdef ACE_LACKS_IOCTL
25 #include "ace/OS_NS_devctl.h"
26 #endif
28 #ifdef ACE_VXWORKS
29 # include "ace/os_include/sys/os_sysctl.h"
30 # include <net/route.h>
31 #endif
33 #ifdef ACE_HAS_ALLOC_HOOKS
34 # include "ace/Malloc_Base.h"
35 #endif
37 // Include if_arp so that getmacaddr can use the
38 // arp structure.
39 #if defined (sun)
40 # include /**/ <net/if_arp.h>
41 #endif
43 #include <algorithm>
45 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
47 int
48 ACE_OS::getmacaddress (struct macaddr_node_t *node)
50 ACE_OS_TRACE ("ACE_OS::getmacaddress");
52 #if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
53 # if !defined (ACE_HAS_PHARLAP)
54 /** Define a structure for use with the netbios routine */
55 struct ADAPTERSTAT
57 ADAPTER_STATUS adapt;
58 NAME_BUFFER NameBuff [30];
61 NCB ncb;
62 LANA_ENUM lenum;
63 unsigned char result;
65 ACE_OS::memset (&ncb, 0, sizeof(ncb));
66 ncb.ncb_command = NCBENUM;
67 ncb.ncb_buffer = reinterpret_cast<unsigned char*> (&lenum);
68 ncb.ncb_length = sizeof(lenum);
70 result = Netbios (&ncb);
72 for(int i = 0; i < lenum.length; i++)
74 ACE_OS::memset (&ncb, 0, sizeof(ncb));
75 ncb.ncb_command = NCBRESET;
76 ncb.ncb_lana_num = lenum.lana [i];
78 /** Reset the netbios */
79 result = Netbios (&ncb);
81 if (ncb.ncb_retcode != NRC_GOODRET)
83 return -1;
86 ADAPTERSTAT adapter;
87 ACE_OS::memset (&ncb, 0, sizeof (ncb));
88 ACE_OS::strcpy (reinterpret_cast<char*> (ncb.ncb_callname), "*");
89 ncb.ncb_command = NCBASTAT;
90 ncb.ncb_lana_num = lenum.lana[i];
91 ncb.ncb_buffer = reinterpret_cast<unsigned char*> (&adapter);
92 ncb.ncb_length = sizeof (adapter);
94 result = Netbios (&ncb);
96 if (result == 0)
98 ACE_OS::memcpy (node->node,
99 adapter.adapt.adapter_address,
101 return 0;
104 return 0;
105 # else
106 # if defined (ACE_HAS_PHARLAP_RT)
107 DEVHANDLE ip_dev = (DEVHANDLE)0;
108 EK_TCPIPCFG *devp = 0;
109 size_t i;
110 ACE_TCHAR dev_name[16];
112 for (i = 0; i < 10; i++)
114 // Ethernet.
115 ACE_OS::snprintf (dev_name, 16, "ether%d", i);
116 ip_dev = EtsTCPGetDeviceHandle (dev_name);
117 if (ip_dev != 0)
118 break;
120 if (ip_dev == 0)
121 return -1;
122 devp = EtsTCPGetDeviceCfg (ip_dev);
123 if (devp == 0)
124 return -1;
125 ACE_OS::memcpy (node->node,
126 &devp->EthernetAddress[0],
128 return 0;
129 # else
130 ACE_UNUSED_ARG (node);
131 ACE_NOTSUP_RETURN (-1);
132 # endif /* ACE_HAS_PHARLAP_RT */
133 # endif /* ACE_HAS_PHARLAP */
134 #elif defined (sun)
136 /** obtain the local host name */
137 char hostname [MAXHOSTNAMELEN];
138 ACE_OS::hostname (hostname, sizeof (hostname));
140 /** Get the hostent to use with ioctl */
141 struct hostent *phost =
142 ACE_OS::gethostbyname (hostname);
144 if (phost == 0)
145 return -1;
147 ACE_HANDLE handle =
148 ACE_OS::socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
150 if (handle == ACE_INVALID_HANDLE)
151 return -1;
153 char **paddrs = phost->h_addr_list;
155 struct arpreq ar;
157 struct sockaddr_in *psa =
158 (struct sockaddr_in *)&(ar.arp_pa);
160 ACE_OS::memset (&ar,
162 sizeof (struct arpreq));
164 psa->sin_family = AF_INET;
166 ACE_OS::memcpy (&(psa->sin_addr),
167 *paddrs,
168 sizeof (struct in_addr));
170 if (ACE_OS::ioctl (handle,
171 SIOCGARP,
172 &ar) == -1)
174 ACE_OS::close (handle);
175 return -1;
178 ACE_OS::close (handle);
180 ACE_OS::memcpy (node->node,
181 ar.arp_ha.sa_data,
184 return 0;
186 #elif defined (ACE_LINUX) && !defined (ACE_LACKS_NETWORKING)
188 // It's easiest to know the first MAC-using interface. Use the BSD
189 // getifaddrs function that simplifies access to connected interfaces.
190 struct ifaddrs *ifap = 0;
191 struct ifaddrs *p_if = 0;
193 if (::getifaddrs (&ifap) != 0)
194 return -1;
196 for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
198 if (p_if->ifa_addr == 0)
199 continue;
201 // Check to see if it's up and is not either PPP or loopback
202 if ((p_if->ifa_flags & IFF_UP) == IFF_UP &&
203 (p_if->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
204 break;
206 if (p_if == 0)
208 errno = ENODEV;
209 ::freeifaddrs (ifap);
210 return -1;
213 struct ifreq ifr;
214 ACE_OS::strcpy (ifr.ifr_name, p_if->ifa_name);
215 ::freeifaddrs (ifap);
217 ACE_HANDLE handle =
218 ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
220 if (handle == ACE_INVALID_HANDLE)
221 return -1;
223 # ifdef ACE_LACKS_IOCTL
224 int info = 0;
225 if (ACE_OS::posix_devctl (handle, SIOCGIFHWADDR, &ifr, sizeof ifr, &info) < 0)
226 # else
227 if (ACE_OS::ioctl (handle/*s*/, SIOCGIFHWADDR, &ifr) < 0)
228 # endif
230 ACE_OS::close (handle);
231 return -1;
234 struct sockaddr* sa =
235 (struct sockaddr *) &ifr.ifr_addr;
237 ACE_OS::close (handle);
239 ACE_OS::memcpy (node->node,
240 sa->sa_data,
243 return 0;
245 #elif defined (__ANDROID_API__) && defined (ACE_HAS_SIOCGIFCONF) && !defined (ACE_LACKS_NETWORKING)
247 struct ifconf ifc;
248 struct ifreq ifr_buf[32];
251 ACE_HANDLE handle =
252 ACE_OS::socket (AF_INET, SOCK_DGRAM, 0);
254 if (handle == ACE_INVALID_HANDLE)
256 return -1;
260 ifc.ifc_len = sizeof(ifr_buf);
261 ifc.ifc_req = &ifr_buf[0];
263 if (ACE_OS::ioctl (handle, SIOCGIFCONF, &ifc) < 0)
265 ACE_OS::close (handle);
266 return -1;
269 int numif = ifc.ifc_len / sizeof(struct ifreq);
271 // find first eligible device
272 struct ifreq* ifr = 0;
273 for (int i=0; i< numif ;++i)
275 ifr = &ifr_buf[i];
277 // get device flags
278 if (ACE_OS::ioctl (handle, SIOCGIFFLAGS, ifr) < 0)
280 ACE_OS::close (handle);
281 return -1;
284 // Check to see if it's up and is not either PPP or loopback
285 if ((ifr->ifr_flags & IFF_UP) == IFF_UP &&
286 (ifr->ifr_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
287 break;
289 ifr = 0;
291 // did we find any?
292 if (ifr == 0)
294 ACE_OS::close (handle);
295 errno = ENODEV;
296 return -1;
299 if (ACE_OS::ioctl (handle, SIOCGIFHWADDR, ifr) < 0)
301 ACE_OS::close (handle);
302 return -1;
305 struct sockaddr* sa =
306 (struct sockaddr *) &ifr->ifr_hwaddr;
308 ACE_OS::close (handle);
310 ACE_OS::memcpy (node->node,
311 sa->sa_data,
314 return 0;
316 #elif defined (ACE_HAS_SIOCGIFCONF) && !defined (__ANDROID_API__)
318 const long BUFFERSIZE = 4000;
319 char buffer[BUFFERSIZE];
321 struct ifconf ifc;
322 struct ifreq* ifr = 0;
324 ACE_HANDLE handle =
325 ACE_OS::socket (AF_INET, SOCK_DGRAM, 0);
327 if (handle == ACE_INVALID_HANDLE)
329 return -1;
332 ifc.ifc_len = BUFFERSIZE;
333 ifc.ifc_buf = buffer;
335 if (ACE_OS::ioctl (handle, SIOCGIFCONF, &ifc) < 0)
337 ACE_OS::close (handle);
338 return -1;
341 for(char* ptr=buffer; ptr < buffer + ifc.ifc_len; )
343 ifr = (struct ifreq *) ptr;
345 if (ifr->ifr_addr.sa_family == AF_LINK)
347 if(ACE_OS::strcmp (ifr->ifr_name, "en0") == 0)
349 struct sockaddr_dl* sdl =
350 (struct sockaddr_dl *) &ifr->ifr_addr;
352 ACE_OS::memcpy (node->node,
353 LLADDR(sdl),
358 ptr += sizeof(ifr->ifr_name);
360 if(sizeof(ifr->ifr_addr) > ifr->ifr_addr.sa_len)
361 ptr += sizeof(ifr->ifr_addr);
362 else
363 ptr += ifr->ifr_addr.sa_len;
366 ACE_OS::close (handle);
368 return 0;
370 #elif defined ACE_VXWORKS
372 int name[] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
373 static const size_t name_elts = sizeof name / sizeof name[0];
375 size_t result_sz = 0u;
376 if (sysctl (name, name_elts, 0, &result_sz, 0, 0u) != 0)
377 return -1;
379 # ifdef ACE_HAS_ALLOC_HOOKS
380 char *const result =
381 static_cast<char *> (ACE_Allocator::instance ()->malloc (result_sz));
382 # define ACE_NETDB_CLEANUP ACE_Allocator::instance ()->free (result)
383 # else
384 char *const result = static_cast<char *> (ACE_OS::malloc (result_sz));
385 # define ACE_NETDB_CLEANUP ACE_OS::free (result)
386 # endif
388 if (sysctl (name, name_elts, result, &result_sz, 0, 0u) != 0)
390 ACE_NETDB_CLEANUP;
391 return -1;
394 for (size_t pos = 0, n; pos + sizeof (if_msghdr) < result_sz; pos += n)
396 if_msghdr *const hdr = reinterpret_cast<if_msghdr *> (result + pos);
397 n = hdr->ifm_msglen;
398 sockaddr_dl *const addr =
399 reinterpret_cast<sockaddr_dl *> (result + pos + sizeof (if_msghdr));
401 if (addr->sdl_alen >= sizeof node->node)
403 ACE_OS::memcpy (node->node, LLADDR (addr), sizeof node->node);
404 ACE_NETDB_CLEANUP;
405 return 0;
408 while (pos + n < result_sz)
410 ifa_msghdr *const ifa =
411 reinterpret_cast<ifa_msghdr *> (result + pos + n);
412 if (ifa->ifam_type != RTM_NEWADDR)
413 break;
414 n += ifa->ifam_msglen;
418 ACE_NETDB_CLEANUP;
419 # undef ACE_NETDB_CLEANUP
420 return -1;
422 #else
423 ACE_UNUSED_ARG (node);
424 ACE_NOTSUP_RETURN (-1);
425 #endif
428 #ifdef ACE_LACKS_GETADDRINFO
430 ACE_OS::getaddrinfo_emulation (const char *name, addrinfo **result)
432 hostent entry;
433 ACE_HOSTENT_DATA buffer;
434 int herr = 0;
435 const hostent *host = ACE_OS::gethostbyname_r (name, &entry, buffer, &herr);
437 if (host == 0)
439 switch (herr)
441 case NO_DATA:
442 case HOST_NOT_FOUND:
443 return EAI_NONAME;
444 case TRY_AGAIN:
445 return EAI_AGAIN;
446 case NO_RECOVERY:
447 return EAI_FAIL;
448 case ENOTSUP:
449 if (ACE_OS::inet_aton (name, (in_addr *) &buffer[0]) != 0)
451 host = &entry;
452 entry.h_length = sizeof (in_addr);
453 entry.h_addr_list = (char **) (buffer + sizeof (in_addr));
454 entry.h_addr_list[0] = buffer;
455 entry.h_addr_list[1] = 0;
456 break;
458 // fall-through
459 default:
460 errno = herr;
461 return EAI_SYSTEM;
465 size_t n = 0;
466 for (char **addr = host->h_addr_list; *addr; ++addr, ++n) /*empty*/;
468 # ifdef ACE_HAS_ALLOC_HOOKS
469 ACE_Allocator *const al = ACE_Allocator::instance ();
470 # define ACE_ALLOC al->
471 # else
472 # define ACE_ALLOC ACE_OS::
473 # endif
475 ACE_ALLOCATOR_RETURN (*result,
476 (addrinfo *) ACE_ALLOC calloc (n, sizeof (addrinfo)),
477 EAI_MEMORY);
479 sockaddr_in *const addr_storage =
480 (sockaddr_in *) ACE_ALLOC calloc (n, sizeof (sockaddr_in));
482 if (!addr_storage)
484 ACE_ALLOC free (*result);
485 *result = 0;
486 return EAI_MEMORY;
489 for (size_t i = 0; i < n; ++i)
491 (*result)[i].ai_family = AF_INET;
492 (*result)[i].ai_addrlen = sizeof (sockaddr_in);
493 (*result)[i].ai_addr = (sockaddr *) addr_storage + i;
494 (*result)[i].ai_addr->sa_family = AF_INET;
495 ACE_OS::memcpy (&addr_storage[i].sin_addr, host->h_addr_list[i],
496 (std::min) (size_t (host->h_length), sizeof (in_addr)));
497 if (i < n - 1)
498 (*result)[i].ai_next = (*result) + i + 1;
501 return 0;
504 void
505 ACE_OS::freeaddrinfo_emulation (addrinfo *result)
507 # ifdef ACE_HAS_ALLOC_HOOKS
508 ACE_Allocator *const al = ACE_Allocator::instance ();
509 al->free (result->ai_addr);
510 al->free (result);
511 # else
512 ACE_OS::free (result->ai_addr);
513 ACE_OS::free (result);
514 # endif
516 #endif /* ACE_LACKS_GETADDRINFO */
518 #ifdef ACE_LACKS_GETNAMEINFO
520 ACE_OS::getnameinfo_emulation (const sockaddr *saddr, ACE_SOCKET_LEN saddr_len,
521 char *host, ACE_SOCKET_LEN host_len)
523 if (saddr_len != sizeof (sockaddr_in) || saddr->sa_family != AF_INET)
524 return EAI_FAMILY; // IPv6 support requries actual OS-provided getnameinfo
526 const void *addr = &((const sockaddr_in *) saddr)->sin_addr;
527 int h_error;
528 hostent hentry;
529 ACE_HOSTENT_DATA buf;
530 hostent *const hp =
531 ACE_OS::gethostbyaddr_r (static_cast<const char *> (addr),
532 # ifdef ACE_LACKS_IN_ADDR_T
534 # else
535 sizeof (in_addr_t),
536 # endif
537 AF_INET, &hentry, buf, &h_error);
539 if (hp == 0 || hp->h_name == 0)
540 return EAI_NONAME;
542 if (ACE_OS::strlen (hp->h_name) >= size_t (host_len))
544 if (host_len > 0)
546 ACE_OS::memcpy (host, hp->h_name, host_len - 1);
547 host[host_len - 1] = '\0';
549 return EAI_OVERFLOW;
552 ACE_OS::strcpy (host, hp->h_name);
553 return 0;
555 #endif /* ACE_LACKS_GETNAMEINFO */
557 ACE_END_VERSIONED_NAMESPACE_DECL
559 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) && defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
560 # include "ace/OS_NS_Thread.h"
561 # include "ace/Object_Manager_Base.h"
563 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
566 ACE_OS::netdb_acquire (void)
568 return ACE_OS::thread_mutex_lock ((ACE_thread_mutex_t *)
569 ACE_OS_Object_Manager::preallocated_object[
570 ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
574 ACE_OS::netdb_release (void)
576 return ACE_OS::thread_mutex_unlock ((ACE_thread_mutex_t *)
577 ACE_OS_Object_Manager::preallocated_object[
578 ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
581 ACE_END_VERSIONED_NAMESPACE_DECL
583 # endif /* defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) */