| /* SPDX-License-Identifier: LGPL-2.1-only */ |
| /* |
| * Copyright (c) 2013 Thomas Graf <[email protected]> |
| */ |
| |
| #include "nl-default.h" |
| |
| #include <linux/netlink.h> |
| #include <linux/if_ether.h> |
| |
| #include <netlink/attr.h> |
| #include <netlink/msg.h> |
| #include <netlink/route/cls/u32.h> |
| |
| #include "cksuite-all.h" |
| #include "nl-aux-route/nl-route.h" |
| |
| START_TEST(attr_size) |
| { |
| ck_assert_msg(nla_attr_size(0) == NLA_HDRLEN, |
| "Length of empty attribute should match header size"); |
| ck_assert_msg(nla_attr_size(1) == NLA_HDRLEN + 1, |
| "Length of 1 bytes payload should be NLA_HDRLEN + 1"); |
| ck_assert_msg(nla_attr_size(2) == NLA_HDRLEN + 2, |
| "Length of 2 bytes payload should be NLA_HDRLEN + 2"); |
| ck_assert_msg(nla_attr_size(3) == NLA_HDRLEN + 3, |
| "Length of 3 bytes payload should be NLA_HDRLEN + 3"); |
| ck_assert_msg(nla_attr_size(4) == NLA_HDRLEN + 4, |
| "Length of 4 bytes payload should be NLA_HDRLEN + 4"); |
| |
| ck_assert_msg(nla_total_size(1) == NLA_HDRLEN + 4, |
| "Total size of 1 bytes payload should result in 8 bytes"); |
| ck_assert_msg(nla_total_size(2) == NLA_HDRLEN + 4, |
| "Total size of 2 bytes payload should result in 8 bytes"); |
| ck_assert_msg(nla_total_size(3) == NLA_HDRLEN + 4, |
| "Total size of 3 bytes payload should result in 8 bytes"); |
| ck_assert_msg(nla_total_size(4) == NLA_HDRLEN + 4, |
| "Total size of 4 bytes payload should result in 8 bytes"); |
| |
| ck_assert_msg(nla_padlen(1) == 3, |
| "2 bytes of payload should result in 3 padding bytes"); |
| ck_assert_msg(nla_padlen(2) == 2, |
| "2 bytes of payload should result in 2 padding bytes"); |
| ck_assert_msg(nla_padlen(3) == 1, |
| "3 bytes of payload should result in 1 padding bytes"); |
| ck_assert_msg(nla_padlen(4) == 0, |
| "4 bytes of payload should result in 0 padding bytes"); |
| ck_assert_msg(nla_padlen(5) == 3, |
| "5 bytes of payload should result in 3 padding bytes"); |
| } |
| END_TEST |
| |
| START_TEST(msg_construct) |
| { |
| struct nl_msg *msg; |
| struct nlmsghdr *nlh; |
| struct nlattr *a; |
| int i, rem; |
| |
| msg = nlmsg_alloc(); |
| ck_assert_msg(msg, "Unable to allocate netlink message"); |
| |
| for (i = 1; i < 256; i++) { |
| ck_assert_msg(nla_put_u32(msg, i, i + 1) == 0, |
| "Unable to add attribute %d", i); |
| } |
| |
| nlh = nlmsg_hdr(msg); |
| i = 1; |
| nlmsg_for_each_attr(a, nlh, 0, rem) { |
| ck_assert_msg(nla_type(a) == i, "Expected attribute %d", i); |
| i++; |
| ck_assert_msg(nla_get_u32(a) == (unsigned)i, |
| "Expected attribute value %d", i); |
| } |
| |
| nlmsg_free(msg); |
| } |
| END_TEST |
| |
| START_TEST(clone_cls_u32) |
| { |
| _nl_auto_rtnl_link struct rtnl_link *link = NULL; |
| _nl_auto_rtnl_cls struct rtnl_cls *cls = NULL; |
| _nl_auto_rtnl_cls struct rtnl_cls *cls2 = NULL; |
| int r; |
| const uint32_t direction = 16; |
| |
| link = rtnl_link_alloc(); |
| ck_assert(link); |
| |
| rtnl_link_set_ifindex(link, 5); |
| |
| cls = rtnl_cls_alloc(); |
| ck_assert(cls); |
| |
| rtnl_tc_set_link(TC_CAST(cls), link); |
| |
| r = rtnl_tc_set_kind(TC_CAST(cls), "u32"); |
| ck_assert(r == 0); |
| |
| rtnl_cls_set_prio(cls, 1); |
| rtnl_cls_set_protocol(cls, ETH_P_IP); |
| |
| rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0)); |
| |
| rtnl_u32_set_hashtable(cls, 5); |
| |
| rtnl_u32_add_key_uint32(cls, 0x0a000914, 0xffffffff, direction, 0); |
| |
| rtnl_u32_set_hashmask(cls, 0xff000000, direction); |
| |
| rtnl_u32_add_mark(cls, 55, 66); |
| |
| rtnl_u32_set_link(cls, 44); |
| |
| cls2 = (struct rtnl_cls *)nl_object_clone((struct nl_object *)cls); |
| ck_assert(cls2); |
| } |
| END_TEST |
| |
| /*****************************************************************************/ |
| |
| START_TEST(test_nltst_strtok) |
| { |
| #define _assert_strtok(str, ...) \ |
| do { \ |
| const char *const _expected[] = { NULL, ##__VA_ARGS__, NULL }; \ |
| _nltst_auto_strfreev char **_tokens = NULL; \ |
| \ |
| _tokens = _nltst_strtokv(str); \ |
| _nltst_assert_strv_equal(_tokens, &_expected[1]); \ |
| } while (0) |
| |
| _assert_strtok(""); |
| _assert_strtok(" \n"); |
| _assert_strtok("a", "a"); |
| _assert_strtok(" a ", "a"); |
| _assert_strtok(" a\\ b", "a\\ ", "b"); |
| _assert_strtok(" a\\ b cc\\d", "a\\ ", "b", "cc\\d"); |
| _assert_strtok(" a\\ b\\ cc\\d", "a\\ ", "b\\ ", "cc\\d"); |
| } |
| END_TEST |
| |
| /*****************************************************************************/ |
| |
| START_TEST(test_nltst_select_route) |
| { |
| /* This is a unit test for testing the unit-test helper function |
| * _nltst_select_route_parse(). */ |
| |
| #define _check(str, exp_addr_family, exp_addr_pattern, exp_plen) \ |
| do { \ |
| const char *_str = (str); \ |
| const int _exp_addr_family = (exp_addr_family); \ |
| const char *const _exp_addr_pattern = (exp_addr_pattern); \ |
| const int _exp_plen = (exp_plen); \ |
| _nltst_auto_clear_select_route NLTstSelectRoute \ |
| _select_route = { 0 }; \ |
| _nltst_auto_clear_select_route NLTstSelectRoute \ |
| _select_route2 = { 0 }; \ |
| _nl_auto_free char *_str2 = NULL; \ |
| \ |
| _nltst_select_route_parse(_str, &_select_route); \ |
| ck_assert_int_eq(_exp_addr_family, _select_route.addr_family); \ |
| if (_nltst_inet_valid(AF_UNSPEC, _exp_addr_pattern)) { \ |
| ck_assert_str_eq(_exp_addr_pattern, \ |
| _select_route.addr); \ |
| ck_assert_ptr_null(_select_route.addr_pattern); \ |
| } else { \ |
| ck_assert_str_eq(_exp_addr_pattern, \ |
| _select_route.addr_pattern); \ |
| ck_assert_ptr_null(_select_route.addr); \ |
| } \ |
| ck_assert_int_eq(_exp_plen, _select_route.plen); \ |
| \ |
| _nltst_assert_select_route(&_select_route); \ |
| \ |
| _str2 = _nltst_select_route_to_string(&_select_route); \ |
| ck_assert_ptr_nonnull(_str2); \ |
| \ |
| _nltst_select_route_parse(_str2, &_select_route2); \ |
| \ |
| ck_assert(_nltst_select_route_equal(&_select_route, \ |
| &_select_route2)); \ |
| } while (0) |
| |
| _check("0.0.0.0", AF_INET, "0.0.0.0", -1); |
| _check("4 0.0.0.0/0", AF_INET, "0.0.0.0", 0); |
| _check(" 6\n 0:0::/0", AF_INET6, "::", 0); |
| _check(" \n 0:0::/100", AF_INET6, "::", 100); |
| _check("6 0:0::*/0 ", AF_INET6, "0:0::*", 0); |
| _check("6 0:0::*/128 ", AF_INET6, "0:0::*", 128); |
| _check("6 0:0::* ", AF_INET6, "0:0::*", -1); |
| |
| #undef _check |
| } |
| |
| /*****************************************************************************/ |
| |
| Suite *make_nl_attr_suite(void) |
| { |
| Suite *suite = suite_create("Netlink attributes"); |
| TCase *tc = tcase_create("Core"); |
| |
| tcase_add_test(tc, attr_size); |
| tcase_add_test(tc, msg_construct); |
| tcase_add_test(tc, clone_cls_u32); |
| tcase_add_test(tc, test_nltst_strtok); |
| tcase_add_test(tc, test_nltst_select_route); |
| suite_add_tcase(suite, tc); |
| |
| return suite; |
| } |