]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-netlink/test-netlink.c
Merge pull request #1676 from poettering/util-lib-2
[thirdparty/systemd.git] / src / libsystemd / sd-netlink / test-netlink.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <net/if.h>
23 #include <netinet/ether.h>
24
25 #include "sd-netlink.h"
26
27 #include "ether-addr-util.h"
28 #include "event-util.h"
29 #include "macro.h"
30 #include "missing.h"
31 #include "netlink-util.h"
32 #include "socket-util.h"
33 #include "string-util.h"
34 #include "util.h"
35
36 static void test_message_link_bridge(sd_netlink *rtnl) {
37 _cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
38 uint32_t cost;
39
40 assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0);
41 assert_se(sd_rtnl_message_link_set_family(message, PF_BRIDGE) >= 0);
42 assert_se(sd_netlink_message_open_container(message, IFLA_PROTINFO) >= 0);
43 assert_se(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0);
44 assert_se(sd_netlink_message_close_container(message) >= 0);
45
46 assert_se(sd_netlink_message_rewind(message) >= 0);
47
48 assert_se(sd_netlink_message_enter_container(message, IFLA_PROTINFO) >= 0);
49 assert_se(sd_netlink_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0);
50 assert_se(cost == 10);
51 assert_se(sd_netlink_message_exit_container(message) >= 0);
52 }
53
54 static void test_link_configure(sd_netlink *rtnl, int ifindex) {
55 _cleanup_netlink_message_unref_ sd_netlink_message *message = NULL;
56 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
57 char buffer[ETHER_ADDR_TO_STRING_MAX];
58 unsigned int mtu = 1450, mtu_out;
59 const char *name_out;
60 struct ether_addr mac_out;
61
62 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
63 assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
64 assert_se(sd_netlink_message_append_string(message, IFLA_IFNAME, name) >= 0);
65 assert_se(sd_netlink_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
66 assert_se(sd_netlink_message_append_u32(message, IFLA_MTU, mtu) >= 0);
67
68 assert_se(sd_netlink_call(rtnl, message, 0, NULL) == 1);
69 assert_se(sd_netlink_message_rewind(message) >= 0);
70
71 assert_se(sd_netlink_message_read_string(message, IFLA_IFNAME, &name_out) >= 0);
72 assert_se(streq(name, name_out));
73
74 assert_se(sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0);
75 assert_se(streq(mac, ether_addr_to_string(&mac_out, buffer)));
76
77 assert_se(sd_netlink_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0);
78 assert_se(mtu == mtu_out);
79 }
80
81 static void test_link_get(sd_netlink *rtnl, int ifindex) {
82 sd_netlink_message *m;
83 sd_netlink_message *r;
84 unsigned int mtu = 1500;
85 const char *str_data;
86 uint8_t u8_data;
87 uint32_t u32_data;
88 struct ether_addr eth_data;
89
90 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
91 assert_se(m);
92
93 /* u8 test cases */
94 assert_se(sd_netlink_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
95 assert_se(sd_netlink_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
96 assert_se(sd_netlink_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
97
98 /* u32 test cases */
99 assert_se(sd_netlink_message_append_u32(m, IFLA_MTU, mtu) >= 0);
100 assert_se(sd_netlink_message_append_u32(m, IFLA_GROUP, 0) >= 0);
101 assert_se(sd_netlink_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
102 assert_se(sd_netlink_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
103 assert_se(sd_netlink_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
104
105 assert_se(sd_netlink_call(rtnl, m, -1, &r) == 1);
106
107 assert_se(sd_netlink_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
108
109 assert_se(sd_netlink_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0);
110 assert_se(sd_netlink_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0);
111 assert_se(sd_netlink_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0);
112
113 assert_se(sd_netlink_message_read_u32(r, IFLA_MTU, &u32_data) == 0);
114 assert_se(sd_netlink_message_read_u32(r, IFLA_GROUP, &u32_data) == 0);
115 assert_se(sd_netlink_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0);
116 assert_se(sd_netlink_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0);
117 assert_se(sd_netlink_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0);
118
119 assert_se(sd_netlink_message_read_ether_addr(r, IFLA_ADDRESS, &eth_data) == 0);
120
121 assert_se((m = sd_netlink_message_unref(m)) == NULL);
122 assert_se((r = sd_netlink_message_unref(r)) == NULL);
123 }
124
125
126 static void test_address_get(sd_netlink *rtnl, int ifindex) {
127 sd_netlink_message *m;
128 sd_netlink_message *r;
129 struct in_addr in_data;
130 struct ifa_cacheinfo cache;
131 const char *label;
132
133 assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
134 assert_se(m);
135
136 assert_se(sd_netlink_call(rtnl, m, -1, &r) == 1);
137
138 assert_se(sd_netlink_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0);
139 assert_se(sd_netlink_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0);
140 assert_se(sd_netlink_message_read_string(r, IFA_LABEL, &label) == 0);
141 assert_se(sd_netlink_message_read_cache_info(r, IFA_CACHEINFO, &cache) == 0);
142
143 assert_se((m = sd_netlink_message_unref(m)) == NULL);
144 assert_se((r = sd_netlink_message_unref(r)) == NULL);
145
146 }
147
148 static void test_route(void) {
149 _cleanup_netlink_message_unref_ sd_netlink_message *req;
150 struct in_addr addr, addr_data;
151 uint32_t index = 2, u32_data;
152 int r;
153
154 r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC);
155 if (r < 0) {
156 log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");
157 return;
158 }
159
160 addr.s_addr = htonl(INADDR_LOOPBACK);
161
162 r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &addr);
163 if (r < 0) {
164 log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
165 return;
166 }
167
168 r = sd_netlink_message_append_u32(req, RTA_OIF, index);
169 if (r < 0) {
170 log_error_errno(r, "Could not append RTA_OIF attribute: %m");
171 return;
172 }
173
174 assert_se(sd_netlink_message_rewind(req) >= 0);
175
176 assert_se(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
177 assert_se(addr_data.s_addr == addr.s_addr);
178
179 assert_se(sd_netlink_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
180 assert_se(u32_data == index);
181
182 assert_se((req = sd_netlink_message_unref(req)) == NULL);
183 }
184
185 static void test_multiple(void) {
186 sd_netlink *rtnl1, *rtnl2;
187
188 assert_se(sd_netlink_open(&rtnl1) >= 0);
189 assert_se(sd_netlink_open(&rtnl2) >= 0);
190
191 rtnl1 = sd_netlink_unref(rtnl1);
192 rtnl2 = sd_netlink_unref(rtnl2);
193 }
194
195 static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
196 char *ifname = userdata;
197 const char *data;
198
199 assert_se(rtnl);
200 assert_se(m);
201
202 log_info("got link info about %s", ifname);
203 free(ifname);
204
205 assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0);
206 assert_se(streq(data, "lo"));
207
208 return 1;
209 }
210
211 static void test_event_loop(int ifindex) {
212 _cleanup_event_unref_ sd_event *event = NULL;
213 _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
214 _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
215 char *ifname;
216
217 ifname = strdup("lo2");
218 assert_se(ifname);
219
220 assert_se(sd_netlink_open(&rtnl) >= 0);
221 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
222
223 assert_se(sd_netlink_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
224
225 assert_se(sd_event_default(&event) >= 0);
226
227 assert_se(sd_netlink_attach_event(rtnl, event, 0) >= 0);
228
229 assert_se(sd_event_run(event, 0) >= 0);
230
231 assert_se(sd_netlink_detach_event(rtnl) >= 0);
232
233 assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
234 }
235
236 static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
237 int *counter = userdata;
238 int r;
239
240 (*counter) --;
241
242 r = sd_netlink_message_get_errno(m);
243
244 log_info_errno(r, "%d left in pipe. got reply: %m", *counter);
245
246 assert_se(r >= 0);
247
248 return 1;
249 }
250
251 static void test_async(int ifindex) {
252 _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
253 _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL, *r = NULL;
254 uint32_t serial;
255 char *ifname;
256
257 ifname = strdup("lo");
258 assert_se(ifname);
259
260 assert_se(sd_netlink_open(&rtnl) >= 0);
261
262 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
263
264 assert_se(sd_netlink_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
265
266 assert_se(sd_netlink_wait(rtnl, 0) >= 0);
267 assert_se(sd_netlink_process(rtnl, &r) >= 0);
268
269 assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
270 }
271
272 static void test_pipe(int ifindex) {
273 _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
274 _cleanup_netlink_message_unref_ sd_netlink_message *m1 = NULL, *m2 = NULL;
275 int counter = 0;
276
277 assert_se(sd_netlink_open(&rtnl) >= 0);
278
279 assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
280 assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
281
282 counter ++;
283 assert_se(sd_netlink_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
284
285 counter ++;
286 assert_se(sd_netlink_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
287
288 while (counter > 0) {
289 assert_se(sd_netlink_wait(rtnl, 0) >= 0);
290 assert_se(sd_netlink_process(rtnl, NULL) >= 0);
291 }
292
293 assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
294 }
295
296 static void test_container(void) {
297 _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
298 uint16_t u16_data;
299 uint32_t u32_data;
300 const char *string_data;
301
302 assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
303
304 assert_se(sd_netlink_message_open_container(m, IFLA_LINKINFO) >= 0);
305 assert_se(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0);
306 assert_se(sd_netlink_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
307 assert_se(sd_netlink_message_close_container(m) >= 0);
308 assert_se(sd_netlink_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
309 assert_se(sd_netlink_message_close_container(m) >= 0);
310 assert_se(sd_netlink_message_close_container(m) == -EINVAL);
311
312 assert_se(sd_netlink_message_rewind(m) >= 0);
313
314 assert_se(sd_netlink_message_enter_container(m, IFLA_LINKINFO) >= 0);
315 assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
316 assert_se(streq("vlan", string_data));
317
318 assert_se(sd_netlink_message_enter_container(m, IFLA_INFO_DATA) >= 0);
319 assert_se(sd_netlink_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0);
320 assert_se(sd_netlink_message_exit_container(m) >= 0);
321
322 assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
323 assert_se(streq("vlan", string_data));
324 assert_se(sd_netlink_message_exit_container(m) >= 0);
325
326 assert_se(sd_netlink_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0);
327
328 assert_se(sd_netlink_message_exit_container(m) == -EINVAL);
329 }
330
331 static void test_match(void) {
332 _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
333
334 assert_se(sd_netlink_open(&rtnl) >= 0);
335
336 assert_se(sd_netlink_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
337 assert_se(sd_netlink_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
338
339 assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
340 assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
341 assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
342
343 assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
344 }
345
346 static void test_get_addresses(sd_netlink *rtnl) {
347 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
348 sd_netlink_message *m;
349
350 assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0);
351
352 assert_se(sd_netlink_call(rtnl, req, 0, &reply) >= 0);
353
354 for (m = reply; m; m = sd_netlink_message_next(m)) {
355 uint16_t type;
356 unsigned char scope, flags;
357 int family, ifindex;
358
359 assert_se(sd_netlink_message_get_type(m, &type) >= 0);
360 assert_se(type == RTM_NEWADDR);
361
362 assert_se(sd_rtnl_message_addr_get_ifindex(m, &ifindex) >= 0);
363 assert_se(sd_rtnl_message_addr_get_family(m, &family) >= 0);
364 assert_se(sd_rtnl_message_addr_get_scope(m, &scope) >= 0);
365 assert_se(sd_rtnl_message_addr_get_flags(m, &flags) >= 0);
366
367 assert_se(ifindex > 0);
368 assert_se(family == AF_INET || family == AF_INET6);
369
370 log_info("got IPv%u address on ifindex %i", family == AF_INET ? 4: 6, ifindex);
371 }
372 }
373
374 static void test_message(void) {
375 _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
376
377 assert_se(rtnl_message_new_synthetic_error(-ETIMEDOUT, 1, &m) >= 0);
378 assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT);
379 }
380
381 int main(void) {
382 sd_netlink *rtnl;
383 sd_netlink_message *m;
384 sd_netlink_message *r;
385 const char *string_data;
386 int if_loopback;
387 uint16_t type;
388
389 test_message();
390
391 test_match();
392
393 test_multiple();
394
395 test_route();
396
397 test_container();
398
399 assert_se(sd_netlink_open(&rtnl) >= 0);
400 assert_se(rtnl);
401
402 if_loopback = (int) if_nametoindex("lo");
403 assert_se(if_loopback > 0);
404
405 test_async(if_loopback);
406
407 test_pipe(if_loopback);
408
409 test_event_loop(if_loopback);
410
411 test_link_configure(rtnl, if_loopback);
412
413 test_get_addresses(rtnl);
414
415 test_message_link_bridge(rtnl);
416
417 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
418 assert_se(m);
419
420 assert_se(sd_netlink_message_get_type(m, &type) >= 0);
421 assert_se(type == RTM_GETLINK);
422
423 assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
424
425 assert_se(sd_netlink_call(rtnl, m, 0, &r) == 1);
426 assert_se(sd_netlink_message_get_type(r, &type) >= 0);
427 assert_se(type == RTM_NEWLINK);
428
429 assert_se((r = sd_netlink_message_unref(r)) == NULL);
430
431 assert_se(sd_netlink_call(rtnl, m, -1, &r) == -EPERM);
432 assert_se((m = sd_netlink_message_unref(m)) == NULL);
433 assert_se((r = sd_netlink_message_unref(r)) == NULL);
434
435 test_link_get(rtnl, if_loopback);
436 test_address_get(rtnl, if_loopback);
437
438 assert_se((m = sd_netlink_message_unref(m)) == NULL);
439 assert_se((r = sd_netlink_message_unref(r)) == NULL);
440 assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
441
442 return EXIT_SUCCESS;
443 }