From 4f652c1ec45132a2392d8a946135d4e1655b714c Mon Sep 17 00:00:00 2001 From: Eugene Syromyatnikov Date: Fri, 25 May 2018 05:14:18 +0200 Subject: [PATCH] tests: check decoding of IFLA_AF_SPEC netlink attribute * configure.ac (AC_CHECK_TYPES): Check for struct ifla_cacheinfo in (AC_CHECK_DECLS): Check for IFLA_AF_SPEC in . * tests/nlattr_ifla_af_spec.c: New file. * tests/pure_executables.list: Add nlattr_ifla_af_spec. * tests/.gitignore: Likewise. * tests/gen_tests.in (nlattr_ifla_af_spec): New test. --- configure.ac | 2 + tests/.gitignore | 1 + tests/gen_tests.in | 1 + tests/nlattr_ifla_af_spec.c | 320 ++++++++++++++++++++++++++++++++++++ tests/pure_executables.list | 1 + 5 files changed, 325 insertions(+) create mode 100644 tests/nlattr_ifla_af_spec.c diff --git a/configure.ac b/configure.ac index dc887abe..ed22a720 100644 --- a/configure.ac +++ b/configure.ac @@ -507,6 +507,7 @@ AC_CHECK_TYPES(m4_normalize([ AC_CHECK_TYPES(m4_normalize([ struct ifla_bridge_id, + struct ifla_cacheinfo, struct ifla_port_vsi, struct rtnl_link_stats64 ]),,, [#include @@ -519,6 +520,7 @@ AC_CHECK_MEMBERS(m4_normalize([ AC_CHECK_DECLS(m4_normalize([ IFLA_PORT_SELF, IFLA_PROTINFO, + IFLA_AF_SPEC, IFLA_XDP ]),,, [#include #include ]) diff --git a/tests/.gitignore b/tests/.gitignore index a754f788..4c5fd7fa 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -287,6 +287,7 @@ nlattr_fib_rule_hdr nlattr_ifaddrlblmsg nlattr_ifaddrmsg nlattr_ifinfomsg +nlattr_ifla_af_spec nlattr_ifla_brport nlattr_ifla_port nlattr_ifla_xdp diff --git a/tests/gen_tests.in b/tests/gen_tests.in index f3518d19..9d6c00be 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -262,6 +262,7 @@ nlattr_fib_rule_hdr +netlink_sock_diag.test nlattr_ifaddrlblmsg +netlink_sock_diag.test nlattr_ifaddrmsg +netlink_sock_diag.test nlattr_ifinfomsg +netlink_sock_diag.test +nlattr_ifla_af_spec +netlink_sock_diag.test nlattr_ifla_brport +netlink_sock_diag.test nlattr_ifla_port +netlink_sock_diag.test nlattr_ifla_xdp +netlink_sock_diag.test diff --git a/tests/nlattr_ifla_af_spec.c b/tests/nlattr_ifla_af_spec.c new file mode 100644 index 00000000..287e0817 --- /dev/null +++ b/tests/nlattr_ifla_af_spec.c @@ -0,0 +1,320 @@ +/* + * IFLA_AF_SPEC netlink attribute decoding check. + * + * Copyright (c) 2018 The strace developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tests.h" + +#include +#include +#include +#include "test_nlattr.h" + +#include +#include +#ifdef HAVE_LINUX_IF_LINK_H +# include +#endif +#include + +#if !HAVE_DECL_IFLA_AF_SPEC +enum { IFLA_AF_SPEC = 26 }; +#endif + +#define XLAT_MACROS_ONLY +# include "xlat/rtnl_ifla_af_spec_inet_attrs.h" +# include "xlat/rtnl_ifla_af_spec_inet6_attrs.h" +#undef XLAT_MACROS_ONLY + +#ifndef HAVE_STRUCT_IFLA_CACHEINFO +struct ifla_cacheinfo { + uint32_t max_reasm_len; + uint32_t tstamp; + uint32_t reachable_time; + uint32_t retrans_time; +}; +#endif + +#define IFLA_ATTR IFLA_AF_SPEC +#include "nlattr_ifla.h" + +#define AF_SPEC_FUNCS(family_) \ + static void \ + init_##family_##_msg(struct nlmsghdr *const nlh, \ + const unsigned int msg_len) \ + { \ + init_ifinfomsg(nlh, msg_len); \ + \ + struct nlattr *nla = NLMSG_ATTR(nlh, hdrlen); \ + nla += 1; \ + SET_STRUCT(struct nlattr, nla, \ + .nla_len = msg_len - NLMSG_SPACE(hdrlen) \ + - NLA_HDRLEN, \ + .nla_type = family_, \ + ); \ + } \ + \ + static void \ + print_##family_##_msg(const unsigned int msg_len) \ + { \ + print_ifinfomsg(msg_len); \ + printf(", {{nla_len=%u, nla_type=" #family_ "}", \ + msg_len - NLMSG_SPACE(hdrlen) - NLA_HDRLEN); \ + } \ + /* end of AF_SPEC_FUNCS definition */ + +AF_SPEC_FUNCS(AF_INET) +AF_SPEC_FUNCS(AF_INET6) + +static void +print_arr_val(uint32_t *val, size_t idx, const char *idx_str) +{ + if (idx_str) + printf("[%s] = ", idx_str); + else + printf("[%zu] = ", idx); + + printf("%d", *val); +} + +static void +print_arr_uval(uint64_t *val, size_t idx, const char *idx_str) +{ + if (idx_str) + printf("[%s] = ", idx_str); + else + printf("[%zu] = ", idx); + + printf("%" PRIu64, *val); +} + +static void +print_inet_conf_val(uint32_t *val, size_t idx) +{ + static const char * const strs[] = { + "IPV4_DEVCONF_FORWARDING-1", + "IPV4_DEVCONF_MC_FORWARDING-1", + }; + + print_arr_val(val, idx, idx < ARRAY_SIZE(strs) ? strs[idx] : NULL); +} + + +static void +print_inet6_conf_val(uint32_t *val, size_t idx) +{ + static const char * const strs[] = { + "DEVCONF_FORWARDING", + "DEVCONF_HOPLIMIT", + }; + + print_arr_val(val, idx, idx < ARRAY_SIZE(strs) ? strs[idx] : NULL); +} + +static void +print_inet6_stats_val(uint64_t *val, size_t idx) +{ + static const char * const strs[] = { + "IPSTATS_MIB_NUM", + "IPSTATS_MIB_INPKTS", + }; + + print_arr_uval(val, idx, idx < ARRAY_SIZE(strs) ? strs[idx] : NULL); +} + +static void +print_icmp6_stats_val(uint64_t *val, size_t idx) +{ + static const char * const strs[] = { + "ICMP6_MIB_NUM", + "ICMP6_MIB_INMSGS", + "ICMP6_MIB_INERRORS", + "ICMP6_MIB_OUTMSGS", + "ICMP6_MIB_OUTERRORS", + "ICMP6_MIB_CSUMERRORS", + "6 /* ICMP6_MIB_??? */", + }; + + print_arr_uval(val, idx, idx < ARRAY_SIZE(strs) ? strs[idx] : NULL); +} + +int +main(void) +{ + static const uint8_t unknown_msg[] = { 0xab, 0xac, 0xdb, 0xcd }; + + skip_if_unavailable("/proc/self/fd/"); + + const int fd = create_nl_socket(NETLINK_ROUTE); + + const unsigned int hdrlen = sizeof(struct ifinfomsg); + void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), 3 * NLA_HDRLEN + 256); + + static char pattern[4096]; + fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1); + + + /* unknown AF_* */ + TEST_NESTED_NLATTR_OBJECT(fd, nlh0, hdrlen, + init_ifinfomsg, print_ifinfomsg, + AF_UNIX, pattern, unknown_msg, + printf("\"\\xab\\xac\\xdb\\xcd\"")); + + /* AF_INET */ + TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen, + init_AF_INET_msg, print_AF_INET_msg, + 0, "IFLA_INET_UNSPEC", pattern, + unknown_msg, 2, + printf("\"\\xab\\xac\\xdb\\xcd\"")); + TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen, + init_AF_INET_msg, print_AF_INET_msg, + 2, "0x2 /* IFLA_INET_??? */", pattern, + unknown_msg, 2, + printf("\"\\xab\\xac\\xdb\\xcd\"")); + + /* AF_INET: IFLA_INET_CONF */ + uint32_t inet_conf_vals[] = { 0xdeadc0de, 0xda7aface }; + TEST_NESTED_NLATTR_ARRAY_EX(fd, nlh0, hdrlen, + init_AF_INET_msg, print_AF_INET_msg, + IFLA_INET_CONF, pattern, + inet_conf_vals, 2, print_inet_conf_val); + + /* AF_INET6 */ + TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen, + init_AF_INET6_msg, print_AF_INET6_msg, + 0, "IFLA_INET6_UNSPEC", pattern, + unknown_msg, 2, + printf("\"\\xab\\xac\\xdb\\xcd\"")); + TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen, + init_AF_INET6_msg, print_AF_INET6_msg, + 9, "0x9 /* IFLA_INET6_??? */", pattern, + unknown_msg, 2, + printf("\"\\xab\\xac\\xdb\\xcd\"")); + + /* AF_INET6: IFLA_INET6_FLAGS */ + static const struct { + uint32_t flags; + const char *str; + } inet6_flags[] = { + { 0xf, "0xf /* IF_??? */" }, + { 0x10, "IF_RS_SENT" }, + { 0xc0, "IF_RA_MANAGED|IF_RA_OTHERCONF" }, + { 0xdeadc0de, "IF_RS_SENT|IF_RA_MANAGED|IF_RA_OTHERCONF" + "|IF_READY|0x5eadc00e" }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(inet6_flags); i++) { + TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen, + init_AF_INET6_msg, + print_AF_INET6_msg, + 1, "IFLA_INET6_FLAGS", pattern, + inet6_flags[i].flags, 2, + printf("%s", inet6_flags[i].str)); + } + + /* AF_INET6: IFLA_INET6_CONF */ + uint32_t inet6_conf_vals[] = { 0xdeadc0de, 0xda7aface }; + TEST_NESTED_NLATTR_ARRAY_EX(fd, nlh0, hdrlen, + init_AF_INET6_msg, print_AF_INET6_msg, + IFLA_INET6_CONF, pattern, + inet6_conf_vals, 2, print_inet6_conf_val); + + /* AF_INET6: IFLA_INET6_STATS */ + uint64_t inet6_stats_vals[] = { 0xdeadc0deda7aface, 0xdec0deedbadc0ded }; + TEST_NESTED_NLATTR_ARRAY_EX(fd, nlh0, hdrlen, + init_AF_INET6_msg, print_AF_INET6_msg, + IFLA_INET6_STATS, pattern, + inet6_stats_vals, 2, print_inet6_stats_val); + + /* AF_INET6: IFLA_INET6_MCAST */ + TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen, + init_AF_INET6_msg, print_AF_INET6_msg, + 4, "IFLA_INET6_MCAST", pattern, + unknown_msg, 2, + printf("\"\\xab\\xac\\xdb\\xcd\"")); + + /* AF_INET6: IFLA_INET6_CACHEINFO */ + static const struct ifla_cacheinfo ci = { + 0xbadc0ded, 0xfacebeef, 0xdecafeed, 0xdeadfeed, + }; + TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen, + init_AF_INET6_msg, print_AF_INET6_msg, + 5, "IFLA_INET6_CACHEINFO", pattern, + ci, 2, + PRINT_FIELD_U("{", ci, max_reasm_len); + PRINT_FIELD_U(", ", ci, tstamp); + PRINT_FIELD_U(", ", ci, reachable_time); + PRINT_FIELD_U(", ", ci, retrans_time); + printf("}")); + + /* AF_INET6: IFLA_INET6_ICMP6STATS */ + uint64_t icmp6_stats_vals[] = { + 0xdeadc0deda7aface, 0xdec0deedbadc0ded, 0xfacebeefdeadfeed, + 0xdeadc0deda7afacd, 0xdec0deedbadc0dee, 0xfacebeefdeadfeef, + 0xdeadc0deda7afacc + }; + TEST_NESTED_NLATTR_ARRAY_EX(fd, nlh0, hdrlen, + init_AF_INET6_msg, print_AF_INET6_msg, + IFLA_INET6_ICMP6STATS, pattern, + icmp6_stats_vals, 2, print_icmp6_stats_val); + + /* AF_INET6: IFLA_INET6_TOKEN */ + uint8_t inet6_addr[16] = { + 0xba, 0xdc, 0x0d, 0xed, 0xfa, 0xce, 0xbe, 0xef, + 0xde, 0xca, 0xfe, 0xed, 0xde, 0xad, 0xfe, 0xed, + }; + TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen, + init_AF_INET6_msg, print_AF_INET6_msg, + 7, "IFLA_INET6_TOKEN", pattern, + inet6_addr, 2, + printf("badc:ded:face:beef:deca:feed" + ":dead:feed")); + + /* AF_INET6: IFLA_INET6_ */ + static const struct { + uint8_t flags; + const char *str; + } agms[] = { + { 0x0, "IN6_ADDR_GEN_MODE_EUI64" }, + { 0x3, "IN6_ADDR_GEN_MODE_RANDOM" }, + { 0x4, "0x4 /* IN6_ADDR_GEN_MODE_??? */" }, + { 0xff, "0xff /* IN6_ADDR_GEN_MODE_??? */" }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(agms); i++) { + TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen, + init_AF_INET6_msg, + print_AF_INET6_msg, + 8, "IFLA_INET6_ADDR_GEN_MODE", + pattern, agms[i].flags, 2, + printf("%s", agms[i].str)); + } + + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/pure_executables.list b/tests/pure_executables.list index df84fe66..dea26745 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -238,6 +238,7 @@ nlattr_fib_rule_hdr nlattr_ifaddrlblmsg nlattr_ifaddrmsg nlattr_ifinfomsg +nlattr_ifla_af_spec nlattr_ifla_brport nlattr_ifla_port nlattr_ifla_xdp -- 2.40.0