]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-netlink/test-netlink.c
cb11448e4cb90a8fc54826c044f71a8989b3a503
[thirdparty/systemd.git] / src / libsystemd / sd-netlink / test-netlink.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <linux/fou.h>
4 #include <linux/genetlink.h>
5 #include <linux/if_macsec.h>
6 #include <linux/l2tp.h>
7 #include <linux/nl80211.h>
8 #include <linux/unix_diag.h>
9 #include <net/ethernet.h>
10 #include <net/if.h>
11 #include <netinet/in.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14
15 #include "sd-event.h"
16 #include "sd-netlink.h"
17
18 #include "alloc-util.h"
19 #include "fd-util.h"
20 #include "missing_network.h"
21 #include "netlink-genl.h"
22 #include "netlink-internal.h"
23 #include "netlink-sock-diag.h"
24 #include "netlink-util.h"
25 #include "socket-util.h"
26 #include "stdio-util.h"
27 #include "strv.h"
28 #include "tests.h"
29 #include "time-util.h"
30
31 TEST(message_newlink_bridge) {
32 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
33 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
34 uint32_t cost;
35
36 ASSERT_OK(sd_netlink_open(&rtnl));
37
38 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1));
39 ASSERT_OK(sd_rtnl_message_link_set_family(message, AF_BRIDGE));
40 ASSERT_OK(sd_netlink_message_open_container(message, IFLA_PROTINFO));
41 ASSERT_OK(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10));
42 ASSERT_OK(sd_netlink_message_close_container(message));
43
44 ASSERT_OK(sd_netlink_message_rewind(message, rtnl));
45
46 ASSERT_OK(sd_netlink_message_enter_container(message, IFLA_PROTINFO));
47 ASSERT_OK(sd_netlink_message_read_u32(message, IFLA_BRPORT_COST, &cost));
48 ASSERT_EQ(cost, 10U);
49 ASSERT_OK(sd_netlink_message_exit_container(message));
50 }
51
52 TEST(message_getlink) {
53 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
54 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
55 int ifindex;
56 uint8_t u8_data;
57 uint16_t u16_data;
58 uint32_t u32_data;
59 const char *str_data;
60 struct ether_addr eth_data;
61
62 ASSERT_OK(sd_netlink_open(&rtnl));
63 ifindex = (int) if_nametoindex("lo");
64
65 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
66 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex));
67 ASSERT_OK_EQ(sd_netlink_call(rtnl, message, 0, &reply), 1);
68
69 /* u8 */
70 ASSERT_OK(sd_netlink_message_read_u8(reply, IFLA_CARRIER, &u8_data));
71 ASSERT_OK(sd_netlink_message_read_u8(reply, IFLA_OPERSTATE, &u8_data));
72 ASSERT_OK(sd_netlink_message_read_u8(reply, IFLA_LINKMODE, &u8_data));
73
74 /* u16 */
75 ASSERT_OK(sd_netlink_message_get_type(reply, &u16_data));
76 ASSERT_EQ(u16_data, RTM_NEWLINK);
77
78 /* u32 */
79 ASSERT_OK(sd_netlink_message_read_u32(reply, IFLA_MTU, &u32_data));
80 ASSERT_OK(sd_netlink_message_read_u32(reply, IFLA_GROUP, &u32_data));
81 ASSERT_OK(sd_netlink_message_read_u32(reply, IFLA_TXQLEN, &u32_data));
82 ASSERT_OK(sd_netlink_message_read_u32(reply, IFLA_NUM_TX_QUEUES, &u32_data));
83
84 /* string */
85 ASSERT_OK(sd_netlink_message_read_string(reply, IFLA_IFNAME, &str_data));
86
87 /* ether_addr */
88 ASSERT_OK(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &eth_data));
89 }
90
91 TEST(message_address) {
92 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
93 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
94 int ifindex;
95 struct in_addr in_data;
96 struct ifa_cacheinfo cache;
97 const char *label;
98 int r;
99
100 ASSERT_OK(sd_netlink_open(&rtnl));
101 ifindex = (int) if_nametoindex("lo");
102
103 ASSERT_OK(sd_rtnl_message_new_addr(rtnl, &message, RTM_GETADDR, ifindex, AF_INET));
104 ASSERT_OK(sd_netlink_message_set_request_dump(message, true));
105
106 ASSERT_OK(r = sd_netlink_call(rtnl, message, 0, &reply));
107
108 /* If the loopback device is down we won't get any results. */
109 if (r > 0) {
110 ASSERT_OK(sd_netlink_message_read_in_addr(reply, IFA_LOCAL, &in_data));
111 ASSERT_OK(sd_netlink_message_read_in_addr(reply, IFA_ADDRESS, &in_data));
112 ASSERT_OK(sd_netlink_message_read_string(reply, IFA_LABEL, &label));
113 ASSERT_OK(sd_netlink_message_read_cache_info(reply, IFA_CACHEINFO, &cache));
114 }
115 }
116
117 TEST(message_route) {
118 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
119 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
120 struct in_addr addr, addr_data;
121 uint32_t index = 2, u32_data;
122
123 ASSERT_OK(sd_netlink_open(&rtnl));
124
125 ASSERT_OK(sd_rtnl_message_new_route(rtnl, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC));
126
127 addr.s_addr = htobe32(INADDR_LOOPBACK);
128
129 ASSERT_OK(sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &addr));
130 ASSERT_OK(sd_netlink_message_append_u32(req, RTA_OIF, index));
131
132 ASSERT_OK(sd_netlink_message_rewind(req, rtnl));
133
134 ASSERT_OK(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data));
135 ASSERT_EQ(addr_data.s_addr, addr.s_addr);
136
137 ASSERT_OK(sd_netlink_message_read_u32(req, RTA_OIF, &u32_data));
138 ASSERT_EQ(u32_data, index);
139
140 ASSERT_NULL(req = sd_netlink_message_unref(req));
141 }
142
143 static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
144 const char *data;
145
146 ASSERT_NOT_NULL(rtnl);
147 ASSERT_NOT_NULL(m);
148
149 ASSERT_STREQ(userdata, "foo");
150
151 ASSERT_OK(sd_netlink_message_read_string(m, IFLA_IFNAME, &data));
152 ASSERT_STREQ(data, "lo");
153
154 log_info("%s: got link info about %s", __func__, data);
155 return 1;
156 }
157
158 TEST(netlink_event_loop) {
159 _cleanup_(sd_event_unrefp) sd_event *event = NULL;
160 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
161 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
162 _cleanup_free_ char *userdata = NULL;
163 int ifindex;
164
165 ASSERT_OK(sd_netlink_open(&rtnl));
166 ifindex = (int) if_nametoindex("lo");
167
168 ASSERT_NOT_NULL((userdata = strdup("foo")));
169
170 ASSERT_OK(sd_event_default(&event));
171 ASSERT_OK(sd_netlink_attach_event(rtnl, event, 0));
172
173 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex));
174 ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m, link_handler, NULL, userdata, 0, NULL));
175
176 ASSERT_OK(sd_event_run(event, 0));
177
178 ASSERT_OK(sd_netlink_detach_event(rtnl));
179 ASSERT_NULL(rtnl = sd_netlink_unref(rtnl));
180 }
181
182 static void test_async_destroy(void *userdata) {
183 }
184
185 TEST(netlink_call_async) {
186 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
187 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
188 _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
189 _cleanup_free_ char *userdata = NULL;
190 sd_netlink_destroy_t destroy_callback;
191 const char *description;
192 int ifindex;
193
194 ASSERT_OK(sd_netlink_open(&rtnl));
195 ifindex = (int) if_nametoindex("lo");
196
197 ASSERT_NOT_NULL((userdata = strdup("foo")));
198
199 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex));
200 ASSERT_OK(sd_netlink_call_async(rtnl, &slot, m, link_handler, test_async_destroy, userdata, 0, "hogehoge"));
201
202 ASSERT_PTR_EQ(sd_netlink_slot_get_netlink(slot), rtnl);
203
204 ASSERT_PTR_EQ(sd_netlink_slot_get_userdata(slot), userdata);
205 ASSERT_PTR_EQ(sd_netlink_slot_set_userdata(slot, NULL), userdata);
206 ASSERT_NULL(sd_netlink_slot_get_userdata(slot));
207 ASSERT_NULL(sd_netlink_slot_set_userdata(slot, userdata));
208 ASSERT_PTR_EQ(sd_netlink_slot_get_userdata(slot), userdata);
209
210 ASSERT_OK_EQ(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback), 1);
211 ASSERT_PTR_EQ(destroy_callback, test_async_destroy);
212 ASSERT_OK(sd_netlink_slot_set_destroy_callback(slot, NULL));
213 ASSERT_OK_ZERO(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback));
214 ASSERT_NULL(destroy_callback);
215 ASSERT_OK(sd_netlink_slot_set_destroy_callback(slot, test_async_destroy));
216 ASSERT_OK_EQ(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback), 1);
217 ASSERT_PTR_EQ(destroy_callback, test_async_destroy);
218
219 ASSERT_OK_ZERO(sd_netlink_slot_get_floating(slot));
220 ASSERT_OK_EQ(sd_netlink_slot_set_floating(slot, 1), 1);
221 ASSERT_OK_EQ(sd_netlink_slot_get_floating(slot), 1);
222
223 ASSERT_OK_EQ(sd_netlink_slot_get_description(slot, &description), 1);
224 ASSERT_STREQ(description, "hogehoge");
225 ASSERT_OK(sd_netlink_slot_set_description(slot, NULL));
226 ASSERT_OK_ZERO(sd_netlink_slot_get_description(slot, &description));
227 ASSERT_NULL(description);
228
229 ASSERT_OK(sd_netlink_wait(rtnl, 0));
230 ASSERT_OK(sd_netlink_process(rtnl, &reply));
231
232 ASSERT_NULL(rtnl = sd_netlink_unref(rtnl));
233 }
234
235 struct test_async_object {
236 unsigned n_ref;
237 char *ifname;
238 };
239
240 static struct test_async_object *test_async_object_free(struct test_async_object *t) {
241 ASSERT_NOT_NULL(t);
242
243 free(t->ifname);
244 return mfree(t);
245 }
246
247 DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(struct test_async_object, test_async_object, test_async_object_free);
248 DEFINE_TRIVIAL_CLEANUP_FUNC(struct test_async_object *, test_async_object_unref);
249
250 static int link_handler2(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
251 struct test_async_object *t = userdata;
252 const char *data;
253
254 ASSERT_NOT_NULL(rtnl);
255 ASSERT_NOT_NULL(m);
256 ASSERT_NOT_NULL(userdata);
257
258 log_info("%s: got link info about %s", __func__, t->ifname);
259
260 ASSERT_OK(sd_netlink_message_read_string(m, IFLA_IFNAME, &data));
261 ASSERT_STREQ(data, "lo");
262
263 return 1;
264 }
265
266 static void test_async_object_destroy(void *userdata) {
267 struct test_async_object *t = userdata;
268
269 ASSERT_NOT_NULL(userdata);
270
271 log_info("%s: n_ref=%u", __func__, t->n_ref);
272 test_async_object_unref(t);
273 }
274
275 TEST(async_destroy_callback) {
276 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
277 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
278 _cleanup_(test_async_object_unrefp) struct test_async_object *t = NULL;
279 _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
280 int ifindex;
281
282 ASSERT_OK(sd_netlink_open(&rtnl));
283 ifindex = (int) if_nametoindex("lo");
284
285 ASSERT_NOT_NULL((t = new(struct test_async_object, 1)));
286 *t = (struct test_async_object) {
287 .n_ref = 1,
288 };
289 ASSERT_NOT_NULL((t->ifname = strdup("lo")));
290
291 /* destroy callback is called after processing message */
292 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex));
293 ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0, NULL));
294
295 ASSERT_EQ(t->n_ref, 1U);
296 ASSERT_PTR_EQ(test_async_object_ref(t), t);
297 ASSERT_EQ(t->n_ref, 2U);
298
299 ASSERT_OK(sd_netlink_wait(rtnl, 0));
300 ASSERT_OK_EQ(sd_netlink_process(rtnl, &reply), 1);
301 ASSERT_EQ(t->n_ref, 1U);
302
303 ASSERT_NULL(sd_netlink_message_unref(m));
304
305 /* destroy callback is called when asynchronous call is cancelled, that is, slot is freed. */
306 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex));
307 ASSERT_OK(sd_netlink_call_async(rtnl, &slot, m, link_handler2, test_async_object_destroy, t, 0, NULL));
308
309 ASSERT_EQ(t->n_ref, 1U);
310 ASSERT_PTR_EQ(test_async_object_ref(t), t);
311 ASSERT_EQ(t->n_ref, 2U);
312
313 ASSERT_NULL(slot = sd_netlink_slot_unref(slot));
314 ASSERT_EQ(t->n_ref, 1U);
315
316 ASSERT_NULL(sd_netlink_message_unref(m));
317
318 /* destroy callback is also called by sd_netlink_unref() */
319 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex));
320 ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0, NULL));
321
322 ASSERT_EQ(t->n_ref, 1U);
323 ASSERT_PTR_EQ(test_async_object_ref(t), t);
324 ASSERT_EQ(t->n_ref, 2U);
325
326 ASSERT_NULL(rtnl = sd_netlink_unref(rtnl));
327 ASSERT_EQ(t->n_ref, 1U);
328 }
329
330 static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
331 int r, *counter = userdata;
332
333 (*counter)--;
334
335 ASSERT_OK(r = sd_netlink_message_get_errno(m));
336 log_info_errno(r, "%d left in pipe. got reply: %m", *counter);
337 return 1;
338 }
339
340 TEST(pipe) {
341 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
342 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL;
343 int ifindex, counter = 0;
344
345 ASSERT_OK(sd_netlink_open(&rtnl));
346 ifindex = (int) if_nametoindex("lo");
347
348 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex));
349 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex));
350
351 counter++;
352 ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m1, pipe_handler, NULL, &counter, 0, NULL));
353
354 counter++;
355 ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m2, pipe_handler, NULL, &counter, 0, NULL));
356
357 while (counter > 0) {
358 ASSERT_OK(sd_netlink_wait(rtnl, 0));
359 ASSERT_OK(sd_netlink_process(rtnl, NULL));
360 }
361
362 ASSERT_NULL(rtnl = sd_netlink_unref(rtnl));
363 }
364
365 TEST(message_container) {
366 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
367 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
368 uint16_t u16_data;
369 uint32_t u32_data;
370 const char *string_data;
371
372 ASSERT_OK(sd_netlink_open(&rtnl));
373
374 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0));
375
376 ASSERT_OK(sd_netlink_message_open_container(m, IFLA_LINKINFO));
377 ASSERT_OK(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "vlan"));
378 ASSERT_OK(sd_netlink_message_append_u16(m, IFLA_VLAN_ID, 100));
379 ASSERT_OK(sd_netlink_message_close_container(m));
380 ASSERT_OK(sd_netlink_message_close_container(m));
381
382 ASSERT_OK(sd_netlink_message_rewind(m, rtnl));
383
384 ASSERT_OK(sd_netlink_message_enter_container(m, IFLA_LINKINFO));
385 ASSERT_OK(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data));
386 ASSERT_STREQ("vlan", string_data);
387
388 ASSERT_OK(sd_netlink_message_enter_container(m, IFLA_INFO_DATA));
389 ASSERT_OK(sd_netlink_message_read_u16(m, IFLA_VLAN_ID, &u16_data));
390 ASSERT_OK(sd_netlink_message_exit_container(m));
391
392 ASSERT_OK(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data));
393 ASSERT_STREQ("vlan", string_data);
394 ASSERT_OK(sd_netlink_message_exit_container(m));
395
396 ASSERT_FAIL(sd_netlink_message_read_u32(m, IFLA_LINKINFO, &u32_data));
397 }
398
399 TEST(sd_netlink_add_match) {
400 _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *s1 = NULL, *s2 = NULL;
401 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
402
403 ASSERT_OK(sd_netlink_open(&rtnl));
404
405 ASSERT_OK(sd_netlink_add_match(rtnl, &s1, RTM_NEWLINK, link_handler, NULL, NULL, NULL));
406 ASSERT_OK(sd_netlink_add_match(rtnl, &s2, RTM_NEWLINK, link_handler, NULL, NULL, NULL));
407 ASSERT_OK(sd_netlink_add_match(rtnl, NULL, RTM_NEWLINK, link_handler, NULL, NULL, NULL));
408
409 ASSERT_NULL(s1 = sd_netlink_slot_unref(s1));
410 ASSERT_NULL(s2 = sd_netlink_slot_unref(s2));
411
412 ASSERT_NULL(rtnl = sd_netlink_unref(rtnl));
413 }
414
415 TEST(dump_addresses) {
416 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
417 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
418
419 ASSERT_OK(sd_netlink_open(&rtnl));
420
421 ASSERT_OK(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC));
422 ASSERT_OK(sd_netlink_message_set_request_dump(req, true));
423 ASSERT_OK(sd_netlink_call(rtnl, req, 0, &reply));
424
425 for (sd_netlink_message *m = reply; m; m = sd_netlink_message_next(m)) {
426 uint16_t type;
427 unsigned char scope;
428 int family, ifindex;
429 uint32_t flags;
430
431 ASSERT_OK(sd_netlink_message_get_type(m, &type));
432 ASSERT_EQ(type, RTM_NEWADDR);
433
434 ASSERT_OK(sd_rtnl_message_addr_get_ifindex(m, &ifindex));
435 ASSERT_OK(sd_rtnl_message_addr_get_family(m, &family));
436 ASSERT_OK(sd_rtnl_message_addr_get_scope(m, &scope));
437 ASSERT_OK(sd_netlink_message_read_u32(m, IFA_FLAGS, &flags));
438
439 ASSERT_GT(ifindex, 0);
440 ASSERT_TRUE(IN_SET(family, AF_INET, AF_INET6));
441
442 log_info("got IPv%i address on ifindex %i", family == AF_INET ? 4 : 6, ifindex);
443 }
444 }
445
446 TEST(sd_netlink_message_get_errno) {
447 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
448 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
449
450 ASSERT_OK(sd_netlink_open(&rtnl));
451
452 ASSERT_OK(message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m));
453 ASSERT_ERROR(sd_netlink_message_get_errno(m), ETIMEDOUT);
454 }
455
456 TEST(message_array) {
457 _cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
458 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
459
460 ASSERT_OK(sd_genl_socket_open(&genl));
461 ASSERT_OK(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m));
462
463 ASSERT_OK(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS));
464 for (unsigned i = 0; i < 10; i++) {
465 char name[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
466 uint32_t id = i + 1000;
467
468 xsprintf(name, "hoge%" PRIu32, id);
469 ASSERT_OK(sd_netlink_message_open_array(m, i + 1));
470 ASSERT_OK(sd_netlink_message_append_u32(m, CTRL_ATTR_MCAST_GRP_ID, id));
471 ASSERT_OK(sd_netlink_message_append_string(m, CTRL_ATTR_MCAST_GRP_NAME, name));
472 ASSERT_OK(sd_netlink_message_close_container(m));
473 }
474 ASSERT_OK(sd_netlink_message_close_container(m));
475
476 message_seal(m);
477 ASSERT_OK(sd_netlink_message_rewind(m, genl));
478
479 ASSERT_OK(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS));
480 for (unsigned i = 0; i < 10; i++) {
481 char expected[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
482 const char *name;
483 uint32_t id;
484
485 ASSERT_OK(sd_netlink_message_enter_array(m, i + 1));
486 ASSERT_OK(sd_netlink_message_read_u32(m, CTRL_ATTR_MCAST_GRP_ID, &id));
487 ASSERT_OK(sd_netlink_message_read_string(m, CTRL_ATTR_MCAST_GRP_NAME, &name));
488 ASSERT_OK(sd_netlink_message_exit_container(m));
489
490 ASSERT_EQ(id, i + 1000);
491 xsprintf(expected, "hoge%" PRIu32, id);
492 ASSERT_STREQ(name, expected);
493 }
494 ASSERT_OK(sd_netlink_message_exit_container(m));
495 }
496
497 TEST(message_strv) {
498 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
499 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
500 _cleanup_strv_free_ char **names_in = NULL, **names_out;
501 const char *p;
502
503 ASSERT_OK(sd_netlink_open(&rtnl));
504
505 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINKPROP, 1));
506
507 for (unsigned i = 0; i < 10; i++) {
508 char name[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
509
510 xsprintf(name, "hoge%" PRIu32, i + 1000);
511 ASSERT_OK(strv_extend(&names_in, name));
512 }
513
514 ASSERT_OK(sd_netlink_message_open_container(m, IFLA_PROP_LIST));
515 ASSERT_OK(sd_netlink_message_append_strv(m, IFLA_ALT_IFNAME, (const char**) names_in));
516 ASSERT_OK(sd_netlink_message_close_container(m));
517
518 message_seal(m);
519 ASSERT_OK(sd_netlink_message_rewind(m, rtnl));
520
521 ASSERT_OK(sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &names_out));
522 ASSERT_TRUE(strv_equal(names_in, names_out));
523
524 ASSERT_OK(sd_netlink_message_enter_container(m, IFLA_PROP_LIST));
525 ASSERT_OK(sd_netlink_message_read_string(m, IFLA_ALT_IFNAME, &p));
526 ASSERT_STREQ(p, "hoge1009");
527 ASSERT_OK(sd_netlink_message_exit_container(m));
528 }
529
530 static int genl_ctrl_match_callback(sd_netlink *genl, sd_netlink_message *m, void *userdata) {
531 const char *name;
532 uint16_t id;
533 uint8_t cmd;
534
535 ASSERT_NOT_NULL(genl);
536 ASSERT_NOT_NULL(m);
537
538 ASSERT_OK(sd_genl_message_get_family_name(genl, m, &name));
539 ASSERT_STREQ(name, CTRL_GENL_NAME);
540
541 ASSERT_OK(sd_genl_message_get_command(genl, m, &cmd));
542
543 switch (cmd) {
544 case CTRL_CMD_NEWFAMILY:
545 case CTRL_CMD_DELFAMILY:
546 ASSERT_OK(sd_netlink_message_read_string(m, CTRL_ATTR_FAMILY_NAME, &name));
547 ASSERT_OK(sd_netlink_message_read_u16(m, CTRL_ATTR_FAMILY_ID, &id));
548 log_debug("%s: %s (id=%"PRIu16") family is %s.",
549 __func__, name, id, cmd == CTRL_CMD_NEWFAMILY ? "added" : "removed");
550 break;
551 case CTRL_CMD_NEWMCAST_GRP:
552 case CTRL_CMD_DELMCAST_GRP:
553 ASSERT_OK(sd_netlink_message_read_string(m, CTRL_ATTR_FAMILY_NAME, &name));
554 ASSERT_OK(sd_netlink_message_read_u16(m, CTRL_ATTR_FAMILY_ID, &id));
555 log_debug("%s: multicast group for %s (id=%"PRIu16") family is %s.",
556 __func__, name, id, cmd == CTRL_CMD_NEWMCAST_GRP ? "added" : "removed");
557 break;
558 default:
559 log_debug("%s: received nlctrl message with unknown command '%"PRIu8"'.", __func__, cmd);
560 }
561
562 return 0;
563 }
564
565 TEST(genl) {
566 _cleanup_(sd_event_unrefp) sd_event *event = NULL;
567 _cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
568 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
569 const char *name;
570 uint8_t cmd;
571 int r;
572
573 ASSERT_OK(sd_genl_socket_open(&genl));
574 ASSERT_OK(sd_event_default(&event));
575 ASSERT_OK(sd_netlink_attach_event(genl, event, 0));
576
577 ASSERT_OK(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m));
578 ASSERT_OK(sd_genl_message_get_family_name(genl, m, &name));
579 ASSERT_STREQ(name, CTRL_GENL_NAME);
580 ASSERT_OK(sd_genl_message_get_command(genl, m, &cmd));
581 ASSERT_EQ(cmd, CTRL_CMD_GETFAMILY);
582
583 ASSERT_OK(sd_genl_add_match(genl, NULL, CTRL_GENL_NAME, "notify", 0, genl_ctrl_match_callback, NULL, NULL, "genl-ctrl-notify"));
584
585 ASSERT_NULL(m = sd_netlink_message_unref(m));
586 ASSERT_FAIL(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m));
587 ASSERT_ERROR(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m), EOPNOTSUPP);
588
589 /* These families may not be supported by kernel. Hence, ignore results. */
590 (void) sd_genl_message_new(genl, FOU_GENL_NAME, 0, &m);
591 ASSERT_NULL(m = sd_netlink_message_unref(m));
592 (void) sd_genl_message_new(genl, L2TP_GENL_NAME, 0, &m);
593 ASSERT_NULL(m = sd_netlink_message_unref(m));
594 (void) sd_genl_message_new(genl, MACSEC_GENL_NAME, 0, &m);
595 ASSERT_NULL(m = sd_netlink_message_unref(m));
596 (void) sd_genl_message_new(genl, NL80211_GENL_NAME, 0, &m);
597 ASSERT_NULL(m = sd_netlink_message_unref(m));
598 (void) sd_genl_message_new(genl, NETLBL_NLTYPE_UNLABELED_NAME, 0, &m);
599
600 for (;;) {
601 ASSERT_OK(r = sd_event_run(event, 500 * USEC_PER_MSEC));
602 if (r == 0)
603 return;
604 }
605 }
606
607 static void remove_dummy_interfacep(int *ifindex) {
608 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
609 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
610
611 if (!ifindex || *ifindex <= 0)
612 return;
613
614 ASSERT_OK(sd_netlink_open(&rtnl));
615
616 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_DELLINK, *ifindex));
617 ASSERT_OK_EQ(sd_netlink_call(rtnl, message, 0, NULL), 1);
618 }
619
620 TEST(rtnl_set_link_name) {
621 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
622 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
623 _cleanup_(remove_dummy_interfacep) int ifindex = 0;
624 _cleanup_strv_free_ char **alternative_names = NULL;
625 int r;
626
627 if (geteuid() != 0)
628 return (void) log_tests_skipped("not root");
629
630 ASSERT_OK(sd_netlink_open(&rtnl));
631
632 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 0));
633 ASSERT_OK(sd_netlink_message_append_string(message, IFLA_IFNAME, "test-netlink"));
634 ASSERT_OK(sd_netlink_message_open_container(message, IFLA_LINKINFO));
635 ASSERT_OK(sd_netlink_message_append_string(message, IFLA_INFO_KIND, "dummy"));
636 r = sd_netlink_call(rtnl, message, 0, &reply);
637 if (r == -EPERM)
638 return (void) log_tests_skipped("missing required capabilities");
639 if (r == -EOPNOTSUPP)
640 return (void) log_tests_skipped("dummy network interface is not supported");
641 ASSERT_OK(r);
642
643 ASSERT_NULL(message = sd_netlink_message_unref(message));
644 ASSERT_NULL(reply = sd_netlink_message_unref(reply));
645
646 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, 0));
647 ASSERT_OK(sd_netlink_message_append_string(message, IFLA_IFNAME, "test-netlink"));
648 ASSERT_OK_EQ(sd_netlink_call(rtnl, message, 0, &reply), 1);
649
650 ASSERT_OK(sd_rtnl_message_link_get_ifindex(reply, &ifindex));
651 ASSERT_GT(ifindex, 0);
652
653 /* Test that the new name (which is currently an alternative name) is
654 * restored as an alternative name on error. Create an error by using
655 * an invalid device name, namely one that exceeds IFNAMSIZ
656 * (alternative names can exceed IFNAMSIZ, but not regular names). */
657 r = rtnl_set_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename", "test-shortname"));
658 if (r == -EPERM)
659 return (void) log_tests_skipped("missing required capabilities");
660 if (r == -EOPNOTSUPP)
661 return (void) log_tests_skipped("alternative name is not supported");
662 ASSERT_OK(r);
663
664 ASSERT_OK(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names));
665 ASSERT_TRUE(strv_contains(alternative_names, "testlongalternativename"));
666 ASSERT_TRUE(strv_contains(alternative_names, "test-shortname"));
667
668 ASSERT_ERROR(rtnl_set_link_name(&rtnl, ifindex, "testlongalternativename", NULL), EINVAL);
669 ASSERT_OK(rtnl_set_link_name(&rtnl, ifindex, "test-shortname", STRV_MAKE("testlongalternativename", "test-shortname", "test-additional-name")));
670
671 ASSERT_NULL(alternative_names = strv_free(alternative_names));
672 ASSERT_OK(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names));
673 ASSERT_TRUE(strv_contains(alternative_names, "testlongalternativename"));
674 ASSERT_TRUE(strv_contains(alternative_names, "test-additional-name"));
675 ASSERT_FALSE(strv_contains(alternative_names, "test-shortname"));
676
677 ASSERT_OK(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")));
678
679 ASSERT_NULL(alternative_names = strv_free(alternative_names));
680 ASSERT_OK_EQ(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names), ifindex);
681 ASSERT_FALSE(strv_contains(alternative_names, "testlongalternativename"));
682 ASSERT_TRUE(strv_contains(alternative_names, "test-additional-name"));
683 ASSERT_FALSE(strv_contains(alternative_names, "test-shortname"));
684
685 _cleanup_free_ char *resolved = NULL;
686 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", NULL), ifindex);
687 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", &resolved), ifindex);
688 ASSERT_STREQ(resolved, "test-shortname");
689 ASSERT_NULL(resolved = mfree(resolved));
690
691 ASSERT_OK(rtnl_rename_link(&rtnl, "test-shortname", "test-shortname"));
692 ASSERT_OK(rtnl_rename_link(&rtnl, "test-shortname", "test-shortname2"));
693 ASSERT_OK(rtnl_rename_link(NULL, "test-shortname2", "test-shortname3"));
694
695 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", NULL), ifindex);
696 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", &resolved), ifindex);
697 ASSERT_STREQ(resolved, "test-shortname3");
698 ASSERT_NULL(resolved = mfree(resolved));
699
700 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-shortname3", NULL), ifindex);
701 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-shortname3", &resolved), ifindex);
702 ASSERT_STREQ(resolved, "test-shortname3");
703 ASSERT_NULL(resolved = mfree(resolved));
704 }
705
706 TEST(sock_diag_unix) {
707 _cleanup_(sd_netlink_unrefp) sd_netlink *nl = NULL;
708 int r;
709
710 ASSERT_OK(sd_sock_diag_socket_open(&nl));
711
712 _cleanup_close_ int unix_fd = ASSERT_FD(socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0));
713 ASSERT_OK(socket_autobind(unix_fd, /* ret_name= */ NULL));
714 ASSERT_OK_ERRNO(listen(unix_fd, 123));
715
716 struct stat st;
717 ASSERT_OK_ERRNO(fstat(unix_fd, &st));
718
719 uint64_t cookie;
720 ASSERT_OK(socket_get_cookie(unix_fd, &cookie));
721
722 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
723 ASSERT_OK(sd_sock_diag_message_new_unix(nl, &message, st.st_ino, cookie, UDIAG_SHOW_RQLEN));
724
725 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *reply = NULL;
726 r = sd_netlink_call(nl, message, /* timeout= */ 0, &reply);
727 if (r == -ENOENT)
728 return (void) log_tests_skipped("CONFIG_UNIX_DIAG disabled");
729 ASSERT_OK(r);
730 }
731
732 DEFINE_TEST_MAIN(LOG_DEBUG);