Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / INET_Addr.cpp
blob25a1fb5d74fb74c1463c54db92540160b1ee5a83
1 // Defines the Internet domain address family address format.
2 #include "ace/INET_Addr.h"
4 #if !defined (__ACE_INLINE__)
5 #include "ace/INET_Addr.inl"
6 #endif /* __ACE_INLINE__ */
8 #include "ace/Log_Category.h"
9 #include "ace/OS_NS_stdio.h"
10 #include "ace/OS_NS_errno.h"
11 #include "ace/OS_NS_stdlib.h"
12 #include "ace/OS_Memory.h"
13 #include "ace/OS_NS_arpa_inet.h"
14 #include "ace/OS_NS_netdb.h"
15 #include "ace/OS_NS_unistd.h"
16 #include "ace/OS_NS_sys_socket.h"
17 #include "ace/Truncate.h"
18 #if defined (ACE_HAS_ALLOC_HOOKS)
19 # include "ace/Malloc_Base.h"
20 #endif /* ACE_HAS_ALLOC_HOOKS */
22 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
24 ACE_ALLOC_HOOK_DEFINE(ACE_INET_Addr)
26 // Transform the current address into string format.
28 int
29 ACE_INET_Addr::addr_to_string (ACE_TCHAR s[],
30 size_t size,
31 int ipaddr_format) const
33 ACE_TRACE ("ACE_INET_Addr::addr_to_string");
35 // XXX Can we (should we) include the scope id for IPv6 addresses?
36 char hoststr[MAXHOSTNAMELEN+1];
38 bool result = false;
39 if (ipaddr_format == 0)
40 result = (this->get_host_name (hoststr, MAXHOSTNAMELEN+1) == 0);
41 else
42 result = (this->get_host_addr (hoststr, MAXHOSTNAMELEN+1) != 0);
44 if (!result)
45 return -1;
47 size_t total_len =
48 ACE_OS::strlen (hoststr)
49 + 5 // ACE_OS::strlen ("65535"), Assuming the max port number.
50 + 1 // sizeof (':'), addr/port sep
51 + 1; // sizeof ('\0'), terminating NUL
52 ACE_TCHAR const *format = ACE_TEXT("%") ACE_TEXT_PRIs ACE_TEXT(":%d");
53 #if defined (ACE_HAS_IPV6)
54 if (ACE_OS::strchr (hoststr, ACE_TEXT (':')) != 0)
56 total_len += 2; // ACE_OS::strlen ("[]") IPv6 addr frames
57 format = ACE_TEXT("[%") ACE_TEXT_PRIs ACE_TEXT("]:%d");
59 #endif // ACE_HAS_IPV6
61 if (size < total_len)
62 return -1;
63 else
64 ACE_OS::snprintf (s, size, format,
65 ACE_TEXT_CHAR_TO_TCHAR (hoststr),
66 this->get_port_number ());
67 return 0;
70 void
71 ACE_INET_Addr::dump () const
73 #if defined (ACE_HAS_DUMP)
74 ACE_TRACE ("ACE_INET_Addr::dump");
76 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
78 ACE_TCHAR s[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16];
79 this->addr_to_string(s, ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16);
80 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("%s"), s));
81 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
82 #endif /* ACE_HAS_DUMP */
85 // Compare two addresses for inequality.
87 bool
88 ACE_INET_Addr::operator != (const ACE_INET_Addr &sap) const
90 ACE_TRACE ("ACE_INET_Addr::operator !=");
91 return !((*this) == sap);
94 // Compare two addresses for equality.
96 bool
97 ACE_INET_Addr::operator == (const ACE_INET_Addr &sap) const
99 ACE_TRACE ("ACE_INET_Addr::operator ==");
101 if (this->get_type () != sap.get_type ()
102 || this->get_size () != sap.get_size ())
103 return false;
105 return (ACE_OS::memcmp (&this->inet_addr_,
106 &sap.inet_addr_,
107 this->get_size ()) == 0);
110 bool
111 ACE_INET_Addr::is_ip_equal (const ACE_INET_Addr &sap) const
113 if (this->get_type () != sap.get_type ()
114 || this->get_size () != sap.get_size ())
115 return false;
117 #if defined (ACE_HAS_IPV6)
118 if (this->get_type () == PF_INET6)
120 const unsigned int *addr =
121 reinterpret_cast<const unsigned int*>(this->ip_addr_pointer());
122 const unsigned int *saddr =
123 reinterpret_cast<const unsigned int*>(sap.ip_addr_pointer());
124 return (addr[0] == saddr[0] &&
125 addr[1] == saddr[1] &&
126 addr[2] == saddr[2] &&
127 addr[3] == saddr[3]);
129 else
130 #endif /* ACE_HAS_IPV6 */
131 return this->get_ip_address () == sap.get_ip_address();
134 u_long
135 ACE_INET_Addr::hash () const
137 #if defined (ACE_HAS_IPV6)
138 if (this->get_type () == PF_INET6)
140 const unsigned int *addr = (const unsigned int*)this->ip_addr_pointer();
141 return addr[0] + addr[1] + addr[2] + addr[3] + this->get_port_number();
143 else
144 #endif /* ACE_HAS_IPV6 */
145 return this->get_ip_address () + this->get_port_number ();
148 bool
149 ACE_INET_Addr::next ()
151 if (this->inet_addrs_.empty () ||
152 this->inet_addrs_iter_ == this->inet_addrs_.end ())
153 return false;
155 union ip46 next_a = *this->inet_addrs_iter_++;
156 this->set_addr (&next_a, sizeof (next_a));
157 return true;
160 void
161 ACE_INET_Addr::reset ()
163 this->inet_addrs_iter_ = this->inet_addrs_.begin ();
164 this->next ();
167 ACE_INET_Addr::ACE_INET_Addr ()
168 : ACE_Addr (determine_type (), sizeof (inet_addr_))
170 // ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
171 this->reset_i ();
174 ACE_INET_Addr &
175 ACE_INET_Addr::operator= (const ACE_INET_Addr& rhs)
177 if (this != &rhs)
178 this->set (rhs);
179 return *this;
183 ACE_INET_Addr::set (const ACE_INET_Addr &sa)
185 ACE_TRACE ("ACE_INET_Addr::set");
187 if (sa.get_type () == AF_ANY)
188 // Ugh, this is really a base class, so don't copy it.
189 ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
190 else
192 // It's ok to make the copy.
193 ACE_OS::memcpy (&this->inet_addr_,
194 &sa.inet_addr_,
195 sa.get_size ());
197 this->set_type (sa.get_type());
198 this->set_size (sa.get_size());
199 this->inet_addrs_ = sa.inet_addrs_;
200 this->reset ();
203 return 0;
206 // Transform the string into the current addressing format.
209 ACE_INET_Addr::string_to_addr (const char s[], int address_family)
211 ACE_TRACE ("ACE_INET_Addr::string_to_addr");
212 int result;
213 char *ip_buf = 0;
214 char *ip_addr = 0;
216 // Need to make a duplicate since we'll be overwriting the string.
217 ACE_ALLOCATOR_RETURN (ip_buf,
218 ACE_OS::strdup (s),
219 -1);
220 ip_addr = ip_buf;
221 // We use strrchr because of IPv6 addresses.
222 char *port_p = ACE_OS::strrchr (ip_addr, ':');
223 #if defined (ACE_HAS_IPV6)
224 // Check for extended IPv6 format : '[' <ipv6 address> ']' ':' <port>
225 if (ip_addr[0] == '[')
227 // find closing bracket
228 char *cp_pos = ACE_OS::strchr (ip_addr, ']');
229 // check for port separator after closing bracket
230 // if not found leave it, error will come later
231 if (cp_pos)
233 *cp_pos = '\0'; // blank out ']'
234 ++ip_addr; // skip over '['
235 if (cp_pos[1] == ':')
236 port_p = cp_pos + 1;
237 else
238 port_p = cp_pos; // leads to error on missing port
241 #endif /* ACE_HAS_IPV6 */
243 if (port_p == 0) // Assume it's a port number.
245 char *endp = 0;
246 long const port = ACE_OS::strtol (ip_addr, &endp, 10);
248 if (*endp == '\0') // strtol scanned the entire string - all digits
250 if (port < 0 || port > ACE_MAX_DEFAULT_PORT)
251 result = -1;
252 else
253 result = this->set (u_short (port), ACE_UINT32 (INADDR_ANY));
255 else // port name
256 result = this->set (ip_addr, ACE_UINT32 (INADDR_ANY));
258 else
260 *port_p = '\0'; ++port_p; // skip over ':'
262 char *endp = 0;
263 long port = ACE_OS::strtol (port_p, &endp, 10);
265 if (*endp == '\0') // strtol scanned the entire string - all digits
267 if (port < 0 || port > ACE_MAX_DEFAULT_PORT)
268 result = -1;
269 else
270 result = this->set (u_short (port), ip_addr, 1, address_family);
272 else
273 result = this->set (port_p, ip_addr);
276 #if defined (ACE_HAS_ALLOC_HOOKS)
277 ACE_Allocator::instance()->free (ACE_MALLOC_T (ip_buf));
278 #else
279 ACE_OS::free (ACE_MALLOC_T (ip_buf));
280 #endif /* ACE_HAS_ALLOC_HOOKS */
281 return result;
285 ACE_INET_Addr::set (const char address[], int address_family)
287 ACE_TRACE ("ACE_INET_Addr::set");
288 this->reset_i ();
289 return this->string_to_addr (address, address_family);
292 ACE_INET_Addr::ACE_INET_Addr (const char address[], int address_family)
293 : ACE_Addr (determine_type (), sizeof (inet_addr_))
295 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
296 this->set (address, address_family);
299 #if defined (ACE_HAS_WCHAR)
300 ACE_INET_Addr::ACE_INET_Addr (const wchar_t address[], int address_family)
301 : ACE_Addr (determine_type (), sizeof (inet_addr_))
303 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
304 this->set (address, address_family);
307 #endif /* ACE_HAS_WCHAR */
309 // Copy constructor.
311 ACE_INET_Addr::ACE_INET_Addr (const ACE_INET_Addr &sa)
312 : ACE_Addr (sa.get_type (), sa.get_size())
314 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
315 this->set (sa);
318 // Initializes a ACE_INET_Addr from a PORT_NUMBER and a 32 bit Internet
319 // address.
321 ACE_INET_Addr::set (u_short port_number,
322 ACE_UINT32 inet_address,
323 int encode,
324 int map)
326 ACE_TRACE ("ACE_INET_Addr::set");
327 this->reset_i ();
328 this->set_address (reinterpret_cast<const char *> (&inet_address),
329 sizeof inet_address,
330 encode, map);
331 this->set_port_number (port_number, encode);
333 return 0;
336 // Initializes a ACE_INET_Addr from a PORT_NUMBER and the remote
337 // HOST_NAME.
339 ACE_INET_Addr::set (u_short port_number,
340 const char host_name[],
341 int encode,
342 int address_family)
344 ACE_TRACE ("ACE_INET_Addr::set");
346 // Yow, someone gave us a NULL host_name!
347 if (host_name == 0)
349 errno = EINVAL;
350 return -1;
353 this->reset_i ();
355 #if defined ACE_HAS_IPV6 && defined ACE_USES_IPV4_IPV6_MIGRATION
356 if (address_family == AF_UNSPEC && !ACE::ipv6_enabled ())
357 address_family = AF_INET;
358 #endif /* ACE_HAS_IPV6 && ACE_USES_IPV4_IPV6_MIGRATION */
360 #ifdef ACE_HAS_IPV6
361 if (address_family == AF_UNSPEC && ACE::ipv6_enabled ())
362 address_family = AF_INET6;
364 if (address_family != AF_INET
365 && ACE_OS::inet_pton (AF_INET6, host_name,
366 &this->inet_addr_.in6_.sin6_addr) == 1)
368 this->base_set (AF_INET6, sizeof this->inet_addr_.in4_);
369 # ifdef ACE_HAS_SOCKADDR_IN6_SIN6_LEN
370 this->inet_addr_.in6_.sin6_len = sizeof this->inet_addr_.in6_;
371 # endif
372 this->inet_addr_.in6_.sin6_family = AF_INET6;
373 this->set_size (sizeof this->inet_addr_.in6_);
374 this->set_type (AF_INET6);
375 this->set_port_number (port_number, encode);
376 return 0;
378 #else
379 address_family = AF_INET;
380 #endif /* ACE_HAS_IPV6 */
382 if (ACE_OS::inet_pton (AF_INET, host_name,
383 &this->inet_addr_.in4_.sin_addr) == 1)
385 this->base_set (AF_INET, sizeof this->inet_addr_.in4_);
386 #ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
387 this->inet_addr_.in4_.sin_len = sizeof this->inet_addr_.in4_;
388 #endif
389 this->inet_addr_.in4_.sin_family = AF_INET;
390 this->set_size (sizeof this->inet_addr_.in4_);
391 this->set_type (AF_INET);
392 this->set_port_number (port_number, encode);
393 return 0;
396 addrinfo hints;
397 ACE_OS::memset (&hints, 0, sizeof hints);
398 hints.ai_family = address_family;
399 // The ai_flags used to contain AI_ADDRCONFIG as well but that prevented
400 // lookups from completing if there is no, or only a loopback, IPv6
401 // interface configured. See Bugzilla 4211 for more info.
403 hints.ai_flags = AI_V4MAPPED;
404 #if defined(ACE_HAS_IPV6) && defined(AI_ALL)
405 // Without AI_ALL, Windows machines exhibit inconsistent behaviors on
406 // difference machines we have tested.
407 hints.ai_flags |= AI_ALL;
408 #endif
410 // Note - specify the socktype here to avoid getting multiple entries
411 // returned with the same address for different socket types or
412 // protocols. If this causes a problem for some reason (an address that's
413 // available for TCP but not UDP, or vice-versa) this will need to change
414 // back to unrestricted hints and weed out the duplicate addresses by
415 // searching this->inet_addrs_ which would slow things down.
416 hints.ai_socktype = SOCK_STREAM;
418 addrinfo *res = 0;
419 const int error = ACE_OS::getaddrinfo (host_name, 0, &hints, &res);
421 if (error)
423 errno = error;
424 return -1;
427 this->set_type (res->ai_family);
429 for (addrinfo *curr = res; curr; curr = curr->ai_next)
431 ip46 addr;
432 ACE_OS::memcpy (&addr, curr->ai_addr, curr->ai_addrlen);
433 #ifdef ACE_HAS_IPV6
434 if (curr->ai_family == AF_INET6)
435 addr.in6_.sin6_port = encode ? ACE_NTOHS (port_number) : port_number;
436 else
437 #endif
438 addr.in4_.sin_port = encode ? ACE_NTOHS (port_number) : port_number;
439 this->inet_addrs_.push_back (addr);
442 ACE_OS::freeaddrinfo (res);
443 this->reset ();
444 return 0;
447 /// Helper function to get a port number from a port name.
448 static int get_port_number_from_name (const char port_name[],
449 const char protocol[])
451 // Maybe port_name is directly a port number?
452 char *endp = 0;
453 long port_number = ACE_OS::strtol (port_name, &endp, 10);
455 if (*endp == '\0')
457 // port_name was really a number, and nothing else.
459 // Check for overflow.
460 if (port_number < 0 || port_number > ACE_MAX_DEFAULT_PORT)
461 return -1;
463 // Return the port number. NOTE: this number must
464 // be returned in network byte order!
465 u_short n = static_cast<u_short> (port_number);
466 n = ACE_HTONS (n);
467 return n;
470 // We try to resolve port number from its name.
471 port_number = -1;
472 #if defined (ACE_LACKS_GETSERVBYNAME)
473 ACE_UNUSED_ARG (port_name);
474 ACE_UNUSED_ARG (protocol);
475 #else
476 servent sentry;
477 ACE_SERVENT_DATA buf;
478 servent *sp = ACE_OS::getservbyname_r (port_name,
479 protocol,
480 &sentry,
481 buf);
482 if (sp != 0)
483 port_number = sp->s_port;
484 #endif /* ACE_LACKS_GETSERVBYNAME */
486 return port_number;
489 /// Initializes a ACE_INET_Addr from a @a port_name and the remote
490 /// @a host_name.
492 ACE_INET_Addr::set (const char port_name[],
493 const char host_name[],
494 const char protocol[])
496 ACE_TRACE ("ACE_INET_Addr::set");
498 this->reset_i ();
499 int const port_number = get_port_number_from_name (port_name, protocol);
500 if (port_number == -1)
502 ACE_NOTSUP_RETURN (-1);
505 int address_family = PF_UNSPEC;
506 if (ACE_OS::strcmp(protocol, "tcp") == 0)
507 address_family = AF_INET;
509 # if defined (ACE_HAS_IPV6)
510 if (ACE_OS::strcmp (protocol, "tcp6") == 0)
511 address_family = AF_INET6;
512 # endif /* ACE_HAS_IPV6 */
514 return this->set (static_cast<u_short> (port_number),
515 host_name, 0, address_family);
518 /// Initializes a ACE_INET_Addr from a @a port_name and a 32 bit
519 /// Internet address.
521 ACE_INET_Addr::set (const char port_name[],
522 ACE_UINT32 inet_address,
523 const char protocol[])
525 ACE_TRACE ("ACE_INET_Addr::set");
527 this->reset_i ();
528 int const port_number = get_port_number_from_name (port_name, protocol);
529 if (port_number == -1)
531 ACE_NOTSUP_RETURN (-1);
534 return this->set (static_cast<u_short> (port_number),
535 inet_address, 0);
538 // Creates a ACE_INET_Addr from a PORT_NUMBER and the remote
539 // HOST_NAME.
540 ACE_INET_Addr::ACE_INET_Addr (u_short port_number,
541 const char host_name[],
542 int address_family)
543 : ACE_Addr (determine_type (), sizeof (inet_addr_))
545 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
546 ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
547 if (this->set (port_number,
548 host_name,
550 address_family) == -1)
551 ACELIB_ERROR ((LM_ERROR,
552 ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr: %p\n"),
553 ACE_TEXT_CHAR_TO_TCHAR ((host_name == 0) ?
554 "<unknown>" : host_name)));
557 #if defined (ACE_HAS_WCHAR)
558 ACE_INET_Addr::ACE_INET_Addr (u_short port_number,
559 const wchar_t host_name[],
560 int address_family)
561 : ACE_Addr (determine_type (), sizeof (inet_addr_))
563 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
564 ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_));
565 if (this->set (port_number,
566 host_name,
568 address_family) == -1)
569 ACELIB_ERROR ((LM_ERROR,
570 ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr: %p\n"),
571 ACE_TEXT_WCHAR_TO_TCHAR ((host_name == 0) ?
572 ACE_TEXT_WIDE ("<unknown>") :
573 host_name)));
575 #endif /* ACE_HAS_WCHAR */
577 // Creates a ACE_INET_Addr from a sockaddr_in structure.
579 ACE_INET_Addr::set (const sockaddr_in *addr, int len)
581 ACE_TRACE ("ACE_INET_Addr::set");
583 this->reset_i ();
584 if (addr->sin_family == AF_INET)
586 int const maxlen = static_cast<int> (sizeof (this->inet_addr_.in4_));
587 if (len > maxlen)
588 len = maxlen;
589 ACE_OS::memcpy (&this->inet_addr_.in4_, addr, len);
590 this->base_set (AF_INET, len);
591 return 0;
593 #if defined (ACE_HAS_IPV6)
594 else if (addr->sin_family == AF_INET6)
596 int const maxlen = static_cast<int> (sizeof (this->inet_addr_.in6_));
597 if (len > maxlen)
598 len = maxlen;
599 ACE_OS::memcpy (&this->inet_addr_.in6_, addr, len);
600 this->base_set (AF_INET6, len);
601 return 0;
603 #endif /* ACE_HAS_IPV6 */
605 errno = EAFNOSUPPORT;
606 return -1;
609 // Return the address.
610 void *
611 ACE_INET_Addr::get_addr () const
613 ACE_TRACE ("ACE_INET_Addr::get_addr");
614 return (void*)&this->inet_addr_;
617 void
618 ACE_INET_Addr::set_addr (const void *addr, int len)
620 this->set_addr (addr, len, 0);
623 // Set a pointer to the address.
624 void
625 ACE_INET_Addr::set_addr (const void *addr, int /* len */, int map)
627 ACE_TRACE ("ACE_INET_Addr::set_addr");
628 const struct sockaddr_in *getfamily =
629 static_cast<const struct sockaddr_in *> (addr);
631 if (getfamily->sin_family == AF_INET)
633 #if defined (ACE_HAS_IPV6)
634 if (map)
635 this->set_type (AF_INET6);
636 else
637 #endif /* ACE_HAS_IPV6 */
638 this->set_type (AF_INET);
639 this->set_port_number (getfamily->sin_port, 0);
640 this->set_address (reinterpret_cast<const char*> (&getfamily->sin_addr),
641 sizeof (getfamily->sin_addr),
642 0, map);
644 #if defined (ACE_HAS_IPV6)
645 else if (getfamily->sin_family == AF_INET6)
647 const struct sockaddr_in6 *in6 =
648 static_cast<const struct sockaddr_in6*> (addr);
649 this->set_port_number (in6->sin6_port, 0);
650 this->set_address (reinterpret_cast<const char*> (&in6->sin6_addr),
651 sizeof (in6->sin6_addr),
653 this->inet_addr_.in6_.sin6_scope_id = in6->sin6_scope_id;
655 #endif // ACE_HAS_IPV6
658 // Creates a ACE_INET_Addr from a sockaddr_in structure.
659 ACE_INET_Addr::ACE_INET_Addr (const sockaddr_in *addr, int len)
660 : ACE_Addr (determine_type (), sizeof (inet_addr_))
662 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
663 this->set (addr, len);
666 // Creates a ACE_INET_Addr from a PORT_NUMBER and an Internet address.
667 ACE_INET_Addr::ACE_INET_Addr (u_short port_number,
668 ACE_UINT32 inet_address)
669 : ACE_Addr (determine_type (), sizeof (inet_addr_))
671 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
672 if (this->set (port_number, inet_address) == -1)
673 ACELIB_ERROR ((LM_ERROR,
674 ACE_TEXT ("%p\n"),
675 ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
678 // Creates a ACE_INET_Addr from a PORT_NAME and the remote
679 // HOST_NAME.
680 ACE_INET_Addr::ACE_INET_Addr (const char port_name[],
681 const char host_name[],
682 const char protocol[])
683 : ACE_Addr (determine_type (), sizeof (inet_addr_))
685 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
686 if (this->set (port_name,
687 host_name,
688 protocol) == -1)
689 ACELIB_ERROR ((LM_ERROR,
690 ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
693 #if defined (ACE_HAS_WCHAR)
694 ACE_INET_Addr::ACE_INET_Addr (const wchar_t port_name[],
695 const wchar_t host_name[],
696 const wchar_t protocol[])
697 : ACE_Addr (determine_type (), sizeof (inet_addr_))
699 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
700 if (this->set (port_name,
701 host_name,
702 protocol) == -1)
703 ACELIB_ERROR ((LM_ERROR,
704 ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
706 #endif /* ACE_HAS_WCHAR */
708 // Creates a ACE_INET_Addr from a PORT_NAME and an Internet address.
709 ACE_INET_Addr::ACE_INET_Addr (const char port_name[],
710 ACE_UINT32 inet_address,
711 const char protocol[])
712 : ACE_Addr (determine_type (), sizeof (inet_addr_))
714 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
715 if (this->set (port_name,
716 ACE_HTONL (inet_address),
717 protocol) == -1)
718 ACELIB_ERROR ((LM_ERROR,
719 ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
722 #if defined (ACE_HAS_WCHAR)
723 ACE_INET_Addr::ACE_INET_Addr (const wchar_t port_name[],
724 ACE_UINT32 inet_address,
725 const wchar_t protocol[])
726 : ACE_Addr (determine_type (), sizeof (inet_addr_))
728 ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr");
729 if (this->set (port_name,
730 ACE_HTONL (inet_address),
731 protocol) == -1)
732 ACELIB_ERROR ((LM_ERROR,
733 ACE_TEXT ("ACE_INET_Addr::ACE_INET_Addr")));
735 #endif /* ACE_HAS_WCHAR */
737 ACE_INET_Addr::~ACE_INET_Addr ()
742 ACE_INET_Addr::get_host_name (char hostname[],
743 size_t len) const
745 ACE_TRACE ("ACE_INET_Addr::get_host_name");
747 int result;
748 if (len > 1)
750 result = this->get_host_name_i (hostname,len);
751 if (result < 0)
753 if (result == -2)
754 // We know that hostname is nul-terminated
755 result = -1;
756 else
758 //result == -1;
759 // This could be worse than hostname[len -1] = '\0'?
760 hostname[0] = '\0';
764 else
766 if (len == 1)
767 hostname[0] = '\0';
768 result = -1;
771 return result;
774 #if defined (ACE_HAS_WCHAR)
776 ACE_INET_Addr::get_host_name (wchar_t hostname[],
777 size_t len) const
779 ACE_TRACE ("ACE_INET_Addr::get_host_name");
781 char char_hostname [MAXHOSTNAMELEN + 1];
783 // We have a build in limitation of MAXHOSTNAMELEN
784 if (len > MAXHOSTNAMELEN + 1)
785 len = MAXHOSTNAMELEN + 1;
787 // Call the char version
788 int const result = this->get_host_name (char_hostname, len);
790 // And copy it over, if successful
791 if (result == 0)
792 ACE_OS::strcpy (hostname,
793 ACE_Ascii_To_Wide (char_hostname).wchar_rep ());
795 return result;
797 #endif /* ACE_HAS_WCHAR */
799 // Return the character representation of the hostname.
801 const char *
802 ACE_INET_Addr::get_host_name () const
804 ACE_TRACE ("ACE_INET_Addr::get_host_name");
806 static char name[MAXHOSTNAMELEN + 1];
807 if (this->get_host_name (name, MAXHOSTNAMELEN + 1) == -1)
808 ACE_OS::strcpy (name, "<unknown>");
809 return name;
812 void
813 ACE_INET_Addr::set_port_number (u_short port_number,
814 int encode)
816 ACE_TRACE ("ACE_INET_Addr::set_port_number");
818 if (encode)
819 port_number = ACE_HTONS (port_number);
821 #if defined (ACE_HAS_IPV6)
822 if (this->get_type () == AF_INET6)
823 this->inet_addr_.in6_.sin6_port = port_number;
824 else
825 #endif /* ACE_HAS_IPV6 */
826 this->inet_addr_.in4_.sin_port = port_number;
828 if (this->inet_addrs_.empty ())
829 return;
830 for (std::vector<union ip46>::iterator i = this->inet_addrs_.begin ();
831 i != this->inet_addrs_.end ();
832 i++)
834 #if defined (ACE_HAS_IPV6)
835 if (this->get_type () == AF_INET6)
836 i->in6_.sin6_port = port_number;
837 else
838 #endif /* ACE_HAS_IPV6 */
839 i->in4_.sin_port = port_number;
843 // returns -2 when the hostname is truncated
845 ACE_INET_Addr::get_host_name_i (char hostname[], size_t len) const
847 ACE_TRACE ("ACE_INET_Addr::get_host_name_i");
849 #if defined (ACE_HAS_IPV6)
850 if ((this->get_type () == PF_INET6 &&
851 0 == ACE_OS::memcmp (&this->inet_addr_.in6_.sin6_addr,
852 &in6addr_any,
853 sizeof (this->inet_addr_.in6_.sin6_addr)))
855 (this->get_type () == PF_INET &&
856 this->inet_addr_.in4_.sin_addr.s_addr == INADDR_ANY))
857 #else
858 if (this->inet_addr_.in4_.sin_addr.s_addr == INADDR_ANY)
859 #endif /* ACE_HAS_IPV6 */
860 return (ACE_OS::hostname (hostname, len) == -1) ? -1 : 0;
862 const ACE_SOCKET_LEN addr_size =
863 #ifdef ACE_HAS_IPV6
864 (this->get_type () == PF_INET6) ? sizeof (sockaddr_in6) :
865 #endif
866 sizeof (sockaddr_in);
868 const int res = ACE_OS::getnameinfo ((const sockaddr *) this->get_addr (),
869 addr_size, hostname,
870 static_cast<ACE_SOCKET_LEN> (len),
871 0, 0, 0);
872 return (res == 0) ? 0 : -1;
875 int ACE_INET_Addr::set_address (const char *ip_addr,
876 int len,
877 int encode /* = 1 */,
878 int map /* = 0 */)
880 ACE_TRACE ("ACE_INET_Addr::set_address");
881 // This is really intended for IPv4. If the object is IPv4, or the type
882 // hasn't been set but it's a 4-byte address, go ahead. If this is an
883 // IPv6 object and <encode> is requested, refuse.
884 if (encode && len != 4)
886 errno = EAFNOSUPPORT;
887 return -1;
890 if (len == 4)
892 ACE_UINT32 ip4 = *reinterpret_cast<const ACE_UINT32 *> (ip_addr);
893 if (encode)
894 ip4 = ACE_HTONL (ip4);
897 if (this->get_type () == AF_INET && map == 0) {
898 this->base_set (AF_INET, sizeof (this->inet_addr_.in4_));
899 #ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
900 this->inet_addr_.in4_.sin_len = sizeof (this->inet_addr_.in4_);
901 #endif
902 this->inet_addr_.in4_.sin_family = AF_INET;
903 this->set_size (sizeof (this->inet_addr_.in4_));
904 ACE_OS::memcpy (&this->inet_addr_.in4_.sin_addr,
905 &ip4,
906 len);
908 #if defined (ACE_HAS_IPV6)
909 else if (map == 0)
911 // this->set_type (AF_INET);
912 this->base_set (AF_INET, sizeof (this->inet_addr_.in4_));
913 #ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
914 this->inet_addr_.in4_.sin_len = sizeof (this->inet_addr_.in4_);
915 #endif
916 this->inet_addr_.in4_.sin_family = AF_INET;
917 this->set_size (sizeof (this->inet_addr_.in4_));
918 ACE_OS::memcpy (&this->inet_addr_.in4_.sin_addr,
919 &ip4, len);
921 // If given an IPv4 address to copy to an IPv6 object, map it to
922 // an IPv4-mapped IPv6 address.
923 else
925 this->base_set (AF_INET6, sizeof (this->inet_addr_.in6_));
926 #ifdef ACE_HAS_SOCKADDR_IN6_SIN6_LEN
927 this->inet_addr_.in6_.sin6_len = sizeof (this->inet_addr_.in6_);
928 #endif
929 this->inet_addr_.in6_.sin6_family = AF_INET6;
930 this->set_size (sizeof (this->inet_addr_.in6_));
931 if (ip4 == ACE_HTONL (INADDR_ANY))
933 in6_addr const ip6 = in6addr_any;
934 ACE_OS::memcpy (&this->inet_addr_.in6_.sin6_addr,
935 &ip6,
936 sizeof (ip6));
937 return 0;
939 else
941 // Build up a 128 bit address. An IPv4-mapped IPv6 address
942 // is defined as 0:0:0:0:0:ffff:IPv4_address. This is defined
943 // in RFC 1884 */
944 ACE_OS::memset (&this->inet_addr_.in6_.sin6_addr, 0, 16);
945 this->inet_addr_.in6_.sin6_addr.s6_addr[10] =
946 this->inet_addr_.in6_.sin6_addr.s6_addr[11] = 0xff;
947 ACE_OS::memcpy
948 (&this->inet_addr_.in6_.sin6_addr.s6_addr[12], &ip4, 4);
951 #endif /* ACE_HAS_IPV6 */
953 return 0;
954 } /* end if (len == 4) */
955 #if defined (ACE_HAS_IPV6)
956 else if (len == 16)
958 if (this->get_type () != PF_INET6)
960 errno = EAFNOSUPPORT;
961 return -1;
963 // We protect ourselves up above so IPv6 must be possible here.
964 this->base_set (AF_INET6, sizeof (this->inet_addr_.in6_));
965 this->inet_addr_.in6_.sin6_family = AF_INET6;
966 #ifdef ACE_HAS_SOCKADDR_IN6_SIN6_LEN
967 this->inet_addr_.in6_.sin6_len = sizeof (this->inet_addr_.in6_);
968 #endif
969 ACE_OS::memcpy (&this->inet_addr_.in6_.sin6_addr, ip_addr, len);
970 return 0;
971 } /* end len == 16 */
972 #endif /* ACE_HAS_IPV6 */
974 // Here with an unrecognized length.
975 errno = EAFNOSUPPORT;
976 return -1;
979 #if (defined (ACE_LINUX) || defined (ACE_WIN32)) && defined (ACE_HAS_IPV6)
981 ACE_INET_Addr::set_interface (const char *intf_name)
983 if (this->get_type () == PF_INET6 &&
984 (IN6_IS_ADDR_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr) ||
985 IN6_IS_ADDR_MC_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr)))
987 #if defined (ACE_LINUX)
988 this->inet_addr_.in6_.sin6_scope_id =
989 ACE_OS::if_nametoindex (intf_name);
990 #else
991 this->inet_addr_.in6_.sin6_scope_id =
992 intf_name ? ACE_OS::atoi (intf_name) : 0;
993 #endif
994 // check to see if the interface lookup succeeded
995 if (this->inet_addr_.in6_.sin6_scope_id != 0)
996 return 0;
997 else
998 return -1;
1000 else
1001 return 0;
1003 #endif /* ACE_LINUX && ACE_HAS_IPV6 */
1005 const char *
1006 ACE_INET_Addr::get_host_addr (char *dst, int size) const
1008 #if defined (ACE_HAS_IPV6)
1009 if (this->get_type () == AF_INET6)
1011 // mcorino@remedy.nl - Aug-26, 2005
1012 // I don't think this should be done because it results in a decimal address
1013 // representation which is not distinguishable from the IPv4 form which makes
1014 // it impossible to resolve back to an IPv6 INET_Addr without prior knowledge
1015 // that this was such an address to begin with.
1017 //if (IN6_IS_ADDR_V4MAPPED (&this->inet_addr_.in6_.sin6_addr))
1019 // ACE_UINT32 addr;
1020 // addr = this->get_ip_address();
1021 // addr = ACE_HTONL (addr);
1022 // return ACE_OS::inet_ntop (AF_INET, &addr, dst, size);
1025 # if defined (ACE_WIN32)
1026 sockaddr *sa = reinterpret_cast<sockaddr *>
1027 (const_cast<sockaddr_in6 *> (&this->inet_addr_.in6_));
1028 if (ACE_OS::getnameinfo (sa, this->get_size (), dst, size,
1029 0, 0, // Don't want service name
1030 NI_NUMERICHOST) == 0)
1031 return dst;
1032 ACE_OS::set_errno_to_wsa_last_error ();
1033 return 0;
1034 # else
1035 const char *ch = ACE_OS::inet_ntop (AF_INET6,
1036 &this->inet_addr_.in6_.sin6_addr,
1037 dst,
1038 size);
1039 #if defined (ACE_LINUX)
1040 if ((IN6_IS_ADDR_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr) ||
1041 IN6_IS_ADDR_MC_LINKLOCAL (&this->inet_addr_.in6_.sin6_addr)) &&
1042 this->inet_addr_.in6_.sin6_scope_id != 0)
1044 char scope_buf[32];
1045 ACE_OS::snprintf (scope_buf, 32, "%%%u",
1046 this->inet_addr_.in6_.sin6_scope_id);
1047 if ((ACE_OS::strlen (ch)+ACE_OS::strlen (scope_buf)) < (size_t)size)
1049 ACE_OS::strcat (dst, scope_buf);
1052 #endif
1053 return ch;
1054 # endif /* ACE_WIN32 */
1056 #endif /* ACE_HAS_IPV6 */
1058 return ACE_OS::inet_ntop (AF_INET,
1059 &this->inet_addr_.in4_.sin_addr,
1060 dst,
1061 size);
1064 // Return the dotted Internet address.
1065 const char *
1066 ACE_INET_Addr::get_host_addr () const
1068 ACE_TRACE ("ACE_INET_Addr::get_host_addr");
1069 #if defined (ACE_HAS_IPV6)
1070 static char buf[INET6_ADDRSTRLEN];
1071 return this->get_host_addr (buf, INET6_ADDRSTRLEN);
1072 #else /* ACE_HAS_IPV6 */
1073 static char buf[INET_ADDRSTRLEN];
1074 return this->get_host_addr (buf, INET_ADDRSTRLEN);
1075 #endif /* !ACE_HAS_IPV6 */
1078 // Return the 4-byte IP address, converting it into host byte order.
1079 ACE_UINT32
1080 ACE_INET_Addr::get_ip_address () const
1082 ACE_TRACE ("ACE_INET_Addr::get_ip_address");
1083 #if defined (ACE_HAS_IPV6)
1084 if (this->get_type () == AF_INET6)
1086 if (IN6_IS_ADDR_V4MAPPED (&this->inet_addr_.in6_.sin6_addr) ||
1087 IN6_IS_ADDR_V4COMPAT (&this->inet_addr_.in6_.sin6_addr))
1089 ACE_UINT32 addr;
1090 // Return the last 32 bits of the address
1091 char *thisaddrptr = (char*)this->ip_addr_pointer ();
1092 thisaddrptr += 128/8 - 32/8;
1093 ACE_OS::memcpy (&addr, thisaddrptr, sizeof (addr));
1094 return ACE_NTOHL (addr);
1097 ACELIB_ERROR ((LM_ERROR,
1098 ACE_TEXT ("ACE_INET_Addr::get_ip_address: address is a IPv6 address not IPv4\n")));
1099 errno = EAFNOSUPPORT;
1100 return 0;
1102 #endif /* ACE_HAS_IPV6 */
1103 return ACE_NTOHL (ACE_UINT32 (this->inet_addr_.in4_.sin_addr.s_addr));
1106 ACE_END_VERSIONED_NAMESPACE_DECL