Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / OS_NS_netdb.cpp
blob49f658e5c5e975ec4d22f34937b7b66b5422db5b
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 #include "ace/os_include/net/os_if.h"
9 #include "ace/Global_Macros.h"
10 #include "ace/OS_NS_arpa_inet.h"
11 #include "ace/OS_NS_stdlib.h"
12 #include "ace/OS_NS_stropts.h"
13 #include "ace/OS_NS_sys_socket.h"
14 #include "ace/OS_NS_unistd.h"
16 #if defined (ACE_LINUX) && !defined (ACE_LACKS_NETWORKING)
17 # include "ace/os_include/os_ifaddrs.h"
18 #endif /* ACE_LINUX && !ACE_LACKS_NETWORKING */
20 #ifdef ACE_LACKS_IOCTL
21 #include "ace/OS_NS_devctl.h"
22 #endif
24 #ifdef ACE_VXWORKS
25 # include "ace/os_include/sys/os_sysctl.h"
26 # include <net/route.h>
27 #endif
29 #ifdef ACE_HAS_ALLOC_HOOKS
30 # include "ace/Malloc_Base.h"
31 #endif
33 #include <algorithm>
35 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
37 int
38 ACE_OS::getmacaddress (struct macaddr_node_t *node)
40 ACE_OS_TRACE ("ACE_OS::getmacaddress");
42 #if defined (ACE_WIN32)
43 /** Define a structure for use with the netbios routine */
44 struct ADAPTERSTAT
46 ADAPTER_STATUS adapt;
47 NAME_BUFFER NameBuff [30];
50 NCB ncb;
51 LANA_ENUM lenum;
52 unsigned char result;
54 ACE_OS::memset (&ncb, 0, sizeof(ncb));
55 ncb.ncb_command = NCBENUM;
56 ncb.ncb_buffer = reinterpret_cast<unsigned char*> (&lenum);
57 ncb.ncb_length = sizeof(lenum);
59 result = Netbios (&ncb);
61 for(int i = 0; i < lenum.length; i++)
63 ACE_OS::memset (&ncb, 0, sizeof(ncb));
64 ncb.ncb_command = NCBRESET;
65 ncb.ncb_lana_num = lenum.lana [i];
67 /** Reset the netbios */
68 result = Netbios (&ncb);
70 if (ncb.ncb_retcode != NRC_GOODRET)
72 return -1;
75 ADAPTERSTAT adapter;
76 ACE_OS::memset (&ncb, 0, sizeof (ncb));
77 ACE_OS::strcpy (reinterpret_cast<char*> (ncb.ncb_callname), "*");
78 ncb.ncb_command = NCBASTAT;
79 ncb.ncb_lana_num = lenum.lana[i];
80 ncb.ncb_buffer = reinterpret_cast<unsigned char*> (&adapter);
81 ncb.ncb_length = sizeof (adapter);
83 result = Netbios (&ncb);
85 if (result == 0)
87 ACE_OS::memcpy (node->node,
88 adapter.adapt.adapter_address,
89 6);
90 return 0;
93 return 0;
94 #elif defined (ACE_LINUX) && !defined (ACE_LACKS_NETWORKING)
96 // It's easiest to know the first MAC-using interface. Use the BSD
97 // getifaddrs function that simplifies access to connected interfaces.
98 struct ifaddrs *ifap = 0;
99 struct ifaddrs *p_if = 0;
101 if (::getifaddrs (&ifap) != 0)
102 return -1;
104 for (p_if = ifap; p_if != 0; p_if = p_if->ifa_next)
106 if (p_if->ifa_addr == 0)
107 continue;
109 // Check to see if it's up and is not either PPP or loopback
110 if ((p_if->ifa_flags & IFF_UP) == IFF_UP &&
111 (p_if->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
112 break;
114 if (p_if == 0)
116 errno = ENODEV;
117 ::freeifaddrs (ifap);
118 return -1;
121 struct ifreq ifr;
122 ACE_OS::strcpy (ifr.ifr_name, p_if->ifa_name);
123 ::freeifaddrs (ifap);
125 ACE_HANDLE handle =
126 ACE_OS::socket (PF_INET, SOCK_DGRAM, 0);
128 if (handle == ACE_INVALID_HANDLE)
129 return -1;
131 # ifdef ACE_LACKS_IOCTL
132 int info = 0;
133 if (ACE_OS::posix_devctl (handle, SIOCGIFHWADDR, &ifr, sizeof ifr, &info) < 0)
134 # else
135 if (ACE_OS::ioctl (handle/*s*/, SIOCGIFHWADDR, &ifr) < 0)
136 # endif
138 ACE_OS::close (handle);
139 return -1;
142 struct sockaddr* sa =
143 (struct sockaddr *) &ifr.ifr_addr;
145 ACE_OS::close (handle);
147 ACE_OS::memcpy (node->node,
148 sa->sa_data,
151 return 0;
153 #elif defined (__ANDROID_API__) && defined (ACE_HAS_SIOCGIFCONF) && !defined (ACE_LACKS_NETWORKING)
155 struct ifconf ifc;
156 struct ifreq ifr_buf[32];
159 ACE_HANDLE handle =
160 ACE_OS::socket (AF_INET, SOCK_DGRAM, 0);
162 if (handle == ACE_INVALID_HANDLE)
164 return -1;
168 ifc.ifc_len = sizeof(ifr_buf);
169 ifc.ifc_req = &ifr_buf[0];
171 if (ACE_OS::ioctl (handle, SIOCGIFCONF, &ifc) < 0)
173 ACE_OS::close (handle);
174 return -1;
177 int numif = ifc.ifc_len / sizeof(struct ifreq);
179 // find first eligible device
180 struct ifreq* ifr = 0;
181 for (int i=0; i< numif ;++i)
183 ifr = &ifr_buf[i];
185 // get device flags
186 if (ACE_OS::ioctl (handle, SIOCGIFFLAGS, ifr) < 0)
188 ACE_OS::close (handle);
189 return -1;
192 // Check to see if it's up and is not either PPP or loopback
193 if ((ifr->ifr_flags & IFF_UP) == IFF_UP &&
194 (ifr->ifr_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
195 break;
197 ifr = 0;
199 // did we find any?
200 if (ifr == 0)
202 ACE_OS::close (handle);
203 errno = ENODEV;
204 return -1;
207 if (ACE_OS::ioctl (handle, SIOCGIFHWADDR, ifr) < 0)
209 ACE_OS::close (handle);
210 return -1;
213 struct sockaddr* sa =
214 (struct sockaddr *) &ifr->ifr_hwaddr;
216 ACE_OS::close (handle);
218 ACE_OS::memcpy (node->node,
219 sa->sa_data,
222 return 0;
224 #elif defined (ACE_HAS_SIOCGIFCONF) && !defined (__ANDROID_API__)
226 const long BUFFERSIZE = 4000;
227 char buffer[BUFFERSIZE];
229 struct ifconf ifc;
230 struct ifreq* ifr = 0;
232 ACE_HANDLE handle =
233 ACE_OS::socket (AF_INET, SOCK_DGRAM, 0);
235 if (handle == ACE_INVALID_HANDLE)
237 return -1;
240 ifc.ifc_len = BUFFERSIZE;
241 ifc.ifc_buf = buffer;
243 if (ACE_OS::ioctl (handle, SIOCGIFCONF, &ifc) < 0)
245 ACE_OS::close (handle);
246 return -1;
249 for(char* ptr=buffer; ptr < buffer + ifc.ifc_len; )
251 ifr = (struct ifreq *) ptr;
253 if (ifr->ifr_addr.sa_family == AF_LINK)
255 if(ACE_OS::strcmp (ifr->ifr_name, "en0") == 0)
257 struct sockaddr_dl* sdl =
258 (struct sockaddr_dl *) &ifr->ifr_addr;
260 ACE_OS::memcpy (node->node,
261 LLADDR(sdl),
266 ptr += sizeof(ifr->ifr_name);
268 if(sizeof(ifr->ifr_addr) > ifr->ifr_addr.sa_len)
269 ptr += sizeof(ifr->ifr_addr);
270 else
271 ptr += ifr->ifr_addr.sa_len;
274 ACE_OS::close (handle);
276 return 0;
278 #elif defined ACE_VXWORKS
280 int name[] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
281 static const size_t name_elts = sizeof name / sizeof name[0];
283 size_t result_sz = 0u;
284 if (sysctl (name, name_elts, 0, &result_sz, 0, 0u) != 0)
285 return -1;
287 # ifdef ACE_HAS_ALLOC_HOOKS
288 char *const result =
289 static_cast<char *> (ACE_Allocator::instance ()->malloc (result_sz));
290 # define ACE_NETDB_CLEANUP ACE_Allocator::instance ()->free (result)
291 # else
292 char *const result = static_cast<char *> (ACE_OS::malloc (result_sz));
293 # define ACE_NETDB_CLEANUP ACE_OS::free (result)
294 # endif
296 if (sysctl (name, name_elts, result, &result_sz, 0, 0u) != 0)
298 ACE_NETDB_CLEANUP;
299 return -1;
302 for (size_t pos = 0, n; pos + sizeof (if_msghdr) < result_sz; pos += n)
304 if_msghdr *const hdr = reinterpret_cast<if_msghdr *> (result + pos);
305 n = hdr->ifm_msglen;
306 sockaddr_dl *const addr =
307 reinterpret_cast<sockaddr_dl *> (result + pos + sizeof (if_msghdr));
309 if (addr->sdl_alen >= sizeof node->node)
311 ACE_OS::memcpy (node->node, LLADDR (addr), sizeof node->node);
312 ACE_NETDB_CLEANUP;
313 return 0;
316 while (pos + n < result_sz)
318 ifa_msghdr *const ifa =
319 reinterpret_cast<ifa_msghdr *> (result + pos + n);
320 if (ifa->ifam_type != RTM_NEWADDR)
321 break;
322 n += ifa->ifam_msglen;
326 ACE_NETDB_CLEANUP;
327 # undef ACE_NETDB_CLEANUP
328 return -1;
330 #else
331 ACE_UNUSED_ARG (node);
332 ACE_NOTSUP_RETURN (-1);
333 #endif
336 #ifdef ACE_LACKS_GETADDRINFO
338 ACE_OS::getaddrinfo_emulation (const char *name, addrinfo **result)
340 hostent entry;
341 ACE_HOSTENT_DATA buffer;
342 int herr = 0;
343 const hostent *host = ACE_OS::gethostbyname_r (name, &entry, buffer, &herr);
345 if (host == 0)
347 switch (herr)
349 case NO_DATA:
350 case HOST_NOT_FOUND:
351 return EAI_NONAME;
352 case TRY_AGAIN:
353 return EAI_AGAIN;
354 case NO_RECOVERY:
355 return EAI_FAIL;
356 case ENOTSUP:
357 if (ACE_OS::inet_aton (name, (in_addr *) &buffer[0]) != 0)
359 host = &entry;
360 entry.h_length = sizeof (in_addr);
361 entry.h_addr_list = (char **) (buffer + sizeof (in_addr));
362 entry.h_addr_list[0] = buffer;
363 entry.h_addr_list[1] = 0;
364 break;
366 // fall-through
367 default:
368 errno = herr;
369 return EAI_SYSTEM;
373 size_t n = 0;
374 for (char **addr = host->h_addr_list; *addr; ++addr, ++n) /*empty*/;
376 # ifdef ACE_HAS_ALLOC_HOOKS
377 ACE_Allocator *const al = ACE_Allocator::instance ();
378 # define ACE_ALLOC al->
379 # else
380 # define ACE_ALLOC ACE_OS::
381 # endif
383 ACE_ALLOCATOR_RETURN (*result,
384 (addrinfo *) ACE_ALLOC calloc (n, sizeof (addrinfo)),
385 EAI_MEMORY);
387 sockaddr_in *const addr_storage =
388 (sockaddr_in *) ACE_ALLOC calloc (n, sizeof (sockaddr_in));
390 if (!addr_storage)
392 ACE_ALLOC free (*result);
393 *result = 0;
394 return EAI_MEMORY;
397 for (size_t i = 0; i < n; ++i)
399 (*result)[i].ai_family = AF_INET;
400 (*result)[i].ai_addrlen = sizeof (sockaddr_in);
401 (*result)[i].ai_addr = (sockaddr *) addr_storage + i;
402 (*result)[i].ai_addr->sa_family = AF_INET;
403 ACE_OS::memcpy (&addr_storage[i].sin_addr, host->h_addr_list[i],
404 (std::min) (size_t (host->h_length), sizeof (in_addr)));
405 if (i < n - 1)
406 (*result)[i].ai_next = (*result) + i + 1;
409 return 0;
412 void
413 ACE_OS::freeaddrinfo_emulation (addrinfo *result)
415 # ifdef ACE_HAS_ALLOC_HOOKS
416 ACE_Allocator *const al = ACE_Allocator::instance ();
417 al->free (result->ai_addr);
418 al->free (result);
419 # else
420 ACE_OS::free (result->ai_addr);
421 ACE_OS::free (result);
422 # endif
424 #endif /* ACE_LACKS_GETADDRINFO */
426 #ifdef ACE_LACKS_GETNAMEINFO
428 ACE_OS::getnameinfo_emulation (const sockaddr *saddr, ACE_SOCKET_LEN saddr_len,
429 char *host, ACE_SOCKET_LEN host_len)
431 if (saddr_len != sizeof (sockaddr_in) || saddr->sa_family != AF_INET)
432 return EAI_FAMILY; // IPv6 support requries actual OS-provided getnameinfo
434 const void *addr = &((const sockaddr_in *) saddr)->sin_addr;
435 int h_error;
436 hostent hentry;
437 ACE_HOSTENT_DATA buf;
438 hostent *const hp =
439 ACE_OS::gethostbyaddr_r (static_cast<const char *> (addr),
440 # ifdef ACE_LACKS_IN_ADDR_T
442 # else
443 sizeof (in_addr_t),
444 # endif
445 AF_INET, &hentry, buf, &h_error);
447 if (hp == 0 || hp->h_name == 0)
448 return EAI_NONAME;
450 if (ACE_OS::strlen (hp->h_name) >= size_t (host_len))
452 if (host_len > 0)
454 ACE_OS::memcpy (host, hp->h_name, host_len - 1);
455 host[host_len - 1] = '\0';
457 return EAI_OVERFLOW;
460 ACE_OS::strcpy (host, hp->h_name);
461 return 0;
463 #endif /* ACE_LACKS_GETNAMEINFO */
465 ACE_END_VERSIONED_NAMESPACE_DECL
467 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) && defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
468 # include "ace/OS_NS_Thread.h"
469 # include "ace/Object_Manager_Base.h"
471 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
474 ACE_OS::netdb_acquire ()
476 return ACE_OS::thread_mutex_lock ((ACE_thread_mutex_t *)
477 ACE_OS_Object_Manager::preallocated_object[
478 ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
482 ACE_OS::netdb_release ()
484 return ACE_OS::thread_mutex_unlock ((ACE_thread_mutex_t *)
485 ACE_OS_Object_Manager::preallocated_object[
486 ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
489 ACE_END_VERSIONED_NAMESPACE_DECL
491 # endif /* defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) */