The branch, master has been updated via 096c9a7 tests: Add more tests for socket options. via e7f7bec swrap: Support more socket options in getsockopt(). via c9b06b3 echo_srv: Add support for IP_SENDSRCADDR. via 27be91d swrap: Call swrap_msghdr_filter_cmsghdr in swrap_sendmsg_before(). via 4849b2e swrap: Add swrap_msghdr_filter_cmsg_pktinfo(). via 69f22c9 swrap: Add swrap_sendmsg_filter_cmsg_socket(). via 63c59be swrap: Add swrap_sendmsg_copy_cmsg(). via c9332d4 swrap: Add swrap_sendmsg_filter_cmsghdr(). via 3c55e35 echo_srv: Implement support for IP_RECVDSTADDR on BSD. via 29f24e5 swrap: Implement support for IP_RECVDSTADDR on BSD. via 75271e6 echo_srv: Fix building on OpenIndiana. via 13ea22c swrap: Check if the in_pktinfo structure is available. via f81b6e8 swrap: Silence a warning on OpenIndiana. via d977b0e tests: Fix assert_sockaddr_equal() file and line output. via f60415a cmake: Add some warnings were we should error out. via 54d74cb swrap: Properly cache the handle also in LIBC_SO case. from b9404d4 cmake: Fix a typo in socket_wrapper-config.cmake.in.
http://gitweb.samba.org/?p=socket_wrapper.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 096c9a7545ab5a406859a67374ca8a1c9d046f28 Author: Andreas Schneider <a...@samba.org> Date: Thu May 22 11:32:22 2014 +0200 tests: Add more tests for socket options. Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit e7f7bec0b56acd7b9744af53f7d96a53abd46ad3 Author: Andreas Schneider <a...@samba.org> Date: Thu May 22 11:18:08 2014 +0200 swrap: Support more socket options in getsockopt(). Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit c9b06b39df767539e47da8b6ce2208a5463a5314 Author: Andreas Schneider <a...@samba.org> Date: Fri May 23 14:36:23 2014 +0200 echo_srv: Add support for IP_SENDSRCADDR. Pair-Programmed-With: Michael Adam <ob...@samba.org> Signed-off-by: Andreas Schneider <a...@samba.org> Signed-off-by: Michael Adam <ob...@samba.org> commit 27be91da8fbb56826c361abd67ebb1e081540bfe Author: Andreas Schneider <a...@samba.org> Date: Fri May 23 14:35:59 2014 +0200 swrap: Call swrap_msghdr_filter_cmsghdr in swrap_sendmsg_before(). Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit 4849b2ebbfca6176e685ac9c6c933aad8470295f Author: Andreas Schneider <a...@samba.org> Date: Fri May 23 14:35:34 2014 +0200 swrap: Add swrap_msghdr_filter_cmsg_pktinfo(). Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit 69f22c94b4ad061263c40c8c271a86f444cee72d Author: Andreas Schneider <a...@samba.org> Date: Fri May 23 15:44:23 2014 +0200 swrap: Add swrap_sendmsg_filter_cmsg_socket(). Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit 63c59be9ace8282ed19b15fa9d66c7448c1bdd97 Author: Andreas Schneider <a...@samba.org> Date: Fri May 23 15:48:33 2014 +0200 swrap: Add swrap_sendmsg_copy_cmsg(). Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit c9332d48d55925c585641bbd7069f3a4c774e3c1 Author: Andreas Schneider <a...@samba.org> Date: Fri May 23 15:42:14 2014 +0200 swrap: Add swrap_sendmsg_filter_cmsghdr(). Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit 3c55e35cad90ef3c1126b390cf53b860c99fdd6e Author: Andreas Schneider <a...@samba.org> Date: Mon May 26 11:07:45 2014 +0200 echo_srv: Implement support for IP_RECVDSTADDR on BSD. Pair-Programmed-With: Michael Adam <ob...@samba.org> Signed-off-by: Andreas Schneider <a...@samba.org> Signed-off-by: Michael Adam <ob...@samba.org> commit 29f24e5cc059ed37117126838045f85b494fc288 Author: Andreas Schneider <a...@samba.org> Date: Mon May 26 11:00:09 2014 +0200 swrap: Implement support for IP_RECVDSTADDR on BSD. Pair-Programmed-With: Michael Adam <ob...@samba.org> Signed-off-by: Andreas Schneider <a...@samba.org> Signed-off-by: Michael Adam <ob...@samba.org> commit 75271e62121ba207076add1378d716adcf3ee47f Author: Andreas Schneider <a...@samba.org> Date: Fri May 23 09:26:13 2014 +0200 echo_srv: Fix building on OpenIndiana. Solaris doesn't have support for auxillary messages. Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit 13ea22cdaac3b5855232f1f59d910b628847ffe2 Author: Andreas Schneider <a...@samba.org> Date: Fri May 23 10:01:21 2014 +0200 swrap: Check if the in_pktinfo structure is available. Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit f81b6e84d57a6d40dce96b49cf18d924ab282872 Author: Andreas Schneider <a...@samba.org> Date: Fri May 23 09:20:31 2014 +0200 swrap: Silence a warning on OpenIndiana. Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit d977b0ee9570757cb15014c18787d366956d7901 Author: Andreas Schneider <a...@samba.org> Date: Wed May 21 14:52:21 2014 +0200 tests: Fix assert_sockaddr_equal() file and line output. Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit f60415a3ae411454551adc494e65fff7412e270e Author: Andreas Schneider <a...@samba.org> Date: Fri May 23 08:50:47 2014 +0200 cmake: Add some warnings were we should error out. Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit 54d74cb22eb17107bdc8c36c24c43a1f2d16914e Author: Pino Toscano <toscano.p...@tiscali.it> Date: Thu May 8 16:26:43 2014 +0200 swrap: Properly cache the handle also in LIBC_SO case. Small regression introduced by me in commit 0fa56909442c3cfea6a697681ea0e89ba5a0aa0f. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10572 Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> ----------------------------------------------------------------------- Summary of changes: ConfigureChecks.cmake | 1 + cmake/Modules/DefineCompilerFlags.cmake | 6 + config.h.cmake | 1 + src/socket_wrapper.c | 231 ++++++++++++++++++++++++++++- tests/echo_srv.c | 102 +++++++++++-- tests/test_echo_tcp_get_peer_sock_name.c | 3 +- tests/test_echo_tcp_socket_options.c | 147 +++++++++++++++++++ 7 files changed, 466 insertions(+), 25 deletions(-) Changeset truncated at 500 lines: diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 2d4c409..3a31f50 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -82,6 +82,7 @@ endif (UNIX) set(SWRAP_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "socket_wrapper required system libraries") # STRUCTS +check_struct_has_member("struct in_pktinfo" ipi_addr "sys/types.h;sys/socket.h;netinet/in.h" HAVE_STRUCT_IN_PKTINFO) set(CMAKE_REQUIRED_FLAGS -D_GNU_SOURCE) check_struct_has_member("struct in6_pktinfo" ipi6_addr "sys/types.h;sys/socket.h;netinet/in.h" HAVE_STRUCT_IN6_PKTINFO) set(CMAKE_REQUIRED_FLAGS) diff --git a/cmake/Modules/DefineCompilerFlags.cmake b/cmake/Modules/DefineCompilerFlags.cmake index e522a6a..e6fab88 100644 --- a/cmake/Modules/DefineCompilerFlags.cmake +++ b/cmake/Modules/DefineCompilerFlags.cmake @@ -11,10 +11,14 @@ if (UNIX AND NOT WIN32) # add -Wconversion ? set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=pointer-arith -Werror=declaration-after-statement") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration") + # with -fPIC check_c_compiler_flag("-fPIC" WITH_FPIC) if (WITH_FPIC) @@ -33,6 +37,8 @@ if (UNIX AND NOT WIN32) if (WITH_FORTIFY_SOURCE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-D_FORTIFY_SOURCE=2") endif (WITH_FORTIFY_SOURCE) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=uninitialized") endif() endif() endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)") diff --git a/config.h.cmake b/config.h.cmake index 57a2f12..02c016e 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -22,6 +22,7 @@ /**************************** STRUCTS ****************************/ +#cmakedefine HAVE_STRUCT_IN_PKTINFO 1 #cmakedefine HAVE_STRUCT_IN6_PKTINFO 1 /************************ STRUCT MEMBERS *************************/ diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index 01a498f..19ac184 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -125,6 +125,18 @@ enum swrap_dbglvl_e { # endif /* IPV6_RECVPKTINFO */ #endif /* IPV6_PKTINFO */ +/* + * On BSD IP_PKTINFO has a different name because during + * the time when they implemented it, there was no RFC. + * The name for IPv6 is the same as on Linux. + */ +#ifndef IP_PKTINFO +# ifdef IP_RECVDSTADDR +# define IP_PKTINFO IP_RECVDSTADDR +# endif +#endif + + #define SWRAP_DLIST_ADD(list,item) do { \ if (!(list)) { \ (item)->prev = NULL; \ @@ -434,6 +446,8 @@ static void *swrap_load_lib_handle(enum swrap_lib lib) #ifdef LIBC_SO if (handle == NULL) { handle = dlopen(LIBC_SO, flags); + + swrap.libc_handle = handle; } #endif if (handle == NULL) { @@ -2830,6 +2844,12 @@ int getsockname(int s, struct sockaddr *name, socklen_t *addrlen) * GETSOCKOPT ***************************************************************************/ +#ifndef SO_PROTOCOL +# ifdef SO_PROTOTYPE /* The Solaris name */ +# define SO_PROTOCOL SO_PROTOTYPE +# endif /* SO_PROTOTYPE */ +#endif /* SO_PROTOCOL */ + static int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) { @@ -2844,11 +2864,46 @@ static int swrap_getsockopt(int s, int level, int optname, } if (level == SOL_SOCKET) { - return libc_getsockopt(s, - level, - optname, - optval, - optlen); + switch (optname) { +#ifdef SO_DOMAIN + case SO_DOMAIN: + if (optval == NULL || optlen == NULL || + *optlen < (socklen_t)sizeof(int)) { + errno = EINVAL; + return -1; + } + + *optlen = sizeof(int); + *(int *)optval = si->family; + return 0; +#endif /* SO_DOMAIN */ + case SO_PROTOCOL: + if (optval == NULL || optlen == NULL || + *optlen < (socklen_t)sizeof(int)) { + errno = EINVAL; + return -1; + } + + *optlen = sizeof(int); + *(int *)optval = si->protocol; + return 0; + case SO_TYPE: + if (optval == NULL || optlen == NULL || + *optlen < (socklen_t)sizeof(int)) { + errno = EINVAL; + return -1; + } + + *optlen = sizeof(int); + *(int *)optval = si->type; + return 0; + default: + return libc_getsockopt(s, + level, + optname, + optval, + optlen); + } } errno = ENOPROTOOPT; @@ -2981,6 +3036,15 @@ int ioctl(int s, unsigned long int r, ...) *****************/ #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL + +#ifndef CMSG_ALIGN +# ifdef _ALIGN /* BSD */ +#define CMSG_ALIGN _ALIGN +# else +#error NO_CMSG_ALIGN +# endif /* _ALIGN */ +#endif /* CMSG_ALIGN */ + /** * @brief Add a cmsghdr to a msghdr. * @@ -3051,10 +3115,15 @@ static int swrap_msghdr_add_pktinfo(struct socket_info *si, { /* Add packet info */ switch (si->pktinfo) { -#ifdef IP_PKTINFO +#if defined(IP_PKTINFO) +/* && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR)) */ case AF_INET: { struct sockaddr_in *sin; +#if defined(HAVE_STRUCT_IN_PKTINFO) struct in_pktinfo pkt; +#elif defined(IP_RECVDSTADDR) + struct in_addr pkt; +#endif if (si->bindname_len == sizeof(struct sockaddr_in)) { sin = (struct sockaddr_in*)si->bindname; @@ -3067,8 +3136,12 @@ static int swrap_msghdr_add_pktinfo(struct socket_info *si, ZERO_STRUCT(pkt); +#if defined(HAVE_STRUCT_IN_PKTINFO) pkt.ipi_ifindex = socket_wrapper_default_iface(); pkt.ipi_addr.s_addr = sin->sin_addr.s_addr; +#elif defined(IP_RECVDSTADDR) + pkt = sin->sin_addr; +#endif swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO, &pkt, sizeof(pkt)); @@ -3121,6 +3194,117 @@ static int swrap_msghdr_add_socket_info(struct socket_info *si, return rc; } + +static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg, + uint8_t *cm_data, + size_t *cm_data_space); +static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg, + uint8_t *cm_data, + size_t *cm_data_space); + +static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg, + uint8_t *cm_data, + size_t *cm_data_space) { + struct cmsghdr *cmsg; + int rc = -1; + + /* Nothing to do */ + if (msg->msg_controllen == 0 || msg->msg_control == NULL) { + return 0; + } + + for (cmsg = CMSG_FIRSTHDR(msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(msg, cmsg)) { + switch (cmsg->cmsg_level) { + case IPPROTO_IP: + rc = swrap_sendmsg_filter_cmsg_socket(cmsg, + cm_data, + cm_data_space); + break; + default: + rc = swrap_sendmsg_copy_cmsg(cmsg, + cm_data, + cm_data_space); + break; + } + } + + return rc; +} + +static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg, + uint8_t *cm_data, + size_t *cm_data_space) +{ + size_t cmspace; + uint8_t *p; + + cmspace = + (*cm_data_space) + + CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))); + + p = realloc(cm_data, cmspace); + if (p == NULL) { + return -1; + } + cm_data = p; + + p = cm_data + (*cm_data_space); + *cm_data_space = cmspace; + + memcpy(p, cmsg, cmsg->cmsg_len); + + return 0; +} + +static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg, + uint8_t *cm_data, + size_t *cm_data_space); + + +static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg, + uint8_t *cm_data, + size_t *cm_data_space) +{ + int rc = -1; + + switch(cmsg->cmsg_type) { +#ifdef IP_PKTINFO + case IP_PKTINFO: + rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg, + cm_data, + cm_data_space); + break; +#endif +#ifdef IPV6_PKTINFO + case IPV6_PKTINFO: + rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg, + cm_data, + cm_data_space); + break; +#endif + default: + break; + } + + return rc; +} + +static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg, + uint8_t *cm_data, + size_t *cm_data_space) +{ + (void)cmsg; /* unused */ + (void)cm_data; /* unused */ + (void)cm_data_space; /* unused */ + + /* + * Passing a IP pktinfo to a unix socket might be rejected by the + * Kernel, at least on FreeBSD. So skip this cmsg. + */ + return 0; +} #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */ static ssize_t swrap_sendmsg_before(int fd, @@ -3243,6 +3427,28 @@ static ssize_t swrap_sendmsg_before(int fd, return -1; } +#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL + if (msg->msg_controllen > 0 && msg->msg_control != NULL) { + uint8_t *cmbuf = NULL; + size_t cmlen = 0; + + ret = swrap_sendmsg_filter_cmsghdr(msg, cmbuf, &cmlen); + if (ret < 0) { + free(cmbuf); + return -1; + } + + if (cmlen == 0) { + msg->msg_controllen = 0; + msg->msg_control = NULL; + } else if (cmlen < msg->msg_controllen) { + memcpy(msg->msg_control, cmbuf, cmlen); + msg->msg_controllen = cmlen; + } + free(cmbuf); + } +#endif + return 0; } @@ -3875,8 +4081,10 @@ static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags) struct socket_info *si; struct msghdr msg; struct iovec tmp; +#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL size_t msg_ctrllen_filled; size_t msg_ctrllen_left; +#endif ssize_t ret; int rc; @@ -3988,8 +4196,15 @@ static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags) msg.msg_iov = omsg->msg_iov; /* scatter/gather array */ msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */ #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL - msg.msg_control = omsg->msg_control; /* ancillary data, see below */ - msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */ + if (msg.msg_controllen > 0 && msg.msg_control != NULL) { + /* omsg is a const so use a local buffer for modifications */ + uint8_t cmbuf[omsg->msg_controllen]; + + memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen); + + msg.msg_control = cmbuf; /* ancillary data, see below */ + msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */ + } msg.msg_flags = omsg->msg_flags; /* flags on received message */ #endif diff --git a/tests/echo_srv.c b/tests/echo_srv.c index 33f2ebd..88d8170 100644 --- a/tests/echo_srv.c +++ b/tests/echo_srv.c @@ -55,14 +55,24 @@ struct echo_srv_opts { const char *pidfile; }; +#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL + +#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) || defined(IPV6_PKTINFO) union pktinfo { #ifdef HAVE_STRUCT_IN6_PKTINFO struct in6_pktinfo pkt6; #endif +#ifdef HAVE_STRUCT_IN_PKTINFO struct in_pktinfo pkt4; +#elif defined(IP_RECVDSTADDR) + struct in_addr pkt4; +#endif char c; }; +#define HAVE_UNION_PKTINFO 1 +#endif /* IP_PKTINFO || IP_RECVDSTADDR || IPV6_PKTINFO */ + static const char *echo_server_address(int family) { switch (family) { @@ -90,6 +100,7 @@ static const char *echo_server_address(int family) return NULL; } +#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */ static void _assert_return_code(int rc, int err, @@ -216,12 +227,24 @@ static void set_sock_pktinfo(int sock, int family) switch(family) { case AF_INET: proto = IPPROTO_IP; +#ifdef IP_PKTINFO option = IP_PKTINFO; +#elif IP_RECVDSTADDR + option = IP_RECVDSTADDR; +#else + return; +#endif /* IP_PKTINFO */ break; +#ifdef HAVE_IPV6 +#ifdef IPV6_RECVPKTINFO case AF_INET6: proto = IPPROTO_IPV6; option = IPV6_RECVPKTINFO; break; +#endif /* IPV6_RECVPKTINFO */ +#endif /* HAVE_IPV6 */ + default: + return; } rc = setsockopt(sock, proto, option, &sockopt, sizeof(sockopt)); @@ -541,11 +564,15 @@ static ssize_t echo_udp_recv_from_to(int sock, { struct msghdr rmsg; struct iovec riov; -#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL + ssize_t ret; + +#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(HAVE_UNION_PKTINFO) size_t cmlen = CMSG_LEN(sizeof(union pktinfo)); char cmsg[cmlen]; -#endif - ssize_t ret; +#else + (void)to; /* unused */ + (void)tolen; /* unused */ +#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */ riov.iov_base = buf; riov.iov_len = buflen; @@ -558,7 +585,7 @@ static ssize_t echo_udp_recv_from_to(int sock, rmsg.msg_iov = &riov; rmsg.msg_iovlen = 1; -#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL +#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(HAVE_UNION_PKTINFO) memset(cmsg, 0, cmlen); rmsg.msg_control = cmsg; @@ -571,6 +598,7 @@ static ssize_t echo_udp_recv_from_to(int sock, } *fromlen = rmsg.msg_namelen; +#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(HAVE_UNION_PKTINFO) if (rmsg.msg_controllen > 0) { struct cmsghdr *cmsgptr; @@ -578,11 +606,12 @@ static ssize_t echo_udp_recv_from_to(int sock, while (cmsgptr != NULL) { const char *p; +#if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO) if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO) { char ip[INET_ADDRSTRLEN] = { 0 }; - struct in_pktinfo *pkt; struct sockaddr_in *sinp = (struct sockaddr_in *)to; + struct in_pktinfo *pkt; pkt = (struct in_pktinfo *)CMSG_DATA(cmsgptr); @@ -601,7 +630,33 @@ static ssize_t echo_udp_recv_from_to(int sock, abort(); } } -#ifdef IPV6_PKTINFO +#endif /* IP_PKTINFO */ +#ifdef IP_RECVDSTADDR + if (cmsgptr->cmsg_level == IPPROTO_IP && + cmsgptr->cmsg_type == IP_RECVDSTADDR) { + char ip[INET_ADDRSTRLEN] = { 0 }; + struct sockaddr_in *sinp = (struct sockaddr_in *)to; + struct in_addr *addr; + + addr = (struct in_addr *)CMSG_DATA(cmsgptr); + + sinp->sin_family = AF_INET; + sinp->sin_addr = *addr; -- Socket Wrapper Repository