diff options
-rw-r--r-- | ChangeLog | 65 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-02a | 65 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-03a | 65 | ||||
-rw-r--r-- | ace/Asynch_Acceptor.cpp | 2 | ||||
-rw-r--r-- | ace/INET_Addr.cpp | 495 | ||||
-rw-r--r-- | ace/INET_Addr.h | 72 | ||||
-rw-r--r-- | ace/INET_Addr.i | 127 | ||||
-rw-r--r-- | ace/MEM_Addr.cpp | 10 | ||||
-rw-r--r-- | ace/MEM_Connector.cpp | 5 | ||||
-rw-r--r-- | ace/OS.h | 23 | ||||
-rw-r--r-- | ace/OS.i | 71 | ||||
-rw-r--r-- | ace/SOCK.cpp | 2 | ||||
-rw-r--r-- | ace/SOCK_Acceptor.cpp | 223 | ||||
-rw-r--r-- | ace/SOCK_Acceptor.h | 18 | ||||
-rw-r--r-- | ace/SOCK_CODgram.h | 5 | ||||
-rw-r--r-- | ace/SOCK_Connector.cpp | 11 | ||||
-rw-r--r-- | ace/SOCK_Connector.h | 8 | ||||
-rw-r--r-- | ace/SOCK_Dgram.cpp | 12 | ||||
-rw-r--r-- | ace/SOCK_Dgram.h | 5 | ||||
-rw-r--r-- | ace/Sock_Connect.cpp | 79 | ||||
-rw-r--r-- | ace/Sock_Connect.h | 15 | ||||
-rw-r--r-- | tests/INET_Addr_Test.cpp | 93 | ||||
-rw-r--r-- | tests/Makefile | 1 |
23 files changed, 1149 insertions, 323 deletions
diff --git a/ChangeLog b/ChangeLog index a6d3a0e8539..eb5cc58babd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,60 @@ +Mon Dec 3 15:50:42 2001 Steve Huston <shuston@riverace.com> + + * IPv6 changes done by John Aughey and myself. To enable IPv6 + support for a build, put this in your config.h file: + #define ACE_HAS_IPV6 + If your build with IPv6 enabled must also run on systems where + the IPv6 support in the kernel is not actually turned on (for + example, Redhat Linux 7 by default), also add this to your + config.h file: + #define ACE_USES_IPV4_IPV6_MIGRATION + + * ace/ACE.cpp (format_hexdump): Add \n to last part of a dump line. + + * ace/INET_Addr.(h i cpp): If IPv6 is enabled, the inet_addr_ + member is now a union of sockaddr_in and sockaddr_in6. Which + one is legit is noted in ACE_Addr::type as well as the family + member of either of the union members. The host name lookup + functions can look up ipv6 as well as ipv4 names, and the + caller can force one or the other by using the address_family + argument to set(). + + * ace/OS.(h i): Removed ACE_OS::gethostbyname2; replaced it with + the more correctly-named and more flexible ACE_OS::getipnodebyname. + Also added ACE_OS::getipnodebyaddr. These are the IPv6-capable + functions analogous to gethostbyname and gethostbyaddr. + + * ace/SOCK.cpp (get_remote_addr, get_local_addr): Set up the + ACE_Addr's type properly to account for ipv4/6 possibilities. + + * ace/SOCK_Acceptor.(h cpp): Allow accepting on ipv4 and ipv6 sockets. + + * ace/SOCK_CODgram.h: + * ace/SOCK_Connector.(cpp h ): + * ace/SOCK_Dgram.(cpp h ): Change default protocol family from + PF_INET to vary and take advantage of IPv6 if available. + + * ace/Sock_Connect.(cpp h): Added ACE_Sock_Connect::ipv6_enabled() + method - it checks to see if the running kernel can do IPv6 + sockets or not. + + * ace/Sock_Connect.cpp (get_ip_interfaces): Removed a #if 0'd + block that had possible specializations for MSVC 4.2. It's + been a number of years, and it's obviously not needed. + + * ace/MEM_Addr.cpp (same_host): Don't try to compare binary + addresses directly... get ACE_INET_Addr objects, clear the port + numbers, and compare them. + + * ace/MEM_Connector.cpp (connect): Print error text with message. + + * ace/Asynch_Acceptor.cpp (open): For the new socket, use the + protocol family from the listen address, not PF_INET. + + * tests/INET_Addr_Test.cpp: New test. + + * tests/Makefile: Added INET_Addr_Test. + Mon Dec 3 10:54:34 2001 Carlos O'Ryan <coryan@uci.edu> * ace/OS.h: @@ -959,6 +1016,14 @@ Wed Oct 24 23:59:13 2001 Douglas C. Schmidt <schmidt@macarena.cs.wustl.edu> by the pointer. Thanks to Juan Jose Comellas <uanjo@comellas.org> for reporting this. +Wed Oct 31 16:45:07 2001 Ossama Othman <ossama@uci.edu> + + * ace/OS.h (llseek): + + Made ACE_OS::llseek() a static method, as it was originally + intended to be. Thanks to Doron Rajwan <doron@BANDWIZ.COM> for + pointing out the problem. + Tue Oct 30 22:53:57 2001 Ossama Othman <ossama@uci.edu> * ace/Svc_Conf_l.cpp: diff --git a/ChangeLogs/ChangeLog-02a b/ChangeLogs/ChangeLog-02a index a6d3a0e8539..eb5cc58babd 100644 --- a/ChangeLogs/ChangeLog-02a +++ b/ChangeLogs/ChangeLog-02a @@ -1,3 +1,60 @@ +Mon Dec 3 15:50:42 2001 Steve Huston <shuston@riverace.com> + + * IPv6 changes done by John Aughey and myself. To enable IPv6 + support for a build, put this in your config.h file: + #define ACE_HAS_IPV6 + If your build with IPv6 enabled must also run on systems where + the IPv6 support in the kernel is not actually turned on (for + example, Redhat Linux 7 by default), also add this to your + config.h file: + #define ACE_USES_IPV4_IPV6_MIGRATION + + * ace/ACE.cpp (format_hexdump): Add \n to last part of a dump line. + + * ace/INET_Addr.(h i cpp): If IPv6 is enabled, the inet_addr_ + member is now a union of sockaddr_in and sockaddr_in6. Which + one is legit is noted in ACE_Addr::type as well as the family + member of either of the union members. The host name lookup + functions can look up ipv6 as well as ipv4 names, and the + caller can force one or the other by using the address_family + argument to set(). + + * ace/OS.(h i): Removed ACE_OS::gethostbyname2; replaced it with + the more correctly-named and more flexible ACE_OS::getipnodebyname. + Also added ACE_OS::getipnodebyaddr. These are the IPv6-capable + functions analogous to gethostbyname and gethostbyaddr. + + * ace/SOCK.cpp (get_remote_addr, get_local_addr): Set up the + ACE_Addr's type properly to account for ipv4/6 possibilities. + + * ace/SOCK_Acceptor.(h cpp): Allow accepting on ipv4 and ipv6 sockets. + + * ace/SOCK_CODgram.h: + * ace/SOCK_Connector.(cpp h ): + * ace/SOCK_Dgram.(cpp h ): Change default protocol family from + PF_INET to vary and take advantage of IPv6 if available. + + * ace/Sock_Connect.(cpp h): Added ACE_Sock_Connect::ipv6_enabled() + method - it checks to see if the running kernel can do IPv6 + sockets or not. + + * ace/Sock_Connect.cpp (get_ip_interfaces): Removed a #if 0'd + block that had possible specializations for MSVC 4.2. It's + been a number of years, and it's obviously not needed. + + * ace/MEM_Addr.cpp (same_host): Don't try to compare binary + addresses directly... get ACE_INET_Addr objects, clear the port + numbers, and compare them. + + * ace/MEM_Connector.cpp (connect): Print error text with message. + + * ace/Asynch_Acceptor.cpp (open): For the new socket, use the + protocol family from the listen address, not PF_INET. + + * tests/INET_Addr_Test.cpp: New test. + + * tests/Makefile: Added INET_Addr_Test. + Mon Dec 3 10:54:34 2001 Carlos O'Ryan <coryan@uci.edu> * ace/OS.h: @@ -959,6 +1016,14 @@ Wed Oct 24 23:59:13 2001 Douglas C. Schmidt <schmidt@macarena.cs.wustl.edu> by the pointer. Thanks to Juan Jose Comellas <uanjo@comellas.org> for reporting this. +Wed Oct 31 16:45:07 2001 Ossama Othman <ossama@uci.edu> + + * ace/OS.h (llseek): + + Made ACE_OS::llseek() a static method, as it was originally + intended to be. Thanks to Doron Rajwan <doron@BANDWIZ.COM> for + pointing out the problem. + Tue Oct 30 22:53:57 2001 Ossama Othman <ossama@uci.edu> * ace/Svc_Conf_l.cpp: diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a index a6d3a0e8539..eb5cc58babd 100644 --- a/ChangeLogs/ChangeLog-03a +++ b/ChangeLogs/ChangeLog-03a @@ -1,3 +1,60 @@ +Mon Dec 3 15:50:42 2001 Steve Huston <shuston@riverace.com> + + * IPv6 changes done by John Aughey and myself. To enable IPv6 + support for a build, put this in your config.h file: + #define ACE_HAS_IPV6 + If your build with IPv6 enabled must also run on systems where + the IPv6 support in the kernel is not actually turned on (for + example, Redhat Linux 7 by default), also add this to your + config.h file: + #define ACE_USES_IPV4_IPV6_MIGRATION + + * ace/ACE.cpp (format_hexdump): Add \n to last part of a dump line. + + * ace/INET_Addr.(h i cpp): If IPv6 is enabled, the inet_addr_ + member is now a union of sockaddr_in and sockaddr_in6. Which + one is legit is noted in ACE_Addr::type as well as the family + member of either of the union members. The host name lookup + functions can look up ipv6 as well as ipv4 names, and the + caller can force one or the other by using the address_family + argument to set(). + + * ace/OS.(h i): Removed ACE_OS::gethostbyname2; replaced it with + the more correctly-named and more flexible ACE_OS::getipnodebyname. + Also added ACE_OS::getipnodebyaddr. These are the IPv6-capable + functions analogous to gethostbyname and gethostbyaddr. + + * ace/SOCK.cpp (get_remote_addr, get_local_addr): Set up the + ACE_Addr's type properly to account for ipv4/6 possibilities. + + * ace/SOCK_Acceptor.(h cpp): Allow accepting on ipv4 and ipv6 sockets. + + * ace/SOCK_CODgram.h: + * ace/SOCK_Connector.(cpp h ): + * ace/SOCK_Dgram.(cpp h ): Change default protocol family from + PF_INET to vary and take advantage of IPv6 if available. + + * ace/Sock_Connect.(cpp h): Added ACE_Sock_Connect::ipv6_enabled() + method - it checks to see if the running kernel can do IPv6 + sockets or not. + + * ace/Sock_Connect.cpp (get_ip_interfaces): Removed a #if 0'd + block that had possible specializations for MSVC 4.2. It's + been a number of years, and it's obviously not needed. + + * ace/MEM_Addr.cpp (same_host): Don't try to compare binary + addresses directly... get ACE_INET_Addr objects, clear the port + numbers, and compare them. + + * ace/MEM_Connector.cpp (connect): Print error text with message. + + * ace/Asynch_Acceptor.cpp (open): For the new socket, use the + protocol family from the listen address, not PF_INET. + + * tests/INET_Addr_Test.cpp: New test. + + * tests/Makefile: Added INET_Addr_Test. + Mon Dec 3 10:54:34 2001 Carlos O'Ryan <coryan@uci.edu> * ace/OS.h: @@ -959,6 +1016,14 @@ Wed Oct 24 23:59:13 2001 Douglas C. Schmidt <schmidt@macarena.cs.wustl.edu> by the pointer. Thanks to Juan Jose Comellas <uanjo@comellas.org> for reporting this. +Wed Oct 31 16:45:07 2001 Ossama Othman <ossama@uci.edu> + + * ace/OS.h (llseek): + + Made ACE_OS::llseek() a static method, as it was originally + intended to be. Thanks to Doron Rajwan <doron@BANDWIZ.COM> for + pointing out the problem. + Tue Oct 30 22:53:57 2001 Ossama Othman <ossama@uci.edu> * ace/Svc_Conf_l.cpp: diff --git a/ace/Asynch_Acceptor.cpp b/ace/Asynch_Acceptor.cpp index 32155af11d8..c83faa29252 100644 --- a/ace/Asynch_Acceptor.cpp +++ b/ace/Asynch_Acceptor.cpp @@ -54,7 +54,7 @@ ACE_Asynch_Acceptor<HANDLER>::open (const ACE_INET_Addr &address, this->reissue_accept_ = reissue_accept; // Create the listener socket - this->listen_handle_ = ACE_OS::socket (PF_INET, SOCK_STREAM, 0); + this->listen_handle_ = ACE_OS::socket (address.get_type (), SOCK_STREAM, 0); if (this->listen_handle_ == ACE_INVALID_HANDLE) ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), diff --git a/ace/INET_Addr.cpp b/ace/INET_Addr.cpp index 3cf3137344a..7955ff918d1 100644 --- a/ace/INET_Addr.cpp +++ b/ace/INET_Addr.cpp @@ -22,11 +22,16 @@ ACE_INET_Addr::addr_to_string (ACE_TCHAR s[], { ACE_TRACE ("ACE_INET_Addr::addr_to_string"); + // XXX Can we (should we) include the scope id for IPv6 addresses? + size_t total_len = (ipaddr_format == 0 ? ACE_OS::strlen (this->get_host_name ()) : ACE_OS::strlen (this->get_host_addr ())) + ACE_OS::strlen ("65536") // Assume the max port number. + sizeof (':') +#if defined ACE_HAS_IPV6 + + ACE_OS::strlen ("[]") +#endif + sizeof ('\0'); // For trailing '\0'. if (size < total_len) @@ -34,7 +39,11 @@ ACE_INET_Addr::addr_to_string (ACE_TCHAR s[], else { ACE_OS::sprintf (s, +#if defined ACE_HAS_IPV6 + ACE_LIB_TEXT ("[%s]:%d"), +#else ACE_LIB_TEXT ("%s:%d"), +#endif ACE_TEXT_CHAR_TO_TCHAR (ipaddr_format == 0 ? this->get_host_name () : this->get_host_addr ()), @@ -51,9 +60,7 @@ ACE_INET_Addr::dump (void) const ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); ACE_TCHAR s[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16]; - ACE_OS::sprintf (s, ACE_LIB_TEXT ("%s:%d"), - this->get_host_addr (), - this->get_port_number ()); + this->addr_to_string(s, ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16); ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("%s"), s)); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } @@ -74,20 +81,22 @@ ACE_INET_Addr::operator == (const ACE_INET_Addr &sap) const { ACE_TRACE ("ACE_INET_Addr::operator =="); - return this->inet_addr_.sin_port == sap.inet_addr_.sin_port - && ACE_OS::memcmp ((void *) &this->inet_addr_.sin_addr, - (void *) &sap.inet_addr_.sin_addr, - sizeof (this->inet_addr_.sin_addr)) == 0; + if (this->get_type () != sap.get_type () || + this->get_size () != sap.get_size () ) + return 0; + + return (ACE_OS::memcmp (&this->inet_addr_, + &sap.inet_addr_, + this->get_size ()) == 0); } ACE_INET_Addr::ACE_INET_Addr (void) - : ACE_Addr (AF_INET, sizeof this->inet_addr_) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { // ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); (void) ACE_OS::memset ((void *) &this->inet_addr_, 0, sizeof this->inet_addr_); - this->inet_addr_.sin_family = AF_INET; } int @@ -95,19 +104,13 @@ ACE_INET_Addr::set (const ACE_INET_Addr &sa) { ACE_TRACE ("ACE_INET_Addr::set"); - this->ACE_Addr::base_set (sa.get_type (), - sa.get_size ()); - if (sa.get_type () == AF_ANY) // Ugh, this is really a base class, so don't copy it. - (void) ACE_OS::memset ((void *) &this->inet_addr_, - 0, - sizeof this->inet_addr_); + ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_)); else // It's ok to make the copy. - (void) ACE_OS::memcpy ((void *) &this->inet_addr_, - (void *) &sa.inet_addr_, - sizeof this->inet_addr_); + ACE_OS::memcpy (&this->inet_addr_, &sa.inet_addr_, sa.get_size ()); + return 0; } @@ -118,43 +121,39 @@ ACE_INET_Addr::string_to_addr (const char s[]) { ACE_TRACE ("ACE_INET_Addr::string_to_addr"); int result; - char *t; + char *ip_addr; // Need to make a duplicate since we'll be overwriting the string. - ACE_ALLOCATOR_RETURN (t, + ACE_ALLOCATOR_RETURN (ip_addr, ACE_OS::strdup (s), -1); - char *ip_addr = ACE_OS::strchr (t, ':'); + // We use strrchr because of IPv6 addresses. + char *port_p = ACE_OS::strrchr (ip_addr, ':'); - if (ip_addr == 0) // Assume it's a port number. + if (port_p == 0) // Assume it's a port number. { - if (ACE_OS::strspn (t, "1234567890") - == ACE_OS::strlen (t)) + if (ACE_OS::strspn (ip_addr, "1234567890") == ACE_OS::strlen (ip_addr)) { // port number - u_short port = (u_short) ACE_OS::atoi (t); - result = this->set (port, - ACE_UINT32 (INADDR_ANY)); + u_short port = (u_short) ACE_OS::atoi (ip_addr); + result = this->set (port, ACE_UINT32 (INADDR_ANY)); } else // port name - result = this->set (t, - ACE_UINT32 (INADDR_ANY)); + result = this->set (ip_addr, ACE_UINT32 (INADDR_ANY)); } else { - *ip_addr = '\0'; ++ip_addr; // skip over ':' + *port_p = '\0'; ++port_p; // skip over ':' - if (ACE_OS::strspn (ip_addr, "1234567890") == - ACE_OS::strlen (ip_addr)) + if (ACE_OS::strspn (port_p, "1234567890") == ACE_OS::strlen (port_p)) { - u_short port = - (u_short) ACE_OS::atoi (ip_addr); - result = this->set (port, t); + u_short port = (u_short) ACE_OS::atoi (port_p); + result = this->set (port, ip_addr); } else - result = this->set (ip_addr, t); + result = this->set (port_p, ip_addr); } - ACE_OS::free (ACE_MALLOC_T (t)); + ACE_OS::free (ACE_MALLOC_T (ip_addr)); return result; } @@ -166,17 +165,19 @@ ACE_INET_Addr::set (const char address[]) } ACE_INET_Addr::ACE_INET_Addr (const char address[]) - : ACE_Addr (AF_INET, sizeof this->inet_addr_) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_)); this->set (address); } #if defined (ACE_HAS_WCHAR) ACE_INET_Addr::ACE_INET_Addr (const wchar_t address[]) - : ACE_Addr (AF_INET, sizeof this->inet_addr_) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_)); this->set (address); } @@ -185,13 +186,13 @@ ACE_INET_Addr::ACE_INET_Addr (const wchar_t address[]) // Copy constructor. ACE_INET_Addr::ACE_INET_Addr (const ACE_INET_Addr &sa) - : ACE_Addr (AF_INET, sizeof this->inet_addr_) + : ACE_Addr (sa.get_type (), sa.get_size()) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); this->set (sa); } -// Initializes a ACE_INET_Addr from a PORT_NUMBER and an Internet +// Initializes a ACE_INET_Addr from a PORT_NUMBER and a 32 bit Internet // address. int @@ -200,43 +201,25 @@ ACE_INET_Addr::set (u_short port_number, int encode) { ACE_TRACE ("ACE_INET_Addr::set"); - this->ACE_Addr::base_set (AF_INET, sizeof this->inet_addr_); - (void) ACE_OS::memset ((void *) &this->inet_addr_, - 0, sizeof this->inet_addr_); - this->inet_addr_.sin_family = AF_INET; -#if defined (ACE_HAS_SIN_LEN) - this->inet_addr_.sin_len = sizeof this->inet_addr_; -#endif /* ACE_HAS_SIN_LEN */ - - if (encode) - { - inet_address = htonl (inet_address); - this->inet_addr_.sin_port = htons (port_number); - } - else - this->inet_addr_.sin_port = port_number; + this->set_address (ACE_reinterpret_cast (const char *, &inet_address), + sizeof inet_address, + encode); + this->set_port_number (port_number, encode); - (void) ACE_OS::memcpy ((void *) &this->inet_addr_.sin_addr, - (void *) &inet_address, - sizeof this->inet_addr_.sin_addr); return 0; } + // Initializes a ACE_INET_Addr from a PORT_NUMBER and the remote // HOST_NAME. int ACE_INET_Addr::set (u_short port_number, const char host_name[], - int encode) + int encode, + int address_family) { ACE_TRACE ("ACE_INET_Addr::set"); - ACE_UINT32 addr; - - this->ACE_Addr::base_set (AF_INET, sizeof this->inet_addr_); - (void) ACE_OS::memset ((void *) &this->inet_addr_, 0, sizeof - this->inet_addr_); - this->inet_addr_.sin_family = AF_INET; // Yow, someone gave us a NULL host_name! if (host_name == 0) @@ -244,23 +227,61 @@ ACE_INET_Addr::set (u_short port_number, errno = EINVAL; return -1; } - else if (ACE_OS::inet_aton (host_name, - (struct in_addr *) &addr) == 1) + + ACE_OS_String::memset ((void *) &this->inet_addr_, + 0, + sizeof this->inet_addr_); + +#if defined (ACE_HAS_IPV6) + struct addrinfo hints, *res, *res0; + int error; + ACE_OS_String::memset (&hints, 0, sizeof (hints)); + + hints.ai_family = address_family; + + error = getaddrinfo (host_name, 0, &hints, &res0); + if (error) + return -1; + + int ret = -1; + for (res = res0; res != 0; res = res->ai_next) + { + if (res->ai_family == AF_INET || res->ai_family == AF_INET6) + { + this->set_type (res->ai_family); + this->set_addr (res->ai_addr, res->ai_addrlen); + this->set_port_number (port_number, encode); + ret = 0; + break; + } + } + freeaddrinfo (res0); + return ret; + +#else /* ACE_HAS_IPV6 */ + + // IPv6 not supported... insure the family is set to IPv4 + address_family = PF_INET; + this->set_type (address_family); + this->inet_addr_.in4_.sin_family = address_family; + ACE_UINT32 addrv4; + if (ACE_OS::inet_aton (host_name, + (struct in_addr *) &addrv4) == 1) return this->set (port_number, - encode ? ntohl (addr) : addr, + encode ? ntohl (addrv4) : addrv4, encode); else { -#if defined (VXWORKS) || defined (CHORUS) +# if defined (VXWORKS) || defined (CHORUS) hostent *hp = ACE_OS::gethostbyname (host_name); -#else +# else hostent hentry; ACE_HOSTENT_DATA buf; int error; hostent *hp = ACE_OS::gethostbyname_r (host_name, &hentry, buf, &error); -#endif /* VXWORKS */ +# endif /* VXWORKS */ if (hp == 0) { @@ -269,16 +290,18 @@ ACE_INET_Addr::set (u_short port_number, } else { - (void) ACE_OS::memcpy ((void *) &addr, - hp->h_addr, - hp->h_length); + (void) ACE_OS_String::memcpy ((void *) &addrv4, + hp->h_addr, + hp->h_length); return this->set (port_number, - encode ? ntohl (addr) : addr, + encode ? ntohl (addrv4) : addrv4, encode); } } +#endif /* ACE_HAS_IPV6 */ } + // Initializes a ACE_INET_Addr from a <port_name> and the remote // <host_name>. @@ -304,12 +327,18 @@ ACE_INET_Addr::set (const char port_name[], buf); if (sp == 0) return -1; - else - return this->set (sp->s_port, host_name, 0); + + int address_family = PF_UNSPEC; +# if defined (ACE_HAS_IPV6) + if (ACE_OS_String::strcmp (protocol, ACE_LIB_TEXT ("tcp6")) == 0) + address_family = AF_INET6; +# endif /* ACE_HAS_IPV6 */ + + return this->set (sp->s_port, host_name, 0, address_family); #endif /* VXWORKS */ } -// Initializes a ACE_INET_Addr from a <port_name> and an Internet +// Initializes a ACE_INET_Addr from a <port_name> and a 32 bit Internet // address. int @@ -344,11 +373,16 @@ ACE_INET_Addr::set (const char port_name[], ACE_INET_Addr::ACE_INET_Addr (u_short port_number, - const char host_name[]) + const char host_name[], + int address_family) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_)); if (this->set (port_number, - host_name) == -1) + host_name, + 1, + address_family) == -1) #if defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) ACE_ERROR ((LM_ERROR, (char *)"ACE_INET_Addr::ACE_INET_Addr: %p\n", @@ -365,11 +399,16 @@ ACE_INET_Addr::ACE_INET_Addr (u_short port_number, #if defined (ACE_HAS_WCHAR) ACE_INET_Addr::ACE_INET_Addr (u_short port_number, - const wchar_t host_name[]) + const wchar_t host_name[], + int address_family) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_)); if (this->set (port_number, - host_name) == -1) + host_name, + 1, + address_family) == -1) #if defined (ACE_HAS_BROKEN_CONDITIONAL_STRING_CASTS) ACE_ERROR ((LM_ERROR, (char *)"ACE_INET_Addr::ACE_INET_Addr: %p\n", @@ -392,11 +431,24 @@ int ACE_INET_Addr::set (const sockaddr_in *addr, int len) { ACE_TRACE ("ACE_INET_Addr::set"); - this->ACE_Addr::base_set (AF_INET, len); - ACE_OS::memcpy ((void *) &this->inet_addr_, - (void *) addr, len); - this->inet_addr_.sin_family = AF_INET; - return 0; + + if (addr->sin_family == AF_INET) + { + ACE_OS::memcpy (&this->inet_addr_.in4_, addr, len); + this->base_set (AF_INET, len); + return 0; + } +#if defined (ACE_HAS_IPV6) + else if (addr->sin_family == AF_INET6) + { + ACE_OS::memcpy (&this->inet_addr_.in6_, addr, len); + this->base_set (AF_INET6, len); + return 0; + } +#endif /* ACE_HAS_IPV6 */ + + errno = EAFNOSUPPORT; + return -1; } // Set a pointer to the address. @@ -404,17 +456,32 @@ void ACE_INET_Addr::set_addr (void *addr, int len) { ACE_TRACE ("ACE_INET_Addr::set_addr"); + ACE_UNUSED_ARG (len); + + struct sockaddr_in *getfamily = ACE_static_cast (struct sockaddr_in*, addr); - this->ACE_Addr::base_set (AF_INET, len); - ACE_OS::memcpy ((void *) &this->inet_addr_, - (void *) addr, len); - this->inet_addr_.sin_family = AF_INET; + if (getfamily->sin_family == AF_INET) + { + this->set_address (ACE_reinterpret_cast (const char*, &getfamily->sin_addr), + sizeof (getfamily->sin_addr), + 0); + } +#if defined ACE_HAS_IPV6 + else if (getfamily->sin_family == AF_INET6) + { + struct sockaddr_in6 *in6 = ACE_static_cast (struct sockaddr_in6*, addr); + this->set_address (ACE_reinterpret_cast (const char*, &in6->sin6_addr), + sizeof (in6->sin6_addr), + 0); + } +#endif // ACE_HAS_IPV6 } // Creates a ACE_INET_Addr from a sockaddr_in structure. ACE_INET_Addr::ACE_INET_Addr (const sockaddr_in *addr, int len) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); this->set (addr, len); @@ -425,8 +492,10 @@ ACE_INET_Addr::ACE_INET_Addr (const sockaddr_in *addr, int len) ACE_INET_Addr::ACE_INET_Addr (u_short port_number, ACE_UINT32 inet_address) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_)); if (this->set (port_number, inet_address) == -1) ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), @@ -439,8 +508,10 @@ ACE_INET_Addr::ACE_INET_Addr (u_short port_number, ACE_INET_Addr::ACE_INET_Addr (const char port_name[], const char host_name[], const char protocol[]) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_)); if (this->set (port_name, host_name, protocol) == -1) @@ -452,8 +523,10 @@ ACE_INET_Addr::ACE_INET_Addr (const char port_name[], ACE_INET_Addr::ACE_INET_Addr (const wchar_t port_name[], const wchar_t host_name[], const wchar_t protocol[]) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_)); if (this->set (port_name, host_name, protocol) == -1) @@ -468,8 +541,10 @@ ACE_INET_Addr::ACE_INET_Addr (const wchar_t port_name[], ACE_INET_Addr::ACE_INET_Addr (const char port_name[], ACE_UINT32 inet_address, const char protocol[]) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_)); if (this->set (port_name, inet_address, protocol) == -1) @@ -481,8 +556,10 @@ ACE_INET_Addr::ACE_INET_Addr (const char port_name[], ACE_INET_Addr::ACE_INET_Addr (const wchar_t port_name[], ACE_UINT32 inet_address, const wchar_t protocol[]) + : ACE_Addr (this->determine_type(), sizeof (inet_addr_)) { ACE_TRACE ("ACE_INET_Addr::ACE_INET_Addr"); + ACE_OS::memset (&this->inet_addr_, 0, sizeof (this->inet_addr_)); if (this->set (port_name, inet_address, protocol) == -1) @@ -524,6 +601,7 @@ ACE_INET_Addr::get_host_name (char hostname[], } result = -1; } + return result; } @@ -574,7 +652,12 @@ ACE_INET_Addr::set_port_number (u_short port_number, if (encode) port_number = htons (port_number); - this->inet_addr_.sin_port = port_number; +#if defined (ACE_HAS_IPV6) + if (this->get_type () == AF_INET6) + this->inet_addr_.in6_.sin6_port = port_number; + else +#endif /* ACE_HAS_IPV6 */ + this->inet_addr_.in4_.sin_port = port_number; } // returns -2 when the hostname is truncated @@ -583,7 +666,17 @@ ACE_INET_Addr::get_host_name_i (char hostname[], size_t len) const { ACE_TRACE ("ACE_INET_Addr::get_host_name_i"); - if (this->inet_addr_.sin_addr.s_addr == INADDR_ANY) +#if defined (ACE_HAS_IPV6) + if ((this->get_type () == PF_INET6 && + 0 == ACE_OS_String::memcmp (&this->inet_addr_.in6_.sin6_addr, + &in6addr_any, + sizeof (this->inet_addr_.in6_.sin6_addr))) + || + (this->get_type () == PF_INET && + this->inet_addr_.in4_.sin_addr.s_addr == INADDR_ANY)) +#else + if (this->inet_addr_.in4_.sin_addr.s_addr == INADDR_ANY) +#endif /* ACE_HAS_IPV6 */ { if (ACE_OS::hostname (hostname, len) == -1) return -1; @@ -595,7 +688,7 @@ ACE_INET_Addr::get_host_name_i (char hostname[], size_t len) const #if defined (VXWORKS) ACE_UNUSED_ARG (len); int error = - ::hostGetByAddr ((int) this->inet_addr_.sin_addr.s_addr, + ::hostGetByAddr ((int) this->inet_addr_.in4_.sin_addr.s_addr, hostname); if (error == OK) return 0; @@ -605,32 +698,26 @@ ACE_INET_Addr::get_host_name_i (char hostname[], size_t len) const return -1; } #else -# if !defined(_UNICOS) - int a_len = sizeof this->inet_addr_.sin_addr.s_addr; -# else /* _UNICOS */ - int a_len = sizeof this->inet_addr_.sin_addr; -# endif /* ! _UNICOS */ int error = 0; -#if defined (CHORUS) || (defined (DIGITAL_UNIX) && defined (__GNUC__)) - hostent *hp = ACE_OS::gethostbyaddr ((char *) -&this->inet_addr_.sin_addr, - a_len, - this->addr_type_); +# if defined (CHORUS) || (defined (DIGITAL_UNIX) && defined (__GNUC__)) + hostent *hp = ACE_OS::gethostbyaddr ((char *)this->ip_addr_pointer (), + this->ip_addr_size (), + this->get_type ()); if (hp == 0) error = errno; // So that the errno gets propagated back; it is // loaded from error below. -#else +# else hostent hentry; ACE_HOSTENT_DATA buf; hostent *hp = - ACE_OS::gethostbyaddr_r ((char *)&this->inet_addr_.sin_addr, - a_len, - this->addr_type_, + ACE_OS::gethostbyaddr_r ((char *)this->ip_addr_pointer (), + this->ip_addr_size (), + this->get_type (), &hentry, buf, &error); -#endif /* CHORUS */ +# endif /* CHORUS */ if (hp == 0) { @@ -646,7 +733,7 @@ ACE_INET_Addr::get_host_name_i (char hostname[], size_t len) const // We know the length, so use memcpy if (len > 0) { - ACE_OS::memcpy(hostname,hp->h_name,len - 1); + ACE_OS::memcpy (hostname, hp->h_name, len - 1); hostname[len-1]= '\0'; } errno = ENOSPC; @@ -660,3 +747,189 @@ ACE_INET_Addr::get_host_name_i (char hostname[], size_t len) const #endif /* VXWORKS */ } } + +int ACE_INET_Addr::set_address (const char *ip_addr, + int len, + int encode /* = 1 */) +{ + ACE_TRACE ("ACE_INET_Addr::set_address"); + // This is really intended for IPv4. If the object is IPv4, or the type + // hasn't been set but it's a 4-byte address, go ahead. If this is an + // IPv6 object and <encode> is requested, refuse. + if (encode && len != 4) + { + errno = EAFNOSUPPORT; + return -1; + } + + if (len == 4) + { + ACE_UINT32 ip4 = *ACE_reinterpret_cast (const ACE_UINT32 *, ip_addr); + if (encode) + ip4 = ACE_HTONL (ip4); + + + if (this->get_type () == AF_INET) { + this->base_set (AF_INET, sizeof (this->inet_addr_.in4_)); + this->inet_addr_.in4_.sin_family = AF_INET; + this->set_size (sizeof (this->inet_addr_.in4_)); + ACE_OS_String::memcpy (&this->inet_addr_.in4_.sin_addr, + &ip4, + len); + } +#if defined (ACE_HAS_IPV6) + // If given an IPv4 address to copy to an IPv6 object, map it to + // an IPv4-mapped IPv6 address. + else + { + this->base_set (AF_INET6, sizeof (this->inet_addr_.in6_)); + this->inet_addr_.in6_.sin6_family = AF_INET6; + this->set_size (sizeof (this->inet_addr_.in6_)); + if (ip4 == INADDR_ANY) + { + in6_addr ip6 = in6addr_any; + ACE_OS_String::memcpy (&this->inet_addr_.in6_.sin6_addr, + &ip6, + sizeof (ip6)); + return 0; + } + if (ip4 == INADDR_LOOPBACK) + { + in6_addr ip6 = in6addr_loopback; + ACE_OS_String::memcpy (&this->inet_addr_.in6_.sin6_addr, + &ip6, + sizeof (ip6)); + return 0; + } + + // Build up a 128 bit address. An IPv4-mapped IPv6 address + // is defined as 0:0:0:0:0:ffff:IPv4_address. This is defined + // in RFC 1884 */ + struct { + ACE_UINT16 prefix[5]; + ACE_UINT16 ffff; + ACE_UINT32 addr; + } newaddress = { + { 0,0,0,0,0 }, + 0xffff, + ip4 + }; + + ACE_OS_String::memcpy (&this->inet_addr_.in6_.sin6_addr, + &newaddress, + sizeof (newaddress)); + } +#endif /* ACE_HAS_IPV6 */ + + return 0; + } /* end if (len == 4) */ +#if defined (ACE_HAS_IPV6) + else if (len == 16) + { + if (this->get_type () != PF_INET6) + { + errno = EAFNOSUPPORT; + return -1; + } + // We protect ourselves up above so IPv6 must be possible here. + this->base_set (AF_INET6, sizeof (this->inet_addr_.in6_)); + this->inet_addr_.in6_.sin6_family = AF_INET6; + ACE_OS_String::memcpy (&this->inet_addr_.in6_.sin6_addr, ip_addr, len); + + return 0; + } /* end len == 16 */ + else + { + /* unknown or unsupported address length */ + errno = EAFNOSUPPORT; + return -1; + } + +#endif /* ACE_HAS_IPV6 */ + + // Here with an unrecognized length. + errno = EAFNOSUPPORT; + return -1; + +} + + +const char * +ACE_INET_Addr::get_host_addr (char *dst, int size) const +{ +#if defined (ACE_HAS_IPV6) + if (this->get_type () == AF_INET6) + { + if (IN6_IS_ADDR_V4MAPPED (&this->inet_addr_.in6_.sin6_addr)) + { + ACE_UINT32 addr; + addr = this->get_ip_address(); + addr = ACE_HTONL (addr); + return ACE_OS::inet_ntop (AF_INET, &addr, dst, size); + } + + const char *ch = ACE_OS::inet_ntop (AF_INET6, + &this->inet_addr_.in6_.sin6_addr, + dst, + size); + return ch; + } +#endif /* ACE_HAS_IPV6 */ + +#if defined (VXWORKS) + // It would be nice to be able to encapsulate this into + // ACE_OS::inet_ntoa(), but that would lead to either inefficiencies + // on vxworks or lack of thread safety. + // + // So, we use the way that vxworks suggests. + ACE_INET_Addr *ncthis = ACE_const_cast (ACE_INET_Addr *, this); + inet_ntoa_b (this->inet_addr_.in4_.sin_addr, ncthis->buf_); + return &buf_[0]; +#else /* VXWORKS */ + char *ch = ACE_OS::inet_ntoa (this->inet_addr_.in4_.sin_addr); + ACE_OS::strncpy (dst, ch, size); + return ch; +#endif +} + +// Return the dotted Internet address. +const char * +ACE_INET_Addr::get_host_addr (void) const +{ + ACE_TRACE ("ACE_INET_Addr::get_host_addr"); +#if defined (ACE_HAS_IPV6) + static char buf[INET6_ADDRSTRLEN]; + return this->get_host_addr (buf, INET6_ADDRSTRLEN); +#else + return ACE_OS::inet_ntoa (this->inet_addr_.in4_.sin_addr); +#endif +} + +// Return the 4-byte IP address, converting it into host byte order. + +ACE_UINT32 +ACE_INET_Addr::get_ip_address (void) const +{ + ACE_TRACE ("ACE_INET_Addr::get_ip_address"); +#if defined (ACE_HAS_IPV6) + if (this->get_type () == AF_INET6) + { + if (IN6_IS_ADDR_V4MAPPED (&this->inet_addr_.in6_.sin6_addr) || + IN6_IS_ADDR_V4COMPAT (&this->inet_addr_.in6_.sin6_addr) ) + { + ACE_UINT32 addr; + // Return the last 32 bits of the address + char *thisaddrptr = (char*)this->ip_addr_pointer (); + thisaddrptr += 128/8 - 32/8; + ACE_OS_String::memcpy (&addr, thisaddrptr, sizeof (addr)); + return ACE_NTOHL (addr); + } + + ACE_ERROR ((LM_ERROR, + ACE_LIB_TEXT ("ACE_INET_Addr::get_ip_address: address is a IPv6 address not IPv4\n"))); + errno = EAFNOSUPPORT; + return 0; + } +#endif /* ACE_HAS_IPV6 */ + return ntohl (ACE_UINT32 (this->inet_addr_.in4_.sin_addr.s_addr)); +} diff --git a/ace/INET_Addr.h b/ace/INET_Addr.h index 9d362ec75d4..3d3b72a369f 100644 --- a/ace/INET_Addr.h +++ b/ace/INET_Addr.h @@ -36,6 +36,7 @@ class ACE_Export ACE_INET_Addr : public ACE_Addr { public: // = Initialization methods. + /// Default constructor. ACE_INET_Addr (void); @@ -48,8 +49,10 @@ public: /// Creates an <ACE_INET_Addr> from a <port_number> and the remote /// <host_name>. The port number is assumed to be in host byte order. /// To set a port already in network byte order, please @see set(). + /// Use address_family to select IPv6 (PF_INET6) vs. IPv4 (PF_INET). ACE_INET_Addr (u_short port_number, - const char host_name[]); + const char host_name[], + int address_family = AF_UNSPEC); /** * Initializes an <ACE_INET_Addr> from the <address>, which can be @@ -67,12 +70,12 @@ public: * network byte order, @see set(). */ ACE_INET_Addr (u_short port_number, - ACE_UINT32 ip_addr = INADDR_ANY); + ACE_UINT32 ip_addr = INADDR_ANY); /// Uses <getservbyname> to create an <ACE_INET_Addr> from a /// <port_name>, the remote <host_name>, and the <protocol>. ACE_INET_Addr (const char port_name[], - const char host_name[], + const char host_name[], const char protocol[] = "tcp"); /** @@ -81,21 +84,22 @@ public: * method assumes that <ip_addr> is in host byte order. */ ACE_INET_Addr (const char port_name[], - ACE_UINT32 ip_addr, + ACE_UINT32 ip_addr, const char protocol[] = "tcp"); #if defined (ACE_HAS_WCHAR) ACE_INET_Addr (u_short port_number, - const wchar_t host_name[]); + const wchar_t host_name[], + int address_family = AF_UNSPEC); ACE_EXPLICIT ACE_INET_Addr (const wchar_t address[]); ACE_INET_Addr (const wchar_t port_name[], - const wchar_t host_name[], + const wchar_t host_name[], const wchar_t protocol[] = ACE_TEXT_WIDE ("tcp")); ACE_INET_Addr (const wchar_t port_name[], - ACE_UINT32 ip_addr, + ACE_UINT32 ip_addr, const wchar_t protocol[] = ACE_TEXT_WIDE ("tcp")); #endif /* ACE_HAS_WCHAR */ @@ -114,10 +118,14 @@ public: * remote <host_name>. If <encode> is non-zero then <port_number> is * converted into network byte order, otherwise it is assumed to be * in network byte order already and are passed straight through. + * address_family can be used to select IPv4/IPv6 if the OS has + * IPv6 capability (ACE_HAS_IPV6 is defined). To specify IPv6, use + * the value AF_INET6. To specify IPv4, use AF_INET. */ int set (u_short port_number, - const char host_name[], - int encode = 1); + const char host_name[], + int encode = 1, + int address_family = AF_UNSPEC); /** * Initializes an <ACE_INET_Addr> from a @param port_number and an @@ -133,7 +141,7 @@ public: /// Uses <getservbyname> to initialize an <ACE_INET_Addr> from a /// <port_name>, the remote <host_name>, and the <protocol>. int set (const char port_name[], - const char host_name[], + const char host_name[], const char protocol[] = "tcp"); /** @@ -142,7 +150,7 @@ public: * <ip_addr> is already in network byte order. */ int set (const char port_name[], - ACE_UINT32 ip_addr, + ACE_UINT32 ip_addr, const char protocol[] = "tcp"); /** @@ -156,19 +164,20 @@ public: /// Creates an <ACE_INET_Addr> from a sockaddr_in structure. int set (const sockaddr_in *, - int len); + int len); #if defined (ACE_HAS_WCHAR) int set (u_short port_number, - const wchar_t host_name[], - int encode = 1); + const wchar_t host_name[], + int encode = 1, + int address_family = AF_UNSPEC); int set (const wchar_t port_name[], - const wchar_t host_name[], + const wchar_t host_name[], const wchar_t protocol[] = ACE_TEXT_WIDE ("tcp")); int set (const wchar_t port_name[], - ACE_UINT32 ip_addr, + ACE_UINT32 ip_addr, const wchar_t protocol[] = ACE_TEXT_WIDE ("tcp")); int set (const wchar_t addr[]); @@ -176,6 +185,7 @@ public: /// Return a pointer to the underlying network address. virtual void *get_addr (void) const; + int get_addr_size(void) const; /// Set a pointer to the address. virtual void set_addr (void *, int len); @@ -217,7 +227,18 @@ public: * already and are passed straight through. */ void set_port_number (u_short, - int encode = 1); + int encode = 1); + + /** + * Sets the address without affecting the port number. If + * <encode> is enabled then <ip_addr> is converted into network + * byte order, otherwise it is assumed to be in network byte order + * already and are passed straight through. The size of the address + * is specified in the <len> parameter. + */ + int set_address (const char *ip_addr, + int len, + int encode = 1); /// Return the port number, converting it into host byte-order. u_short get_port_number (void) const; @@ -246,6 +267,7 @@ public: /// Return the "dotted decimal" Internet address. const char *get_host_addr (void) const; + const char *get_host_addr (char *dst, int size) const; /// Return the 4-byte IP address, converting it into host byte /// order. @@ -279,8 +301,22 @@ private: /// Insure that @arg hostname is properly null-terminated. int get_host_name_i (char hostname[], size_t hostnamelen) const; + // Methods to gain access to the actual address of + // the underlying internet address structure. + void *ip_addr_pointer (void) const; + size_t ip_addr_size (void) const; + int determine_type (void) const; + /// Underlying representation. - sockaddr_in inet_addr_; + /// This union uses the knowledge that the two structures share the + /// first member, sa_family (as all sockaddr structures do). + union + { + sockaddr_in in4_; +#if defined (ACE_HAS_IPV6) + sockaddr_in6 in6_; +#endif /* ACE_HAS_IPV6 */ + } inet_addr_; #if defined (VXWORKS) char buf_[INET_ADDR_LEN]; diff --git a/ace/INET_Addr.i b/ace/INET_Addr.i index 2ec940e02c4..44e74f0f88f 100644 --- a/ace/INET_Addr.i +++ b/ace/INET_Addr.i @@ -9,13 +9,66 @@ ACE_INET_Addr::~ACE_INET_Addr (void) { } +ACE_INLINE int +ACE_INET_Addr::determine_type (void) const +{ +#if defined (ACE_HAS_IPV6) +# if defined (ACE_USES_IPV4_IPV6_MIGRATION) + return ACE_Sock_Connect::ipv6_enabled () ? AF_INET6 : AF_INET; +# else + return AF_INET6; +# endif /* ACE_USES_IPV4_IPV6_MIGRATION */ +#endif /* ACE_HAS_IPV6 */ + return AF_INET; +} + +ACE_INLINE void * +ACE_INET_Addr::ip_addr_pointer (void) const +{ +#if defined (ACE_HAS_IPV6) + if (this->get_type () == PF_INET) + return (void*)&this->inet_addr_.in4_.sin_addr; + else + return (void*)&this->inet_addr_.in6_.sin6_addr; +#else + return (void*)&this->inet_addr_.in4_.sin_addr; +#endif +} + +ACE_INLINE size_t +ACE_INET_Addr::ip_addr_size (void) const +{ +#if defined (ACE_HAS_IPV6) + if (this->get_type () == PF_INET) + return sizeof this->inet_addr_.in4_.sin_addr; + else + return sizeof this->inet_addr_.in6_.sin6_addr; +#else + // These _UNICOS changes were picked up from pre-IPv6 code in + // get_host_name_i... the IPv6 section above may need something + // similar, so keep an eye out for it. +# if !defined(_UNICOS) + return sizeof this->inet_addr_.in4_.sin_addr.s_addr; +# else /* _UNICOS */ + return sizeof this->inet_addr_.in4_.sin_addr; +# endif /* ! _UNICOS */ +#endif /* ACE_HAS_IPV6 */ +} + // Return the port number, converting it into host byte order... ACE_INLINE u_short ACE_INET_Addr::get_port_number (void) const { ACE_TRACE ("ACE_INET_Addr::get_port_number"); - return ntohs (this->inet_addr_.sin_port); +#if defined (ACE_HAS_IPV6) + if (this->get_type () == PF_INET) + return ntohs (this->inet_addr_.in4_.sin_port); + else + return ntohs (this->inet_addr_.in6_.sin6_port); +#else + return ntohs (this->inet_addr_.in4_.sin_port); +#endif /* ACE_HAS_IPV6 */ } // Return the address. @@ -24,41 +77,35 @@ ACE_INLINE void * ACE_INET_Addr::get_addr (void) const { ACE_TRACE ("ACE_INET_Addr::get_addr"); - return (void *) &this->inet_addr_; + return (void*)&this->inet_addr_; } -// Return the dotted Internet address. - -ACE_INLINE const char * -ACE_INET_Addr::get_host_addr (void) const +ACE_INLINE int +ACE_INET_Addr::get_addr_size (void) const { - ACE_TRACE ("ACE_INET_Addr::get_host_addr"); -#if defined (VXWORKS) - // It would be nice to be able to encapsulate this into - // ACE_OS::inet_ntoa(), but that would lead to either inefficiencies - // on vxworks or lack of thread safety. - // - // So, we use the way that vxworks suggests. - ACE_INET_Addr *ncthis = ACE_const_cast (ACE_INET_Addr *, this); - inet_ntoa_b (this->inet_addr_.sin_addr, ncthis->buf_); - return &buf_[0]; -#else /* VXWORKS */ - return ACE_OS::inet_ntoa (this->inet_addr_.sin_addr); -#endif /* VXWORKS */ + ACE_TRACE ("ACE_INET_Addr::get_addr_size"); +#if defined (ACE_HAS_IPV6) + if (this->get_type () == PF_INET) + return sizeof this->inet_addr_.in4_; + else + return sizeof this->inet_addr_.in6_; +#else + return sizeof this->inet_addr_.in4_; +#endif /* ACE_HAS_IPV6 */ } -// Return the 4-byte IP address, converting it into host byte order. - -ACE_INLINE ACE_UINT32 -ACE_INET_Addr::get_ip_address (void) const -{ - ACE_TRACE ("ACE_INET_Addr::get_ip_address"); - return ntohl (ACE_UINT32 (this->inet_addr_.sin_addr.s_addr)); -} -ACE_INLINE u_long +ACE_INLINE u_long ACE_INET_Addr::hash (void) const { +#if defined (ACE_HAS_IPV6) + if (this->get_type () == PF_INET6) + { + const unsigned int *addr = (const unsigned int*)this->ip_addr_pointer(); + return addr[0] + addr[1] + addr[2] + addr[3] + this->get_port_number(); + } + else +#endif /* ACE_HAS_IPV6 */ return this->get_ip_address () + this->get_port_number (); } @@ -71,27 +118,29 @@ ACE_INET_Addr::operator < (const ACE_INET_Addr &rhs) const } #if defined (ACE_HAS_WCHAR) -ACE_INLINE int -ACE_INET_Addr::set (u_short port_number, - const wchar_t host_name[], - int encode) +ACE_INLINE int +ACE_INET_Addr::set (u_short port_number, + const wchar_t host_name[], + int encode, + int address_family) { - return this->set (port_number, + return this->set (port_number, ACE_Wide_To_Ascii (host_name).char_rep (), - encode); + encode, + address_family); } -ACE_INLINE int +ACE_INLINE int ACE_INET_Addr::set (const wchar_t port_name[], - const wchar_t host_name[], + const wchar_t host_name[], const wchar_t protocol[]) { - return this->set (ACE_Wide_To_Ascii (port_name).char_rep (), + return this->set (ACE_Wide_To_Ascii (port_name).char_rep (), ACE_Wide_To_Ascii (host_name).char_rep (), ACE_Wide_To_Ascii (protocol).char_rep ()); } -ACE_INLINE int +ACE_INLINE int ACE_INET_Addr::set (const wchar_t port_name[], ACE_UINT32 ip_addr, const wchar_t protocol[]) @@ -101,7 +150,7 @@ ACE_INET_Addr::set (const wchar_t port_name[], ACE_Wide_To_Ascii (protocol).char_rep ()); } -ACE_INLINE int +ACE_INLINE int ACE_INET_Addr::set (const wchar_t addr[]) { return this->set (ACE_Wide_To_Ascii (addr).char_rep ()); diff --git a/ace/MEM_Addr.cpp b/ace/MEM_Addr.cpp index c51fdceca98..77363d66c4e 100644 --- a/ace/MEM_Addr.cpp +++ b/ace/MEM_Addr.cpp @@ -68,8 +68,14 @@ ACE_MEM_Addr::same_host (const ACE_INET_Addr &sap) { ACE_TRACE ("ACE_MEM_Addr::same_host"); - return this->external_.get_ip_address () == - sap.get_ip_address (); + // Rather than try to obtain and compare low-level binary + // data, get copies of both addresses, set the ports to 0 + // (don't care about them) then compare for equality. + ACE_INET_Addr me (this->external_); + ACE_INET_Addr you (sap); + me.set_port_number (0, 0); // No need to encode a 0 + you.set_port_number (0, 0); + return me == you; } int diff --git a/ace/MEM_Connector.cpp b/ace/MEM_Connector.cpp index 7bb45a1ba0c..617c479e978 100644 --- a/ace/MEM_Connector.cpp +++ b/ace/MEM_Connector.cpp @@ -84,9 +84,10 @@ ACE_MEM_Connector::connect (ACE_MEM_Stream &new_stream, this->address_.get_local_addr (), timeout, local_sap, reuse_addr, flags, perms, - PF_INET, protocol) == -1) + 0, protocol) == -1) ACE_ERROR_RETURN ((LM_DEBUG, - ACE_LIB_TEXT ("ACE_MEM_Connector::connect error connecting to socket\n")), + ACE_LIB_TEXT ("%p\n"), + ACE_LIB_TEXT ("ACE_MEM_Connector::connect")), -1); @@ -4311,6 +4311,21 @@ typedef fd_set ACE_FD_SET_TYPE; # define INET6_ADDRSTRLEN 46 # endif /* INET6_ADDRSTRLEN */ +#if defined (ACE_HAS_IPV6) + +# if defined (ACE_USES_IPV4_IPV6_MIGRATION) +# define ACE_ADDRESS_FAMILY_INET AF_UNSPEC +# define ACE_PROTOCOL_FAMILY_INET PF_UNSPEC +# else +# define ACE_ADDRESS_FAMILY_INET AF_INET6 +# define ACE_PROTOCOL_FAMILY_INET PF_INET6 +# endif /* ACE_USES_IPV4_IPV6_MIGRATION */ + +#else +# define ACE_ADDRESS_FAMILY_INET AF_INET +# define ACE_PROTOCOL_FAMILY_INET PF_INET +#endif + # if defined (ACE_LACKS_SIGSET) # if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) typedef pace_sigset_t sigset_t; @@ -6424,7 +6439,10 @@ public: int length, int type); static struct hostent *gethostbyname (const char *name); - static struct hostent *gethostbyname2 (const char *name, int type); + static struct hostent *getipnodebyname (const char *name, int family, + int flags = 0); + static struct hostent *getipnodebyaddr (const void *src, size_t len, + int family); static struct hostent *gethostbyaddr_r (const char *addr, int length, int type, @@ -6819,8 +6837,6 @@ public: # endif /* ACE_LACKS_NATIVE_STRPTIME */ #endif /* ACE_HAS_STRPTIME */ - - private: #if defined (ACE_LACKS_WRITEV) @@ -6915,7 +6931,6 @@ private: const ACE_Time_Value *timeout); static ACE_Time_Value gettimeofday_i (void); - }; /** @@ -2053,6 +2053,7 @@ ACE_OS::mutex_lock (ACE_mutex_t *m, if (result == -1 && errno == ETIMEDOUT) errno = ETIME; return result; + # elif defined (ACE_HAS_WTHREADS) // Note that we must convert between absolute time (which is passed // as a parameter) and relative time (which is what the system call @@ -5950,26 +5951,37 @@ ACE_OS::gethostbyname (const char *name) } ACE_INLINE struct hostent * -ACE_OS::gethostbyname2 (const char *name, int family) +ACE_OS::getipnodebyname (const char *name, int family, int flags) { - ACE_OS_TRACE ("ACE_OS::gethostbyname2"); + ACE_OS_TRACE ("ACE_OS::getipnodebyname"); # if defined (ACE_PSOS) ACE_UNUSED_ARG (name); ACE_UNUSED_ARG (family); + ACE_UNUSED_ARG (flags); ACE_NOTSUP_RETURN (0); -# elif defined (ACE_HAS_IP6) -# if defined (ACE_HAS_NONCONST_GETBY) +# elif defined (ACE_HAS_IPV6) +# if defined (__GLIBC__) + ACE_UNUSED_ARG (flags); +# if defined (ACE_HAS_NONCONST_GETBY) ACE_SOCKCALL_RETURN (::gethostbyname2 (ACE_const_cast (char *, name), family), - struct hostent *, - 0); -# else + struct hostent *, 0); +# else ACE_SOCKCALL_RETURN (::gethostbyname2 (name, family), - struct hostent *, - 0); -# endif /* ACE_HAS_NONCONST_GETBY */ + struct hostent *, 0); +# endif /* ACE_HAS_NONCONST_GETBY */ +# else + struct hostent *hptr; + int errnum; + if ((hptr = ::getipnodebyname (name, family, flags, &errnum)) == 0) + { + errno = errnum; + } + return hptr; +# endif /* __GLIBC__ */ # else // IPv4-only implementation + ACE_UNUSED_ARG (flags); if (family == AF_INET) return ACE_OS::gethostbyname (name); @@ -5977,6 +5989,37 @@ ACE_OS::gethostbyname2 (const char *name, int family) # endif /* ACE_PSOS */ } + +ACE_INLINE struct hostent * +ACE_OS::getipnodebyaddr (const void *src, size_t len, int family) +{ +#if defined (ACE_HAS_IPV6) +# if defined (__GLIBC__) + ACE_UNUSED_ARG (src); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (family); + ACE_NOTSUP_RETURN (0); +# else + struct hostent *hptr; + int errnum; + if ((hptr = ::getipnodebyaddr (src, len, family, &errnum)) == 0) + { + errno = errnum; + } + return hptr; +# endif /* whatever_doesnt_have_getipnodebyname */ +#else + // IPv4-only implementation + if (family == AF_INET) + return ACE_OS::gethostbyaddr (ACE_static_cast (const char *, src), + len, + family); + + ACE_NOTSUP_RETURN (0); +# endif /* ACE_PSOS */ +} + + ACE_INLINE struct hostent * ACE_OS::gethostbyaddr (const char *addr, int length, int type) { @@ -7274,7 +7317,7 @@ ACE_OS::inet_pton (int family, const char *strptr, void *addrptr) { ACE_OS_TRACE ("ACE_OS::inet_pton"); -#if defined (ACE_HAS_IP6) +#if defined (ACE_HAS_IPV6) ACE_OSCALL_RETURN (::inet_pton (family, strptr, addrptr), int, -1); #else if (family == AF_INET) @@ -7291,7 +7334,7 @@ ACE_OS::inet_pton (int family, const char *strptr, void *addrptr) } ACE_NOTSUP_RETURN(-1); -#endif /* ACE_HAS_IP6 */ +#endif /* ACE_HAS_IPV6 */ } ACE_INLINE const char * @@ -7299,7 +7342,7 @@ ACE_OS::inet_ntop (int family, const void *addrptr, char *strptr, size_t len) { ACE_OS_TRACE ("ACE_OS::inet_ntop"); -#if defined (ACE_HAS_IP6) +#if defined (ACE_HAS_IPV6) ACE_OSCALL_RETURN (::inet_ntop (family, addrptr, strptr, len), const char *, 0); #else const u_char *p = @@ -7327,7 +7370,7 @@ ACE_OS::inet_ntop (int family, const void *addrptr, char *strptr, size_t len) } ACE_NOTSUP_RETURN(0); -#endif /* ACE_HAS_IP6 */ +#endif /* ACE_HAS_IPV6 */ } ACE_INLINE int diff --git a/ace/SOCK.cpp b/ace/SOCK.cpp index cc970c0da67..333ff6c16b5 100644 --- a/ace/SOCK.cpp +++ b/ace/SOCK.cpp @@ -41,6 +41,7 @@ ACE_SOCK::get_remote_addr (ACE_Addr &sa) const return -1; sa.set_size (len); + sa.set_type (addr->sa_family); return 0; } @@ -58,6 +59,7 @@ ACE_SOCK::get_local_addr (ACE_Addr &sa) const &len) == -1) return -1; + sa.set_type (addr->sa_family); sa.set_size (len); return 0; } diff --git a/ace/SOCK_Acceptor.cpp b/ace/SOCK_Acceptor.cpp index 8477e4809ca..04ca6f42716 100644 --- a/ace/SOCK_Acceptor.cpp +++ b/ace/SOCK_Acceptor.cpp @@ -25,8 +25,8 @@ ACE_SOCK_Acceptor::ACE_SOCK_Acceptor (void) int ACE_SOCK_Acceptor::shared_accept_start (ACE_Time_Value *timeout, - int restart, - int &in_blocking_mode) const + int restart, + int &in_blocking_mode) const { ACE_TRACE ("ACE_SOCK_Acceptor::shared_accept_start"); @@ -36,20 +36,20 @@ ACE_SOCK_Acceptor::shared_accept_start (ACE_Time_Value *timeout, if (timeout != 0) { if (ACE::handle_timed_accept (handle, - timeout, - restart) == -1) - return -1; + timeout, + restart) == -1) + return -1; else - { - in_blocking_mode = ACE_BIT_DISABLED (ACE::get_flags (handle), - ACE_NONBLOCK); - // Set the handle into non-blocking mode if it's not already - // in it. - if (in_blocking_mode - && ACE::set_flags (handle, - ACE_NONBLOCK) == -1) - return -1; - } + { + in_blocking_mode = ACE_BIT_DISABLED (ACE::get_flags (handle), + ACE_NONBLOCK); + // Set the handle into non-blocking mode if it's not already + // in it. + if (in_blocking_mode + && ACE::set_flags (handle, + ACE_NONBLOCK) == -1) + return -1; + } } return 0; @@ -57,8 +57,8 @@ ACE_SOCK_Acceptor::shared_accept_start (ACE_Time_Value *timeout, int ACE_SOCK_Acceptor::shared_accept_finish (ACE_SOCK_Stream new_stream, - int in_blocking_mode, - int reset_new_handle) const + int in_blocking_mode, + int reset_new_handle) const { ACE_TRACE ("ACE_SOCK_Acceptor::shared_accept_finish ()"); @@ -75,9 +75,9 @@ ACE_SOCK_Acceptor::shared_accept_finish (ACE_SOCK_Stream new_stream, // Only disable ACE_NONBLOCK if we weren't in non-blocking mode // originally. ACE::clr_flags (this->get_handle (), - ACE_NONBLOCK); + ACE_NONBLOCK); ACE::clr_flags (new_handle, - ACE_NONBLOCK); + ACE_NONBLOCK); } #if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) @@ -96,7 +96,7 @@ ACE_SOCK_Acceptor::shared_accept_finish (ACE_SOCK_Stream new_stream, int ACE_SOCK_Acceptor::accept (ACE_SOCK_Stream &new_stream, ACE_Addr *remote_addr, - ACE_Time_Value *timeout, + ACE_Time_Value *timeout, int restart, int reset_new_handle) const { @@ -104,8 +104,8 @@ ACE_SOCK_Acceptor::accept (ACE_SOCK_Stream &new_stream, int in_blocking_mode = 0; if (this->shared_accept_start (timeout, - restart, - in_blocking_mode) == -1) + restart, + in_blocking_mode) == -1) return -1; else { @@ -116,38 +116,41 @@ ACE_SOCK_Acceptor::accept (ACE_SOCK_Stream &new_stream, int len = 0; if (remote_addr != 0) - { - len = remote_addr->get_size (); + { + len = remote_addr->get_size (); len_ptr = &len; - addr = (sockaddr *) remote_addr->get_addr (); - } + addr = (sockaddr *) remote_addr->get_addr (); + } do - new_stream.set_handle (ACE_OS::accept (this->get_handle (), - addr, - len_ptr)); + new_stream.set_handle (ACE_OS::accept (this->get_handle (), + addr, + len_ptr)); while (new_stream.get_handle () == ACE_INVALID_HANDLE - && restart != 0 - && errno == EINTR - && timeout == 0); + && restart != 0 + && errno == EINTR + && timeout == 0); - // Reset the size of the addr, which is only necessary for UNIX - // domain sockets. + // Reset the size of the addr, so the proper UNIX/IPv4/IPv6 family + // is known. if (new_stream.get_handle () != ACE_INVALID_HANDLE - && remote_addr != 0) - remote_addr->set_size (len); + && remote_addr != 0) + { + remote_addr->set_size (len); + remote_addr->set_type (addr->sa_family); + } } return this->shared_accept_finish (new_stream, - in_blocking_mode, - reset_new_handle); + in_blocking_mode, + reset_new_handle); } int ACE_SOCK_Acceptor::accept (ACE_SOCK_Stream &new_stream, - ACE_Accept_QoS_Params qos_params, + ACE_Accept_QoS_Params qos_params, ACE_Addr *remote_addr, - ACE_Time_Value *timeout, + ACE_Time_Value *timeout, int restart, int reset_new_handle) const { @@ -155,8 +158,8 @@ ACE_SOCK_Acceptor::accept (ACE_SOCK_Stream &new_stream, int in_blocking_mode = 0; if (this->shared_accept_start (timeout, - restart, - in_blocking_mode) == -1) + restart, + in_blocking_mode) == -1) return -1; else { @@ -167,32 +170,32 @@ ACE_SOCK_Acceptor::accept (ACE_SOCK_Stream &new_stream, sockaddr *addr = 0; if (remote_addr != 0) - { - len = remote_addr->get_size (); + { + len = remote_addr->get_size (); len_ptr = &len; - addr = (sockaddr *) remote_addr->get_addr (); - } + addr = (sockaddr *) remote_addr->get_addr (); + } do - new_stream.set_handle (ACE_OS::accept (this->get_handle (), - addr, - len_ptr, - qos_params)); + new_stream.set_handle (ACE_OS::accept (this->get_handle (), + addr, + len_ptr, + qos_params)); while (new_stream.get_handle () == ACE_INVALID_HANDLE - && restart != 0 - && errno == EINTR - && timeout == 0); + && restart != 0 + && errno == EINTR + && timeout == 0); // Reset the size of the addr, which is only necessary for UNIX // domain sockets. if (new_stream.get_handle () != ACE_INVALID_HANDLE - && remote_addr != 0) - remote_addr->set_size (len); + && remote_addr != 0) + remote_addr->set_size (len); } return this->shared_accept_finish (new_stream, - in_blocking_mode, - reset_new_handle); + in_blocking_mode, + reset_new_handle); } void @@ -209,6 +212,38 @@ ACE_SOCK_Acceptor::shared_open (const ACE_Addr &local_sap, ACE_TRACE ("ACE_SOCK_Acceptor::shared_open"); int error = 0; +#if defined (ACE_HAS_IPV6) + ACE_ASSERT (protocol_family == PF_INET || protocol_family == PF_INET6); + + if (protocol_family == PF_INET6) + { + sockaddr_in6 local_inet6_addr; + ACE_OS::memset (ACE_reinterpret_cast (void *, + &local_inet6_addr), + 0, + sizeof local_inet6_addr); + + if (local_sap == ACE_Addr::sap_any) + { + local_inet6_addr.sin6_family = AF_INET6; + local_inet6_addr.sin6_port = 0; + local_inet6_addr.sin6_addr = in6addr_any; + } + else + local_inet6_addr = *ACE_reinterpret_cast (sockaddr_in6 *, + local_sap.get_addr ()); + + // We probably don't need a bind_port written here. + // There are currently no supported OS's that define + // ACE_LACKS_WILDCARD_BIND. + if (ACE_OS::bind (this->get_handle (), + ACE_reinterpret_cast (sockaddr *, + &local_inet6_addr), + sizeof local_inet6_addr) == -1) + error = 1; + } + else +#endif if (protocol_family == PF_INET) { sockaddr_in local_inet_addr; @@ -220,15 +255,13 @@ ACE_SOCK_Acceptor::shared_open (const ACE_Addr &local_sap, if (local_sap == ACE_Addr::sap_any) { local_inet_addr.sin_port = 0; - local_inet_addr.sin_addr.s_addr = htonl (INADDR_ANY); } else local_inet_addr = *ACE_reinterpret_cast (sockaddr_in *, local_sap.get_addr ()); if (local_inet_addr.sin_port == 0) { - if (ACE::bind_port (this->get_handle (), - local_inet_addr.sin_addr.s_addr) == -1) + if (ACE::bind_port (this->get_handle ()) == -1) error = 1; } else if (ACE_OS::bind (this->get_handle (), @@ -238,7 +271,7 @@ ACE_SOCK_Acceptor::shared_open (const ACE_Addr &local_sap, error = 1; } else if (ACE_OS::bind (this->get_handle (), - (sockaddr *) local_sap.get_addr (), + (sockaddr *) local_sap.get_addr (), local_sap.get_size ()) == -1) error = 1; @@ -265,13 +298,16 @@ ACE_SOCK_Acceptor::open (const ACE_Addr &local_sap, { ACE_TRACE ("ACE_SOCK_Acceptor::open"); + if (protocol_family == PF_UNSPEC) + protocol_family = local_sap.get_type (); + if (ACE_SOCK::open (SOCK_STREAM, - protocol_family, - protocol, + protocol_family, + protocol, protocolinfo, g, flags, - reuse_addr) == -1) + reuse_addr) == -1) return -1; else return this->shared_open (local_sap, @@ -293,30 +329,41 @@ ACE_SOCK_Acceptor::ACE_SOCK_Acceptor (const ACE_Addr &local_sap, protocolinfo, g, flags, - reuse_addr, - protocol_family, - backlog, - protocol) == -1) + reuse_addr, + protocol_family, + backlog, + protocol) == -1) ACE_ERROR ((LM_ERROR, - ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("ACE_SOCK_Acceptor"))); + ACE_LIB_TEXT ("%p\n"), + ACE_LIB_TEXT ("ACE_SOCK_Acceptor"))); } // General purpose routine for performing server ACE_SOCK creation. int ACE_SOCK_Acceptor::open (const ACE_Addr &local_sap, - int reuse_addr, - int protocol_family, - int backlog, - int protocol) + int reuse_addr, + int protocol_family, + int backlog, + int protocol) { ACE_TRACE ("ACE_SOCK_Acceptor::open"); + if (local_sap != ACE_Addr::sap_any) + protocol_family = local_sap.get_type (); + else if (protocol_family == PF_UNSPEC) + { +#if defined (ACE_HAS_IPV6) + protocol_family = ACE_Sock_Connect::ipv6_enabled () ? PF_INET6 : PF_INET; +#else + protocol_family = PF_INET; +#endif /* ACE_HAS_IPV6 */ + } + if (ACE_SOCK::open (SOCK_STREAM, - protocol_family, - protocol, - reuse_addr) == -1) + protocol_family, + protocol, + reuse_addr) == -1) return -1; else return this->shared_open (local_sap, @@ -327,23 +374,23 @@ ACE_SOCK_Acceptor::open (const ACE_Addr &local_sap, // General purpose routine for performing server ACE_SOCK creation. ACE_SOCK_Acceptor::ACE_SOCK_Acceptor (const ACE_Addr &local_sap, - int reuse_addr, - int protocol_family, - int backlog, - int protocol) + int reuse_addr, + int protocol_family, + int backlog, + int protocol) { ACE_TRACE ("ACE_SOCK_Acceptor::ACE_SOCK_Acceptor"); if (this->open (local_sap, - reuse_addr, - protocol_family, - backlog, - protocol) == -1) + reuse_addr, + protocol_family, + backlog, + protocol) == -1) ACE_ERROR ((LM_ERROR, - ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("ACE_SOCK_Acceptor"))); + ACE_LIB_TEXT ("%p\n"), + ACE_LIB_TEXT ("ACE_SOCK_Acceptor"))); } -int +int ACE_SOCK_Acceptor::close (void) { return ACE_SOCK::close (); diff --git a/ace/SOCK_Acceptor.h b/ace/SOCK_Acceptor.h index 080692c35a8..b5bd8f8ff17 100644 --- a/ace/SOCK_Acceptor.h +++ b/ace/SOCK_Acceptor.h @@ -48,7 +48,7 @@ public: */ ACE_SOCK_Acceptor (const ACE_Addr &local_sap, int reuse_addr = 0, - int protocol_family = PF_INET, + int protocol_family = PF_UNSPEC, int backlog = ACE_DEFAULT_BACKLOG, int protocol = 0); @@ -59,7 +59,7 @@ public: ACE_SOCK_GROUP g, u_long flags, int reuse_addr, - int protocol_family, + int protocol_family = PF_UNSPEC, int backlog = ACE_DEFAULT_BACKLOG, int protocol = 0); @@ -72,7 +72,7 @@ public: */ int open (const ACE_Addr &local_sap, int reuse_addr = 0, - int protocol_family = PF_INET, + int protocol_family = PF_UNSPEC, int backlog = ACE_DEFAULT_BACKLOG, int protocol = 0); @@ -83,7 +83,7 @@ public: ACE_SOCK_GROUP g, u_long flags, int reuse_addr, - int protocol_family, + int protocol_family = PF_UNSPEC, int backlog = ACE_DEFAULT_BACKLOG, int protocol = 0); @@ -120,7 +120,7 @@ public: * and vice versa. */ int accept (ACE_SOCK_Stream &new_stream, - ACE_Accept_QoS_Params qos_params, + ACE_Accept_QoS_Params qos_params, ACE_Addr *remote_addr = 0, ACE_Time_Value *timeout = 0, int restart = 1, @@ -140,14 +140,14 @@ protected: /// Perform operations that must occur before <ACE_OS::accept> is /// called. int shared_accept_start (ACE_Time_Value *timeout, - int restart, - int &in_blocking_mode) const; + int restart, + int &in_blocking_mode) const; /// Perform operations that must occur after <ACE_OS::accept> is /// called. int shared_accept_finish (ACE_SOCK_Stream new_stream, - int in_blocking_mode, - int reset_new_handle) const; + int in_blocking_mode, + int reset_new_handle) const; /** * This method factors out the common <open> code and is called by diff --git a/ace/SOCK_CODgram.h b/ace/SOCK_CODgram.h index 18741c5a1d0..e275a420031 100644 --- a/ace/SOCK_CODgram.h +++ b/ace/SOCK_CODgram.h @@ -22,6 +22,7 @@ #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Addr.h" +#include "ace/INET_Addr.h" /** * @class ACE_SOCK_CODgram @@ -38,7 +39,7 @@ public: ACE_SOCK_CODgram (const ACE_Addr &remote_sap, const ACE_Addr &local_sap = ACE_Addr::sap_any, - int protocol_family = PF_INET, + int protocol_family = ACE_PROTOCOL_FAMILY_INET, int protocol = 0, int reuse_addr = 0); @@ -50,7 +51,7 @@ public: /// Initiate a connected dgram. int open (const ACE_Addr &remote_sap, const ACE_Addr &local_sap = ACE_Addr::sap_any, - int protocol_family = PF_INET, + int protocol_family = ACE_PROTOCOL_FAMILY_INET, int protocol = 0, int reuse_addr = 0); diff --git a/ace/SOCK_Connector.cpp b/ace/SOCK_Connector.cpp index 728e5d158df..1cba42f861e 100644 --- a/ace/SOCK_Connector.cpp +++ b/ace/SOCK_Connector.cpp @@ -148,6 +148,10 @@ ACE_SOCK_Connector::connect (ACE_SOCK_Stream &new_stream, int protocol) { ACE_TRACE ("ACE_SOCK_Connector::connect"); + + // @@ Should remove this arg when IPv6 is merged... + ACE_UNUSED_ARG (protocol_family); + protocol_family = remote_sap.get_type (); if (this->shared_open (new_stream, protocol_family, protocol, @@ -183,8 +187,13 @@ ACE_SOCK_Connector::connect (ACE_SOCK_Stream &new_stream, int protocol) { ACE_TRACE ("ACE_SOCK_Connector::connect"); + + // @@ Should remove this arg when IPv6 is merged... + ACE_UNUSED_ARG (protocol_family); + protocol_family = remote_sap.get_type (); + if (this->shared_open (new_stream, - protocol_family, + remote_sap.get_type (), protocol, protocolinfo, g, diff --git a/ace/SOCK_Connector.h b/ace/SOCK_Connector.h index 334f448c0ae..1236c53eb92 100644 --- a/ace/SOCK_Connector.h +++ b/ace/SOCK_Connector.h @@ -70,7 +70,7 @@ public: int reuse_addr = 0, int flags = 0, int perms = 0, - int protocol_family = PF_INET, + int protocol_family = ACE_PROTOCOL_FAMILY_INET, int protocol = 0); /** @@ -105,7 +105,7 @@ public: u_long flags = 0, int reuse_addr = 0, int perms = 0, - int protocol_family = PF_INET, + int protocol_family = ACE_PROTOCOL_FAMILY_INET, int protocol = 0); /** @@ -136,7 +136,7 @@ public: int reuse_addr = 0, int flags = 0, int perms = 0, - int protocol_family = PF_INET, + int protocol_family = ACE_PROTOCOL_FAMILY_INET, int protocol = 0); /** @@ -169,7 +169,7 @@ public: u_long flags = 0, int reuse_addr = 0, int perms = 0, - int protocol_family = PF_INET, + int protocol_family = ACE_PROTOCOL_FAMILY_INET, int protocol = 0); /// Default dtor. diff --git a/ace/SOCK_Dgram.cpp b/ace/SOCK_Dgram.cpp index b088d3de55f..741ad75f44e 100644 --- a/ace/SOCK_Dgram.cpp +++ b/ace/SOCK_Dgram.cpp @@ -152,6 +152,18 @@ ACE_SOCK_Dgram::open (const ACE_Addr &local, int reuse_addr) { ACE_TRACE ("ACE_SOCK_Dgram::open"); + + if (local != ACE_Addr::sap_any) + protocol_family = local.get_type (); + else if (protocol_family == PF_UNSPEC) + { +#if defined (ACE_HAS_IPV6) + protocol_family = ACE_Sock_Connect::ipv6_enabled () ? PF_INET6 : PF_INET; +#else + protocol_family = PF_INET; +#endif /* ACE_HAS_IPV6 */ + } + if (ACE_SOCK::open (SOCK_DGRAM, protocol_family, protocol, diff --git a/ace/SOCK_Dgram.h b/ace/SOCK_Dgram.h index 77b4f6dd386..e227f9387af 100644 --- a/ace/SOCK_Dgram.h +++ b/ace/SOCK_Dgram.h @@ -16,6 +16,7 @@ #include "ace/pre.h" #include "ace/SOCK.h" +#include "ace/INET_Addr.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once @@ -39,7 +40,7 @@ public: /// This is a BSD-style method (i.e., no QoS) for initiating a socket /// dgram that will accept datagrams at the <local> address. ACE_SOCK_Dgram (const ACE_Addr &local, - int protocol_family = PF_INET, + int protocol_family = ACE_PROTOCOL_FAMILY_INET, int protocol = 0, int reuse_addr = 0); @@ -59,7 +60,7 @@ public: /// This is a BSD-style method (i.e., no QoS) for initiating a socket /// dgram that will accept datagrams at the <local> address. int open (const ACE_Addr &local, - int protocol_family = PF_INET, + int protocol_family = ACE_PROTOCOL_FAMILY_INET, int protocol = 0, int reuse_addr = 0); diff --git a/ace/Sock_Connect.cpp b/ace/Sock_Connect.cpp index 3fdd2da98ad..ec52f6db9e3 100644 --- a/ace/Sock_Connect.cpp +++ b/ace/Sock_Connect.cpp @@ -15,6 +15,16 @@ extern "C" { } #endif /* VXWORKS */ +#if defined (ACE_HAS_IPV6) +# if defined (ACE_HAS_THREADS) +# include "ace/Synch.h" +# include "ace/Object_Manager.h" +# endif /* ACE_HAS_THREADS */ + +// Whether or not ipv6 is turned on in this box +int ACE_Sock_Connect::ipv6_enabled_ = -1; +#endif /* ACE_HAS_IPV6 */ + #if defined (ACE_LACKS_INLINE_FUNCTIONS) #include "ace/Sock_Connect.i" #endif /* ACE_LACKS_INLINE_FUNCTIONS */ @@ -210,25 +220,17 @@ get_windows_version() int ACE_Sock_Connect::bind_port (ACE_HANDLE handle, - ACE_UINT32 ip_addr) + ACE_UINT32 ip_addr) { ACE_TRACE ("ACE_Sock_Connect::bind_port"); - sockaddr_in sock_addr; - - ACE_OS::memset ((void *) &sock_addr, 0, sizeof sock_addr); - sock_addr.sin_family = AF_INET; -#if defined (ACE_HAS_SIN_LEN) - sock_addr.sin_len = sizeof sock_addr; -#endif /* ACE_HAS_SIN_LEN */ - sock_addr.sin_addr.s_addr = ip_addr; + ACE_INET_Addr addr ((u_short)0, ip_addr); #if !defined (ACE_LACKS_WILDCARD_BIND) // The OS kernel should select a free port for us. - sock_addr.sin_port = 0; return ACE_OS::bind (handle, - ACE_reinterpret_cast(sockaddr *, &sock_addr), - sizeof sock_addr); + (sockaddr*)addr.get_addr(), + addr.get_size()); #else static u_short upper_limit = ACE_MAX_DEFAULT_PORT; int round_trip = upper_limit; @@ -238,11 +240,11 @@ ACE_Sock_Connect::bind_port (ACE_HANDLE handle, for (;;) { - sock_addr.sin_port = htons (upper_limit); + addr.set((u_short)upper_limit,ip_addr); if (ACE_OS::bind (handle, - ACE_reinterpret_cast(sockaddr *, &sock_addr), - sizeof sock_addr) >= 0) + (sockaddr*)addr.get_addr() + addr.get_size()) >= 0) { #if defined (ACE_WIN32) upper_limit--; @@ -468,14 +470,6 @@ ACE_Sock_Connect::get_ip_interfaces (size_t &count, // Win32 can do this by a simple API call if MSVC 5 or later is the compiler. // Not sure if Borland supplies the needed header/lib, but it might. # if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) -#if 0 - // If this also needs to be predicated on MSVC 5 or later, add the - // following condition to the #if above. It tests ok at Riverace w/ 4.2, - // but this isn't a virgin install of 4.2 so there's a minimal risk that - // it may need work later. - defined (_MSC_VER) && (_MSC_VER >= 1100) -#endif /* 0 */ - int i, n_interfaces, status; INTERFACE_INFO info[64]; @@ -851,7 +845,7 @@ ACE_Sock_Connect::get_ip_interfaces (size_t &count, ACE_OS::close (handle); ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("%p\n"), - ACE_LIB_TEXT ("is_address_local:") + ACE_LIB_TEXT ("get_ip_interfaces:") ACE_LIB_TEXT ("ioctl - SIOCGIFCONF failed")), -1); } @@ -983,8 +977,7 @@ ACE_Sock_Connect::get_ip_interfaces (size_t &count, // list of ifreq structs. int -ACE_Sock_Connect::count_interfaces (ACE_HANDLE handle, - size_t &how_many) +ACE_Sock_Connect::count_interfaces (ACE_HANDLE handle, size_t &how_many) { #if defined (sparc) && defined (SIOCGIFNUM) int tmp_how_many; // For 64 bit Solaris @@ -1096,3 +1089,37 @@ ACE_Sock_Connect::get_handle (void) #endif /* sparc */ return handle; } + + +int +ACE_Sock_Connect::ipv6_enabled (void) +{ +#if defined (ACE_HAS_IPV6) + if (ACE_Sock_Connect::ipv6_enabled_ == -1) + { + // Perform Double-Checked Locking Optimization. + ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, + *ACE_Static_Object_Lock::instance (), 0)); + + if (ACE_Sock_Connect::ipv6_enabled_ == -1) + { + // Determine if the kernel has IPv6 support by attempting to + // create a PF_INET6 socket and see if it fails. + ACE_HANDLE s = ACE_OS::socket (PF_INET6, SOCK_DGRAM, 0); + if (s == ACE_INVALID_HANDLE) + { + ACE_Sock_Connect::ipv6_enabled_ = 0; + } + else + { + ACE_Sock_Connect::ipv6_enabled_ = 1; + ACE_OS::closesocket (s); + } + } + } + + return ACE_Sock_Connect::ipv6_enabled_; +#else + return 0; +#endif /* ACE_HAS_IPV6 */ +} diff --git a/ace/Sock_Connect.h b/ace/Sock_Connect.h index a0882a63f1c..c50b0540672 100644 --- a/ace/Sock_Connect.h +++ b/ace/Sock_Connect.h @@ -64,6 +64,21 @@ class ACE_Export ACE_Sock_Connect /// made. Caller must <close> the handle. static ACE_HANDLE get_handle (void); + /** + * Returns 1 if IPv6 is enabled on the current host; 0 if not. + * This is an execution-time check. If ACE has not been compiled + * with ACE_HAS_IPV6, it always returns 0. If ACE_HAS_IPV6 is + * enabled, this function tries to create a PF_INET6 socket, + * returning 1 if it succeeds, and 0 if it fails. Caches the result + * so it only gets checked once. + */ + static int ipv6_enabled (void); + +#if defined (ACE_HAS_IPV6) +private: + /// Does this box have ipv6 turned on? + static int ipv6_enabled_; +#endif /* ACE_HAS_IPV6 */ }; #if !defined (ACE_LACKS_INLINE_FUNCTIONS) diff --git a/tests/INET_Addr_Test.cpp b/tests/INET_Addr_Test.cpp new file mode 100644 index 00000000000..71bd4dfb584 --- /dev/null +++ b/tests/INET_Addr_Test.cpp @@ -0,0 +1,93 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// INET_Addr_Test.cpp +// +// = DESCRIPTION +// Performs several tests on the ACE_INET_Addr class. It creates several +// IPv4 and IPv6 addresses and checks that the address formed by the +// class is valid. +// +// = AUTHOR +// John Aughey (jha@aughey.com) +// +// ============================================================================ + +#include <stdio.h> +#include "ace/INET_Addr.h" + +int main(int argc, char *argv[]) +{ + ACE_UNUSED_ARG(argc); + ACE_UNUSED_ARG(argv); + + char *ipv4_addresses[] = { + "127.0.0.1", "138.38.180.251", "64.219.54.121", "192.0.0.1", "10.0.0.1", 0 + }; + + ACE_INET_Addr addr; + + for(int i=0; ipv4_addresses[i] != 0; i++) { + struct in_addr addrv4; + ACE_UINT32 addr32; + + ACE_OS::inet_pton(AF_INET,ipv4_addresses[i],(void*)&addrv4); + + memcpy((void*)&addr32,(void*)&addrv4,sizeof(addr32)); + + addr.set(80,ipv4_addresses[i]); + + /* Now check to make sure get_ip_address matches and get_host_addr + matches. */ + + if(addr.get_ip_address() != htonl(addr32)) { + printf("Error: Address %s failed get_ip_address() check\n",ipv4_addresses[i]); + printf("0x%x != 0x%x\n",addr.get_ip_address(), addr32); + } + if(0 != ACE_OS::strcmp(addr.get_host_addr(),ipv4_addresses[i])) { + printf("Error: Address %s failed get_host_addr() check\n",ipv4_addresses[i]); + printf("%s != %s\n",addr.get_host_addr(),ipv4_addresses[i]); + } + + // Clear out the address by setting it to 1 and check + addr.set((u_short)0,(ACE_UINT32)1,1); + if(addr.get_ip_address() != 1) { + printf("Error: failed to set address to 1\n"); + } + + // Now set the address using a 32 bit number and check that we get + // the right string out of get_host_addr(). + addr.set(80,addr32,0); // addr32 is already in network byte order + if(0 != ACE_OS::strcmp(addr.get_host_addr(),ipv4_addresses[i])) { + printf("Error: Address %s failed second get_host_addr() check\n",ipv4_addresses[i]); + printf("%s != %s\n",addr.get_host_addr(),ipv4_addresses[i]); + } + } + +#if defined (ACE_HAS_IPV6) + if(ACE_Sock_Connect::ipv6_enabled()) { + char *ipv6_addresses[] = { + "1080::8:800:200c:417a", // unicast address + "ff01::101", // multicast address + "::1", // loopback address + "::", // unspecified addresses + 0 + }; + for(int i=0; ipv6_addresses[i] != 0; i++) { + ACE_INET_Addr addr(80,ipv6_addresses[i]); + + if(0 != ACE_OS::strcmp(addr.get_host_addr(),ipv6_addresses[i])) { + printf("IPv6 get_host_addr failed: %s != %s\n",addr.get_host_addr(),ipv6_addresses[i]); + } + } + } + +#endif + + return 0; +} diff --git a/tests/Makefile b/tests/Makefile index 2a5e39dfb56..265db0cd830 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -40,6 +40,7 @@ BIN = Aio_Platform_Test \ OrdMultiSet_Test \ Hash_Map_Manager_Test \ Hash_Map_Bucket_Iterator_Test \ + INET_Addr_Test \ IOStream_Test \ Lazy_Map_Manager_Test \ Log_Msg_Test \ |