1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (c) 2013 Thomas Graf <[email protected]>
4 */
5
6 #include "nl-default.h"
7
8 #include <linux/netlink.h>
9 #include <linux/if_ether.h>
10
11 #include <netlink/attr.h>
12 #include <netlink/msg.h>
13 #include <netlink/route/cls/u32.h>
14
15 #include "cksuite-all.h"
16 #include "nl-aux-route/nl-route.h"
17
START_TEST(attr_size)18 START_TEST(attr_size)
19 {
20 ck_assert_msg(nla_attr_size(0) == NLA_HDRLEN,
21 "Length of empty attribute should match header size");
22 ck_assert_msg(nla_attr_size(1) == NLA_HDRLEN + 1,
23 "Length of 1 bytes payload should be NLA_HDRLEN + 1");
24 ck_assert_msg(nla_attr_size(2) == NLA_HDRLEN + 2,
25 "Length of 2 bytes payload should be NLA_HDRLEN + 2");
26 ck_assert_msg(nla_attr_size(3) == NLA_HDRLEN + 3,
27 "Length of 3 bytes payload should be NLA_HDRLEN + 3");
28 ck_assert_msg(nla_attr_size(4) == NLA_HDRLEN + 4,
29 "Length of 4 bytes payload should be NLA_HDRLEN + 4");
30
31 ck_assert_msg(nla_total_size(1) == NLA_HDRLEN + 4,
32 "Total size of 1 bytes payload should result in 8 bytes");
33 ck_assert_msg(nla_total_size(2) == NLA_HDRLEN + 4,
34 "Total size of 2 bytes payload should result in 8 bytes");
35 ck_assert_msg(nla_total_size(3) == NLA_HDRLEN + 4,
36 "Total size of 3 bytes payload should result in 8 bytes");
37 ck_assert_msg(nla_total_size(4) == NLA_HDRLEN + 4,
38 "Total size of 4 bytes payload should result in 8 bytes");
39
40 ck_assert_msg(nla_padlen(1) == 3,
41 "2 bytes of payload should result in 3 padding bytes");
42 ck_assert_msg(nla_padlen(2) == 2,
43 "2 bytes of payload should result in 2 padding bytes");
44 ck_assert_msg(nla_padlen(3) == 1,
45 "3 bytes of payload should result in 1 padding bytes");
46 ck_assert_msg(nla_padlen(4) == 0,
47 "4 bytes of payload should result in 0 padding bytes");
48 ck_assert_msg(nla_padlen(5) == 3,
49 "5 bytes of payload should result in 3 padding bytes");
50 }
51 END_TEST
52
START_TEST(msg_construct)53 START_TEST(msg_construct)
54 {
55 struct nl_msg *msg;
56 struct nlmsghdr *nlh;
57 struct nlattr *a;
58 int i, rem;
59
60 msg = nlmsg_alloc();
61 ck_assert_msg(msg, "Unable to allocate netlink message");
62
63 for (i = 1; i < 256; i++) {
64 ck_assert_msg(nla_put_u32(msg, i, i + 1) == 0,
65 "Unable to add attribute %d", i);
66 }
67
68 nlh = nlmsg_hdr(msg);
69 i = 1;
70 nlmsg_for_each_attr(a, nlh, 0, rem) {
71 ck_assert_msg(nla_type(a) == i, "Expected attribute %d", i);
72 i++;
73 ck_assert_msg(nla_get_u32(a) == (unsigned)i,
74 "Expected attribute value %d", i);
75 }
76
77 nlmsg_free(msg);
78 }
79 END_TEST
80
START_TEST(clone_cls_u32)81 START_TEST(clone_cls_u32)
82 {
83 _nl_auto_rtnl_link struct rtnl_link *link = NULL;
84 _nl_auto_rtnl_cls struct rtnl_cls *cls = NULL;
85 _nl_auto_rtnl_cls struct rtnl_cls *cls2 = NULL;
86 int r;
87 const uint32_t direction = 16;
88
89 link = rtnl_link_alloc();
90 ck_assert(link);
91
92 rtnl_link_set_ifindex(link, 5);
93
94 cls = rtnl_cls_alloc();
95 ck_assert(cls);
96
97 rtnl_tc_set_link(TC_CAST(cls), link);
98
99 r = rtnl_tc_set_kind(TC_CAST(cls), "u32");
100 ck_assert(r == 0);
101
102 rtnl_cls_set_prio(cls, 1);
103 rtnl_cls_set_protocol(cls, ETH_P_IP);
104
105 rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0));
106
107 rtnl_u32_set_hashtable(cls, 5);
108
109 rtnl_u32_add_key_uint32(cls, 0x0a000914, 0xffffffff, direction, 0);
110
111 rtnl_u32_set_hashmask(cls, 0xff000000, direction);
112
113 rtnl_u32_add_mark(cls, 55, 66);
114
115 rtnl_u32_set_link(cls, 44);
116
117 cls2 = (struct rtnl_cls *)nl_object_clone((struct nl_object *)cls);
118 ck_assert(cls2);
119 }
120 END_TEST
121
122 /*****************************************************************************/
123
START_TEST(test_nltst_strtok)124 START_TEST(test_nltst_strtok)
125 {
126 #define _assert_strtok(str, ...) \
127 do { \
128 const char *const _expected[] = { NULL, ##__VA_ARGS__, NULL }; \
129 _nltst_auto_strfreev char **_tokens = NULL; \
130 \
131 _tokens = _nltst_strtokv(str); \
132 _nltst_assert_strv_equal(_tokens, &_expected[1]); \
133 } while (0)
134
135 _assert_strtok("");
136 _assert_strtok(" \n");
137 _assert_strtok("a", "a");
138 _assert_strtok(" a ", "a");
139 _assert_strtok(" a\\ b", "a\\ ", "b");
140 _assert_strtok(" a\\ b cc\\d", "a\\ ", "b", "cc\\d");
141 _assert_strtok(" a\\ b\\ cc\\d", "a\\ ", "b\\ ", "cc\\d");
142 }
143 END_TEST
144
145 /*****************************************************************************/
146
START_TEST(test_nltst_select_route)147 START_TEST(test_nltst_select_route)
148 {
149 /* This is a unit test for testing the unit-test helper function
150 * _nltst_select_route_parse(). */
151
152 #define _check(str, exp_addr_family, exp_addr_pattern, exp_plen) \
153 do { \
154 const char *_str = (str); \
155 const int _exp_addr_family = (exp_addr_family); \
156 const char *const _exp_addr_pattern = (exp_addr_pattern); \
157 const int _exp_plen = (exp_plen); \
158 _nltst_auto_clear_select_route NLTstSelectRoute \
159 _select_route = { 0 }; \
160 _nltst_auto_clear_select_route NLTstSelectRoute \
161 _select_route2 = { 0 }; \
162 _nl_auto_free char *_str2 = NULL; \
163 \
164 _nltst_select_route_parse(_str, &_select_route); \
165 ck_assert_int_eq(_exp_addr_family, _select_route.addr_family); \
166 if (_nltst_inet_valid(AF_UNSPEC, _exp_addr_pattern)) { \
167 ck_assert_str_eq(_exp_addr_pattern, \
168 _select_route.addr); \
169 ck_assert_ptr_null(_select_route.addr_pattern); \
170 } else { \
171 ck_assert_str_eq(_exp_addr_pattern, \
172 _select_route.addr_pattern); \
173 ck_assert_ptr_null(_select_route.addr); \
174 } \
175 ck_assert_int_eq(_exp_plen, _select_route.plen); \
176 \
177 _nltst_assert_select_route(&_select_route); \
178 \
179 _str2 = _nltst_select_route_to_string(&_select_route); \
180 ck_assert_ptr_nonnull(_str2); \
181 \
182 _nltst_select_route_parse(_str2, &_select_route2); \
183 \
184 ck_assert(_nltst_select_route_equal(&_select_route, \
185 &_select_route2)); \
186 } while (0)
187
188 _check("0.0.0.0", AF_INET, "0.0.0.0", -1);
189 _check("4 0.0.0.0/0", AF_INET, "0.0.0.0", 0);
190 _check(" 6\n 0:0::/0", AF_INET6, "::", 0);
191 _check(" \n 0:0::/100", AF_INET6, "::", 100);
192 _check("6 0:0::*/0 ", AF_INET6, "0:0::*", 0);
193 _check("6 0:0::*/128 ", AF_INET6, "0:0::*", 128);
194 _check("6 0:0::* ", AF_INET6, "0:0::*", -1);
195
196 #undef _check
197 }
198
199 /*****************************************************************************/
200
make_nl_attr_suite(void)201 Suite *make_nl_attr_suite(void)
202 {
203 Suite *suite = suite_create("Netlink attributes");
204 TCase *tc = tcase_create("Core");
205
206 tcase_add_test(tc, attr_size);
207 tcase_add_test(tc, msg_construct);
208 tcase_add_test(tc, clone_cls_u32);
209 tcase_add_test(tc, test_nltst_strtok);
210 tcase_add_test(tc, test_nltst_select_route);
211 suite_add_tcase(suite, tc);
212
213 return suite;
214 }
215