diff options
author | Justin R. Wilson <wilsonj@objectcomputing.com> | 2019-02-21 09:22:09 -0600 |
---|---|---|
committer | Justin R. Wilson <wilsonj@objectcomputing.com> | 2019-02-22 09:48:09 -0600 |
commit | fa2ecd983d5a4f844b9ee419bcd73edc23d1408c (patch) | |
tree | 6f2a41f3735521a4920b6c4a580076e0d0c8aa70 /ACE | |
parent | b584d571ee82182fb39a572f24fd8083e50eb0ec (diff) | |
download | ATCD-fa2ecd983d5a4f844b9ee419bcd73edc23d1408c.tar.gz |
Provide option for local address for SOCK_Dgram recvmsg
Diffstat (limited to 'ACE')
-rw-r--r-- | ACE/ace/OS_NS_sys_socket.h | 14 | ||||
-rw-r--r-- | ACE/ace/SOCK_Dgram.cpp | 64 | ||||
-rw-r--r-- | ACE/ace/SOCK_Dgram.h | 12 | ||||
-rw-r--r-- | ACE/tests/SOCK_Dgram_Test.cpp | 76 |
4 files changed, 155 insertions, 11 deletions
diff --git a/ACE/ace/OS_NS_sys_socket.h b/ACE/ace/OS_NS_sys_socket.h index aa814443362..1f972a9f24d 100644 --- a/ACE/ace/OS_NS_sys_socket.h +++ b/ACE/ace/OS_NS_sys_socket.h @@ -58,6 +58,20 @@ #define ACE_SHUTDOWN_BOTH 2 #endif /* SD_BOTH */ +#if defined (IP_RECVDSTADDR) +#define ACE_RECVPKTINFO IP_RECVDSTADDR +#elif defined (IP_PKTINFO) +#define ACE_RECVPKTINFO IP_PKTINFO +#endif + +#if defined (ACE_HAS_IPV6) +#if defined (IPV6_PKTINFO) +#define ACE_RECVPKTINFO6 IPV6_PKTINFO +#elif defined (IPV6_RECVPKTINFO) +#define ACE_RECVPKTINFO6 IPV6_RECVPKTINFO +#endif +#endif + ACE_BEGIN_VERSIONED_NAMESPACE_DECL class ACE_Accept_QoS_Params; diff --git a/ACE/ace/SOCK_Dgram.cpp b/ACE/ace/SOCK_Dgram.cpp index 710ac47f7ef..754e2c3898f 100644 --- a/ACE/ace/SOCK_Dgram.cpp +++ b/ACE/ace/SOCK_Dgram.cpp @@ -308,11 +308,26 @@ ssize_t ACE_SOCK_Dgram::recv (iovec iov[], int n, ACE_Addr &addr, - int flags) const + int flags, + ACE_INET_Addr *to_addr) const { ACE_TRACE ("ACE_SOCK_Dgram::recv"); msghdr recv_msg; +#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG) + union control_buffer { + cmsghdr control_msg_header; +#if defined (IP_RECVDSTADDR) + u_char padding[CMSG_SPACE(sizeof (struct in_addr))]; +#elif defined (IP_PKTINFO) + u_char padding[CMSG_SPACE(sizeof (struct in_pktinfo))]; +#endif +#if defined (ACE_HAS_IPV6) + u_char padding6[CMSG_SPACE(sizeof (struct in6_pktinfo))]; +#endif + } cbuf; +#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */ + recv_msg.msg_iov = (iovec *) iov; recv_msg.msg_iovlen = n; #if defined (ACE_HAS_SOCKADDR_MSG_NAME) @@ -323,8 +338,8 @@ ACE_SOCK_Dgram::recv (iovec iov[], recv_msg.msg_namelen = addr.get_size (); #if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG) - recv_msg.msg_control = 0 ; - recv_msg.msg_controllen = 0 ; + recv_msg.msg_control = to_addr ? &cbuf : 0; + recv_msg.msg_controllen = to_addr ? sizeof (cbuf) : 0; #elif !defined ACE_LACKS_SENDMSG recv_msg.msg_accrights = 0; recv_msg.msg_accrightslen = 0; @@ -335,6 +350,49 @@ ACE_SOCK_Dgram::recv (iovec iov[], flags); addr.set_size (recv_msg.msg_namelen); addr.set_type (((sockaddr_in *) addr.get_addr())->sin_family); + +#if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG) + if (to_addr) { + this->get_local_addr (*to_addr); + if (to_addr->get_type() == AF_INET) { +#if defined (IP_RECVDSTADDR) || defined (IP_PKTINFO) + for (cmsghdr *ptr = CMSG_FIRSTHDR (&recv_msg); ptr != 0; ptr = CMSG_NXTHDR (&recv_msg, ptr)) { +#if defined (IP_RECVDSTADDR) + if (ptr->cmsg_level == IPPROTO_IP && + ptr->cmsg_type == IP_RECVDSTADDR) { + to_addr->set_address ((const char *)(CMSG_DATA (ptr)), + sizeof (struct in_addr), + 0); + break; + } +#else + if (ptr->cmsg_level == IPPROTO_IP && + ptr->cmsg_type == IP_PKTINFO) { + to_addr->set_address ((const char *)&(((struct in_pktinfo *)(CMSG_DATA (ptr)))->ipi_addr), + sizeof (struct in_addr), + 0); + break; + } +#endif + } +#endif + } +#if defined (ACE_HAS_IPV6) && defined (IPV6_PKTINFO) + else if (to_addr->get_type() == AF_INET6) { + for (cmsghdr *ptr = CMSG_FIRSTHDR (&recv_msg); ptr != 0; ptr = CMSG_NXTHDR (&recv_msg, ptr)) { + if (ptr->cmsg_level == IPPROTO_IPV6 && ptr->cmsg_type == IPV6_PKTINFO) { + to_addr->set_address ((const char *)&(((struct in6_pktinfo *)(CMSG_DATA (ptr)))->ipi6_addr), + sizeof (struct in6_addr), + 0); + + break; + } + } + } +#endif + } +#endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */ + return status; } diff --git a/ACE/ace/SOCK_Dgram.h b/ACE/ace/SOCK_Dgram.h index 92705f2aa56..ff567997592 100644 --- a/ACE/ace/SOCK_Dgram.h +++ b/ACE/ace/SOCK_Dgram.h @@ -15,6 +15,9 @@ #include "ace/SOCK.h" #include "ace/INET_Addr.h" +// Included so users have access to ACE_RECVPKTINFO and ACE_RECVPKTINFO6 . +#include "ace/OS_NS_sys_socket.h" + #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ @@ -120,11 +123,16 @@ public: int flags = 0) const; /// Recv an <iovec> of size @a n to the datagram socket (uses - /// <recvmsg(3)>). + /// <recvmsg(3)>). The IP destination address will be placed in @a + /// *to_addr if it is not null and set_option has been called with + /// 1) level IPPROTO_IP, option ACE_RECVPKTINFO, and value 1 for + /// IPV4 addresses or 2) IPPROTO_IPV6, option ACE_RECVPKTINFO6, and + /// value 1 for IPV6 addresses. ssize_t recv (iovec iov[], int n, ACE_Addr &addr, - int flags = 0) const; + int flags = 0, + ACE_INET_Addr *to_addr = 0) const; /** * Wait up to @a timeout amount of time to receive a datagram into diff --git a/ACE/tests/SOCK_Dgram_Test.cpp b/ACE/tests/SOCK_Dgram_Test.cpp index d5620a69fc7..14ee0af7eae 100644 --- a/ACE/tests/SOCK_Dgram_Test.cpp +++ b/ACE/tests/SOCK_Dgram_Test.cpp @@ -64,21 +64,81 @@ client (void *arg) ACE_TEXT("(%P|%t) protocol %d, %p\n"), server_addr.get_type (), ACE_TEXT ("SOCK_Dgram open"))); + return 0; } - else if (cli_dgram.send (TEST_DATA, sizeof (TEST_DATA), server_addr) == -1) + + { + if (remote_addr->get_type () == AF_INET) { +#if defined (ACE_RECVPKTINFO) + int sockopt = 1; + if (cli_dgram.set_option(IPPROTO_IP, ACE_RECVPKTINFO, &sockopt, sizeof sockopt) == -1) { + ACE_ERROR((LM_ERROR, + ACE_TEXT("(%P|%t) setsockopt failed\n"))); + return 0; + } else { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT("(%P|%t) setsockopt succeeded\n"))); + } +#endif + } +#if defined (ACE_HAS_IPV6) + else { +#if defined (ACE_RECVPKTINFO6) + int sockopt = 1; + if (cli_dgram.set_option(IPPROTO_IPV6, ACE_RECVPKTINFO6, &sockopt, sizeof sockopt) == -1) { + ACE_ERROR((LM_ERROR, + ACE_TEXT("(%P|%t) setsockopt failed\n"))); + return; + } else { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT("(%P|%t) setsockopt succeeded\n"))); + } +#endif + } +#endif + } + + if (cli_dgram.send (TEST_DATA, sizeof (TEST_DATA), server_addr) == -1) { ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) UDP send to %s %p\n"), hostname_string, ACE_TEXT ("failed"))); + return 0; } - else + { - ssize_t rcv_cnt = cli_dgram.recv (buf, - sizeof (buf), + ACE_INET_Addr local_addr; + cli_dgram.get_local_addr(local_addr); + + if (local_addr.get_type () == AF_INET) + { + local_addr.set (local_addr.get_port_number (), + ACE_LOCALHOST, + 1, + local_addr.get_type ()); + } +#if defined (ACE_HAS_IPV6) + else + { + local_addr.set (local_addr.get_port_number(), + ACE_IPV6_LOCALHOST, + 1, + local_addr.get_type ()); + } +#endif /* ACE_HAS_IPV6 */ + + ACE_INET_Addr to_addr = local_addr; + + iovec iov[1]; + iov[0].iov_base = buf; + iov[0].iov_len = 20; + + ssize_t rcv_cnt = cli_dgram.recv (iov, + 1, peer_addr, 0, - &timeout); + &to_addr); if (rcv_cnt == -1) { if (errno == ETIME) @@ -97,7 +157,7 @@ client (void *arg) } else { - // recv() ok, check data and 'from' address + // recv() ok, check data, 'from', and 'to' address size_t rcv_siz = static_cast<size_t> (rcv_cnt); if (rcv_siz != sizeof (TEST_DATA)) { @@ -125,6 +185,10 @@ client (void *arg) ACE_TEXT ("(%P|%t) recv addr size %d; should be %d\n"), peer_addr.get_size (), server_addr.get_size ())); + if (local_addr != to_addr) { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) local addr is not equal to server addr\n"))); + } } } |