diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2019-05-17 16:16:29 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2019-05-17 16:16:29 +0000 |
commit | 9a2457d7cedef53d2890c38a7cd12af3c2c22c78 (patch) | |
tree | 7f74e9b2f1f37cfee6427ba5161206dd70062d82 | |
parent | e26b1a755a66bf868a00003ca29498e1a3d150a0 (diff) | |
download | strace-9a2457d7cedef53d2890c38a7cd12af3c2c22c78.tar.gz |
tests: check decoding of SO_TIMESTAMP*_NEW control messages
* configure.ac (AC_CHECK_TYPES): Check for struct __kernel_timespec
and struct __kernel_sock_timeval.
* tests/msg_control.c [HAVE_STRUCT___KERNEL_SOCK_TIMEVAL ||
HAVE_STRUCT___KERNEL_TIMESPEC]: Include <linux/time_types.h>.
(test_scm_timestamp): Rename to test_scm_timestamp_old.
(test_scm_timestampns): Rename to test_scm_timestampns_old.
(test_scm_timestamping): Rename to test_scm_timestamping_old.
[HAVE_STRUCT___KERNEL_SOCK_TIMEVAL] (test_scm_timestamp_new): New
function.
[HAVE_STRUCT___KERNEL_TIMESPEC] (test_scm_timestampns_new,
test_scm_timestamping_new): New functions.
(test_sol_socket): Use them.
* tests/sockopt-timestamp.c [HAVE_STRUCT___KERNEL_SOCK_TIMEVAL ||
HAVE_STRUCT___KERNEL_TIMESPEC]: Include <linux/time_types.h>.
Include "xlat/sock_options.h" in XLAT_MACROS_ONLY mode.
(print_timestampns_old): Define unconditionally.
[HAVE_STRUCT___KERNEL_SOCK_TIMEVAL] (print_timestamp_new): New function.
[HAVE_STRUCT___KERNEL_TIMESPEC] (print_timestampns_new): Likewise.
(main): Test SO_TIMESTAMPNS_OLD unconditionally.
[HAVE_STRUCT___KERNEL_SOCK_TIMEVAL]: Test SO_TIMESTAMP_NEW.
[HAVE_STRUCT___KERNEL_TIMESPEC]: Test SO_TIMESTAMPNS_NEW.
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | tests/msg_control.c | 180 | ||||
-rw-r--r-- | tests/sockopt-timestamp.c | 59 |
3 files changed, 226 insertions, 16 deletions
diff --git a/configure.ac b/configure.ac index 86d3626b2..e7df4fe60 100644 --- a/configure.ac +++ b/configure.ac @@ -283,6 +283,9 @@ AC_CHECK_TYPES([struct mmsghdr],,, [#include <sys/socket.h>]) AC_CHECK_TYPES([__kernel_long_t, __kernel_ulong_t],,, [#include <asm/posix_types.h>]) +AC_CHECK_TYPES([struct __kernel_timespec, struct __kernel_sock_timeval],,, +[#include <linux/time_types.h>]) + AC_CHECK_TYPES([struct stat64, struct __old_kernel_stat],,, [#include <sys/types.h> #include <asm/stat.h>]) diff --git a/tests/msg_control.c b/tests/msg_control.c index 84d6ccff4..4b277ec35 100644 --- a/tests/msg_control.c +++ b/tests/msg_control.c @@ -20,6 +20,11 @@ #include <netinet/in.h> #include <arpa/inet.h> +#if defined HAVE_STRUCT___KERNEL_SOCK_TIMEVAL \ + || defined HAVE_STRUCT___KERNEL_TIMESPEC +# include <linux/time_types.h> +#endif + #include "xlat.h" #define XLAT_MACROS_ONLY #include "xlat/sock_options.h" @@ -210,7 +215,7 @@ test_scm_rights3(struct msghdr *const mh, void *const page, const size_t nfds) } static void -test_scm_timestamp(struct msghdr *const mh, void *const page) +test_scm_timestamp_old(struct msghdr *const mh, void *const page) { size_t len = CMSG_SPACE(sizeof(struct timeval)); struct cmsghdr *cmsg = get_cmsghdr(page, len); @@ -255,7 +260,7 @@ test_scm_timestamp(struct msghdr *const mh, void *const page) } static void -test_scm_timestampns(struct msghdr *const mh, void *const page) +test_scm_timestampns_old(struct msghdr *const mh, void *const page) { size_t len = CMSG_SPACE(sizeof(struct timespec)); struct cmsghdr *cmsg = get_cmsghdr(page, len); @@ -301,7 +306,7 @@ test_scm_timestampns(struct msghdr *const mh, void *const page) } static void -test_scm_timestamping(struct msghdr *const mh, void *const page) +test_scm_timestamping_old(struct msghdr *const mh, void *const page) { size_t len = CMSG_SPACE(3 * sizeof(struct timespec)); struct cmsghdr *cmsg = get_cmsghdr(page, len); @@ -355,6 +360,162 @@ test_scm_timestamping(struct msghdr *const mh, void *const page) (unsigned long) len, rc, errno2name()); } +#ifdef HAVE_STRUCT___KERNEL_SOCK_TIMEVAL +static void +test_scm_timestamp_new(struct msghdr *const mh, void *const page) +{ + size_t len = CMSG_SPACE(sizeof(struct __kernel_sock_timeval)); + struct cmsghdr *cmsg = get_cmsghdr(page, len); + + cmsg->cmsg_len = CMSG_LEN(sizeof(struct __kernel_sock_timeval)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMP_NEW; + struct __kernel_sock_timeval *tv = + (struct __kernel_sock_timeval *) CMSG_DATA(cmsg); + tv->tv_sec = 0xdefaceddeadbeef; + tv->tv_usec = 0xdec0dedcafef00d; + + mh->msg_control = cmsg; + mh->msg_controllen = len; + + int rc = sendmsg(-1, mh, 0); + printf("sendmsg(-1, {msg_name=NULL, msg_namelen=0, msg_iov=NULL" + ", msg_iovlen=0, msg_control=[{cmsg_len=%u" + ", cmsg_level=SOL_SOCKET, cmsg_type=SO_TIMESTAMP_NEW" + ", cmsg_data={tv_sec=%lld, tv_usec=%llu}}]" + ", msg_controllen=%lu, msg_flags=0}, 0) = %s\n", + (unsigned) cmsg->cmsg_len, + (long long) tv->tv_sec, zero_extend_signed_to_ull(tv->tv_usec), + (unsigned long) len, sprintrc(rc)); + + len = CMSG_SPACE(sizeof(struct __kernel_sock_timeval) - sizeof(long)); + cmsg = get_cmsghdr(page, len); + + cmsg->cmsg_len = + CMSG_LEN(sizeof(struct __kernel_sock_timeval) - sizeof(long)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMP_NEW; + + mh->msg_control = cmsg; + mh->msg_controllen = len; + + rc = sendmsg(-1, mh, 0); + printf("sendmsg(-1, {msg_name=NULL, msg_namelen=0, msg_iov=NULL" + ", msg_iovlen=0, msg_control=[{cmsg_len=%u" + ", cmsg_level=SOL_SOCKET, cmsg_type=SO_TIMESTAMP_NEW, cmsg_data=?}]" + ", msg_controllen=%lu, msg_flags=0}, 0) = %s\n", + (unsigned) cmsg->cmsg_len, + (unsigned long) len, sprintrc(rc)); +} +#endif /* HAVE_STRUCT___KERNEL_SOCK_TIMEVAL */ + +#ifdef HAVE_STRUCT___KERNEL_TIMESPEC +static void +test_scm_timestampns_new(struct msghdr *const mh, void *const page) +{ + size_t len = CMSG_SPACE(sizeof(struct __kernel_timespec)); + struct cmsghdr *cmsg = get_cmsghdr(page, len); + + cmsg->cmsg_len = CMSG_LEN(sizeof(struct __kernel_timespec)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMPNS_NEW; + struct __kernel_timespec *ts = + (struct __kernel_timespec *) CMSG_DATA(cmsg); + ts->tv_sec = 0xdefaceddeadbeef; + ts->tv_nsec = 0xdec0dedcafef00d; + + mh->msg_control = cmsg; + mh->msg_controllen = len; + + int rc = sendmsg(-1, mh, 0); + printf("sendmsg(-1, {msg_name=NULL, msg_namelen=0, msg_iov=NULL" + ", msg_iovlen=0, msg_control=[{cmsg_len=%u" + ", cmsg_level=SOL_SOCKET, cmsg_type=SO_TIMESTAMPNS_NEW" + ", cmsg_data={tv_sec=%lld, tv_nsec=%llu}}]" + ", msg_controllen=%lu, msg_flags=0}, 0) = %s\n", + (unsigned) cmsg->cmsg_len, + (long long) ts->tv_sec, zero_extend_signed_to_ull(ts->tv_nsec), + (unsigned long) len, sprintrc(rc)); + + len = CMSG_SPACE(sizeof(struct __kernel_timespec) - sizeof(long)); + cmsg = get_cmsghdr(page, len); + + cmsg->cmsg_len = + CMSG_LEN(sizeof(struct __kernel_timespec) - sizeof(long)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMPNS_NEW; + + mh->msg_control = cmsg; + mh->msg_controllen = len; + + rc = sendmsg(-1, mh, 0); + printf("sendmsg(-1, {msg_name=NULL, msg_namelen=0, msg_iov=NULL" + ", msg_iovlen=0, msg_control=[{cmsg_len=%u" + ", cmsg_level=SOL_SOCKET, cmsg_type=SO_TIMESTAMPNS_NEW" + ", cmsg_data=?}]" + ", msg_controllen=%lu, msg_flags=0}, 0) = %s\n", + (unsigned) cmsg->cmsg_len, + (unsigned long) len, sprintrc(rc)); +} + +static void +test_scm_timestamping_new(struct msghdr *const mh, void *const page) +{ + size_t len = CMSG_SPACE(3 * sizeof(struct __kernel_timespec)); + struct cmsghdr *cmsg = get_cmsghdr(page, len); + + cmsg->cmsg_len = CMSG_LEN(3 * sizeof(struct __kernel_timespec)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMPING_NEW; + struct __kernel_timespec *ts = + (struct __kernel_timespec *) CMSG_DATA(cmsg); + ts[0].tv_sec = 0xdeface0deadbef1; + ts[0].tv_nsec = 0xdec0de2cafef0d3; + ts[1].tv_sec = 0xdeface4deadbef5; + ts[1].tv_nsec = 0xdec0de6cafef0d7; + ts[2].tv_sec = 0xdeface8deadbef9; + ts[2].tv_nsec = 0xdec0dedcafef00d; + + mh->msg_control = cmsg; + mh->msg_controllen = len; + + int rc = sendmsg(-1, mh, 0); + printf("sendmsg(-1, {msg_name=NULL, msg_namelen=0, msg_iov=NULL" + ", msg_iovlen=0, msg_control=[{cmsg_len=%u" + ", cmsg_level=SOL_SOCKET, cmsg_type=SO_TIMESTAMPING_NEW" + ", cmsg_data=[{tv_sec=%lld, tv_nsec=%llu}" + ", {tv_sec=%lld, tv_nsec=%llu}, {tv_sec=%lld, tv_nsec=%llu}]}]" + ", msg_controllen=%lu, msg_flags=0}, 0) = %s\n", + (unsigned) cmsg->cmsg_len, (long long) ts[0].tv_sec, + zero_extend_signed_to_ull(ts[0].tv_nsec), + (long long) ts[1].tv_sec, + zero_extend_signed_to_ull(ts[1].tv_nsec), + (long long) ts[2].tv_sec, + zero_extend_signed_to_ull(ts[2].tv_nsec), + (unsigned long) len, sprintrc(rc)); + + len = CMSG_SPACE(3 * sizeof(struct __kernel_timespec) - sizeof(long)); + cmsg = get_cmsghdr(page, len); + + cmsg->cmsg_len = + CMSG_LEN(3 * sizeof(struct __kernel_timespec) - sizeof(long)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SO_TIMESTAMPING_NEW; + + mh->msg_control = cmsg; + mh->msg_controllen = len; + + rc = sendmsg(-1, mh, 0); + printf("sendmsg(-1, {msg_name=NULL, msg_namelen=0, msg_iov=NULL" + ", msg_iovlen=0, msg_control=[{cmsg_len=%u" + ", cmsg_level=SOL_SOCKET, cmsg_type=SO_TIMESTAMPING_NEW" + ", cmsg_data=?}]" + ", msg_controllen=%lu, msg_flags=0}, 0) = %s\n", + (unsigned) cmsg->cmsg_len, + (unsigned long) len, sprintrc(rc)); +} +#endif /* HAVE_STRUCT___KERNEL_TIMESPEC */ + static void print_security(const struct cmsghdr *const cmsg, const size_t cmsg_len) { @@ -504,9 +665,16 @@ test_sol_socket(struct msghdr *const mh, void *const page) test_scm_rights3(mh, page, DEFAULT_STRLEN); test_scm_rights3(mh, page, DEFAULT_STRLEN + 1); - test_scm_timestamp(mh, page); - test_scm_timestampns(mh, page); - test_scm_timestamping(mh, page); + test_scm_timestamp_old(mh, page); + test_scm_timestampns_old(mh, page); + test_scm_timestamping_old(mh, page); +#ifdef HAVE_STRUCT___KERNEL_SOCK_TIMEVAL + test_scm_timestamp_new(mh, page); +#endif +#ifdef HAVE_STRUCT___KERNEL_TIMESPEC + test_scm_timestampns_new(mh, page); + test_scm_timestamping_new(mh, page); +#endif test_unknown_type(mh, page, ARG_STR(SOL_SOCKET), "SCM_???"); } diff --git a/tests/sockopt-timestamp.c b/tests/sockopt-timestamp.c index d6f6ccf9b..c26599258 100644 --- a/tests/sockopt-timestamp.c +++ b/tests/sockopt-timestamp.c @@ -12,15 +12,14 @@ #include <unistd.h> #include <sys/socket.h> -#ifndef SO_TIMESTAMP_OLD -# define SO_TIMESTAMP_OLD SO_TIMESTAMP +#if defined HAVE_STRUCT___KERNEL_SOCK_TIMEVAL \ + || defined HAVE_STRUCT___KERNEL_TIMESPEC +# include <linux/time_types.h> #endif -#ifndef SO_TIMESTAMPNS_OLD -# ifdef SO_TIMESTAMPNS -# define SO_TIMESTAMPNS_OLD SO_TIMESTAMPNS -# endif -#endif +#define XLAT_MACROS_ONLY +#include "xlat/sock_options.h" +#undef XLAT_MACROS_ONLY static void print_timestamp_old(const struct cmsghdr *c) @@ -39,7 +38,6 @@ print_timestamp_old(const struct cmsghdr *c) (long long) tv->tv_sec, (long long) tv->tv_usec); } -#ifdef SO_TIMESTAMPNS_OLD static void print_timestampns_old(const struct cmsghdr *c) { @@ -56,7 +54,44 @@ print_timestampns_old(const struct cmsghdr *c) printf("{tv_sec=%lld, tv_nsec=%lld}", (long long) ts->tv_sec, (long long) ts->tv_nsec); } -#endif /* SO_TIMESTAMPNS_OLD */ + +#ifdef HAVE_STRUCT___KERNEL_SOCK_TIMEVAL +static void +print_timestamp_new(const struct cmsghdr *c) +{ + const void *cmsg_header = c; + const void *cmsg_data = CMSG_DATA(c); + const struct __kernel_sock_timeval *tv = cmsg_data; + const unsigned int expected_len = sizeof(*tv); + const unsigned int data_len = c->cmsg_len - (cmsg_data - cmsg_header); + + if (expected_len != data_len) + perror_msg_and_fail("sizeof(struct __kernel_sock_timeval) = %u" + ", data_len = %u\n", + expected_len, data_len); + printf("{tv_sec=%lld, tv_usec=%lld}", + (long long) tv->tv_sec, (long long) tv->tv_usec); +} +#endif /* HAVE_STRUCT___KERNEL_SOCK_TIMEVAL */ + +#ifdef HAVE_STRUCT___KERNEL_TIMESPEC +static void +print_timestampns_new(const struct cmsghdr *c) +{ + const void *cmsg_header = c; + const void *cmsg_data = CMSG_DATA(c); + const struct __kernel_timespec *ts = cmsg_data; + const unsigned int expected_len = sizeof(*ts); + const unsigned int data_len = c->cmsg_len - (cmsg_data - cmsg_header); + + if (expected_len != data_len) + perror_msg_and_fail("sizeof(struct __kernel_timespec) = %u" + ", data_len = %u\n", + expected_len, data_len); + printf("{tv_sec=%lld, tv_nsec=%lld}", + (long long) ts->tv_sec, (long long) ts->tv_nsec); +} +#endif /* HAVE_STRUCT___KERNEL_TIMESPEC */ static unsigned int test_sockopt(int so_val, const char *str, void (*fun)(const struct cmsghdr *)) @@ -141,8 +176,12 @@ main(void) void (*fun)(const struct cmsghdr *); } tests[] = { { SO_TIMESTAMP_OLD, "SO_TIMESTAMP_OLD", print_timestamp_old }, -#ifdef SO_TIMESTAMPNS_OLD { SO_TIMESTAMPNS_OLD, "SO_TIMESTAMPNS_OLD", print_timestampns_old }, +#ifdef HAVE_STRUCT___KERNEL_SOCK_TIMEVAL + { SO_TIMESTAMP_NEW, "SO_TIMESTAMP_NEW", print_timestamp_new }, +#endif +#ifdef HAVE_STRUCT___KERNEL_TIMESPEC + { SO_TIMESTAMPNS_NEW, "SO_TIMESTAMPNS_NEW", print_timestampns_new }, #endif }; unsigned int tested = 0; |