1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4
5 #include <sys/param.h>
6 #include <sys/module.h>
7
8 #include <netlink/netlink.h>
9 #include <netlink/netlink_route.h>
10 #include "netlink/netlink_snl.h"
11 #include "netlink/netlink_snl_route.h"
12 #include "netlink/netlink_snl_route_parsers.h"
13
14 #include <atf-c.h>
15
16 static const struct snl_hdr_parser *snl_all_core_parsers[] = {
17 &snl_errmsg_parser, &snl_donemsg_parser,
18 &_nla_bit_parser, &_nla_bitset_parser,
19 };
20
21 static const struct snl_hdr_parser *snl_all_route_parsers[] = {
22 &_metrics_mp_nh_parser, &_mpath_nh_parser, &_metrics_parser, &snl_rtm_route_parser,
23 &_link_fbsd_parser, &snl_rtm_link_parser, &snl_rtm_link_parser_simple,
24 &_neigh_fbsd_parser, &snl_rtm_neigh_parser,
25 &_addr_fbsd_parser, &snl_rtm_addr_parser, &_nh_fbsd_parser, &snl_nhmsg_parser,
26 };
27
28 ATF_TC(snl_verify_core_parsers);
ATF_TC_HEAD(snl_verify_core_parsers,tc)29 ATF_TC_HEAD(snl_verify_core_parsers, tc)
30 {
31 atf_tc_set_md_var(tc, "descr", "Tests snl(3) core nlmsg parsers are correct");
32 }
33
ATF_TC_BODY(snl_verify_core_parsers,tc)34 ATF_TC_BODY(snl_verify_core_parsers, tc)
35 {
36 SNL_VERIFY_PARSERS(snl_all_core_parsers);
37
38 }
39
40 ATF_TC(snl_verify_route_parsers);
ATF_TC_HEAD(snl_verify_route_parsers,tc)41 ATF_TC_HEAD(snl_verify_route_parsers, tc)
42 {
43 atf_tc_set_md_var(tc, "descr", "Tests snl(3) route parsers are correct");
44 }
45
ATF_TC_BODY(snl_verify_route_parsers,tc)46 ATF_TC_BODY(snl_verify_route_parsers, tc)
47 {
48 SNL_VERIFY_PARSERS(snl_all_route_parsers);
49
50 }
51
52 ATF_TC(snl_parse_errmsg_capped);
ATF_TC_HEAD(snl_parse_errmsg_capped,tc)53 ATF_TC_HEAD(snl_parse_errmsg_capped, tc)
54 {
55 atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing capped errors");
56 atf_tc_set_md_var(tc, "require.kmods", "netlink");
57 }
58
ATF_TC_BODY(snl_parse_errmsg_capped,tc)59 ATF_TC_BODY(snl_parse_errmsg_capped, tc)
60 {
61 struct snl_state ss;
62 struct snl_writer nw;
63
64 if (!snl_init(&ss, NETLINK_ROUTE))
65 atf_tc_fail("snl_init() failed");
66
67 atf_tc_skip("does not work");
68
69 int optval = 1;
70 ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_CAP_ACK, &optval, sizeof(optval)) == 0);
71
72 snl_init_writer(&ss, &nw);
73
74 struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255);
75 ATF_CHECK(hdr != NULL);
76 ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
77 snl_add_msg_attr_string(&nw, 143, "some random string");
78 ATF_CHECK(snl_finalize_msg(&nw) != NULL);
79
80 ATF_CHECK(snl_send_message(&ss, hdr));
81
82 struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
83 ATF_CHECK(rx_hdr != NULL);
84 ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR);
85
86 struct snl_errmsg_data e = {};
87 ATF_CHECK(rx_hdr->nlmsg_len == sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr));
88 ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e));
89 ATF_CHECK(e.error != 0);
90 ATF_CHECK(!memcmp(hdr, e.orig_hdr, sizeof(struct nlmsghdr)));
91 }
92
93 ATF_TC(snl_parse_errmsg_capped_extack);
ATF_TC_HEAD(snl_parse_errmsg_capped_extack,tc)94 ATF_TC_HEAD(snl_parse_errmsg_capped_extack, tc)
95 {
96 atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing capped errors with extack");
97 atf_tc_set_md_var(tc, "require.kmods", "netlink");
98 }
99
ATF_TC_BODY(snl_parse_errmsg_capped_extack,tc)100 ATF_TC_BODY(snl_parse_errmsg_capped_extack, tc)
101 {
102 struct snl_state ss;
103 struct snl_writer nw;
104
105 if (!snl_init(&ss, NETLINK_ROUTE))
106 atf_tc_fail("snl_init() failed");
107
108 int optval = 1;
109 ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_CAP_ACK, &optval, sizeof(optval)) == 0);
110 optval = 1;
111 ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0);
112
113 snl_init_writer(&ss, &nw);
114
115 struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255);
116 ATF_CHECK(hdr != NULL);
117 ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
118 snl_add_msg_attr_string(&nw, 143, "some random string");
119 ATF_CHECK(snl_finalize_msg(&nw) != NULL);
120
121 ATF_CHECK(snl_send_message(&ss, hdr));
122
123 struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
124 ATF_CHECK(rx_hdr != NULL);
125 ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR);
126
127 struct snl_errmsg_data e = {};
128 ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e));
129 ATF_CHECK(e.error != 0);
130 ATF_CHECK(!memcmp(hdr, e.orig_hdr, sizeof(struct nlmsghdr)));
131
132 ATF_CHECK(e.error_str != NULL);
133 }
134
135 ATF_TC(snl_parse_errmsg_uncapped_extack);
ATF_TC_HEAD(snl_parse_errmsg_uncapped_extack,tc)136 ATF_TC_HEAD(snl_parse_errmsg_uncapped_extack, tc)
137 {
138 atf_tc_set_md_var(tc, "descr", "Tests snl(3) correctly parsing errors with extack");
139 atf_tc_set_md_var(tc, "require.kmods", "netlink");
140 }
141
ATF_TC_BODY(snl_parse_errmsg_uncapped_extack,tc)142 ATF_TC_BODY(snl_parse_errmsg_uncapped_extack, tc)
143 {
144 struct snl_state ss;
145 struct snl_writer nw;
146
147 ATF_CHECK(snl_init(&ss, NETLINK_ROUTE));
148
149 int optval = 1;
150 ATF_CHECK(setsockopt(ss.fd, SOL_NETLINK, NETLINK_EXT_ACK, &optval, sizeof(optval)) == 0);
151
152 snl_init_writer(&ss, &nw);
153
154 struct nlmsghdr *hdr = snl_create_msg_request(&nw, 255);
155 ATF_CHECK(hdr != NULL);
156 ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
157 snl_add_msg_attr_string(&nw, 143, "some random string");
158 ATF_CHECK(snl_finalize_msg(&nw) != NULL);
159
160 ATF_CHECK(snl_send_message(&ss, hdr));
161
162 struct nlmsghdr *rx_hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
163 ATF_CHECK(rx_hdr != NULL);
164 ATF_CHECK(rx_hdr->nlmsg_type == NLMSG_ERROR);
165
166 struct snl_errmsg_data e = {};
167 ATF_CHECK(snl_parse_errmsg(&ss, rx_hdr, &e));
168 ATF_CHECK(e.error != 0);
169 ATF_CHECK(!memcmp(hdr, e.orig_hdr, hdr->nlmsg_len));
170
171 ATF_CHECK(e.error_str != NULL);
172 }
173
174 ATF_TC(snl_list_ifaces);
ATF_TC_HEAD(snl_list_ifaces,tc)175 ATF_TC_HEAD(snl_list_ifaces, tc)
176 {
177 atf_tc_set_md_var(tc, "descr", "Tests snl(3) listing interfaces");
178 atf_tc_set_md_var(tc, "require.kmods", "netlink");
179 }
180
181 struct nl_parsed_link {
182 uint32_t ifi_index;
183 uint32_t ifla_mtu;
184 char *ifla_ifname;
185 };
186
187 #define _IN(_field) offsetof(struct ifinfomsg, _field)
188 #define _OUT(_field) offsetof(struct nl_parsed_link, _field)
189 static struct snl_attr_parser ap_link[] = {
190 { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = snl_attr_get_string },
191 { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = snl_attr_get_uint32 },
192 };
193 static struct snl_field_parser fp_link[] = {
194 {.off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = snl_field_get_uint32 },
195 };
196 #undef _IN
197 #undef _OUT
198 SNL_DECLARE_PARSER(link_parser, struct ifinfomsg, fp_link, ap_link);
199
200
ATF_TC_BODY(snl_list_ifaces,tc)201 ATF_TC_BODY(snl_list_ifaces, tc)
202 {
203 struct snl_state ss;
204 struct snl_writer nw;
205
206 if (!snl_init(&ss, NETLINK_ROUTE))
207 atf_tc_fail("snl_init() failed");
208
209 snl_init_writer(&ss, &nw);
210
211 struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETLINK);
212 ATF_CHECK(hdr != NULL);
213 ATF_CHECK(snl_reserve_msg_object(&nw, struct ifinfomsg) != NULL);
214 ATF_CHECK(snl_finalize_msg(&nw) != NULL);
215 uint32_t seq_id = hdr->nlmsg_seq;
216
217 ATF_CHECK(snl_send_message(&ss, hdr));
218
219 struct snl_errmsg_data e = {};
220 int count = 0;
221
222 while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) {
223 count++;
224 }
225 ATF_REQUIRE(e.error == 0);
226
227 ATF_REQUIRE_MSG(count > 0, "Empty interface list");
228 }
229
ATF_TP_ADD_TCS(tp)230 ATF_TP_ADD_TCS(tp)
231 {
232 ATF_TP_ADD_TC(tp, snl_verify_core_parsers);
233 ATF_TP_ADD_TC(tp, snl_verify_route_parsers);
234 ATF_TP_ADD_TC(tp, snl_parse_errmsg_capped);
235 ATF_TP_ADD_TC(tp, snl_parse_errmsg_capped_extack);
236 ATF_TP_ADD_TC(tp, snl_parse_errmsg_uncapped_extack);
237 ATF_TP_ADD_TC(tp, snl_list_ifaces);
238
239 return (atf_no_error());
240 }
241