]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-netlink/test-netlink.c
man/systemd-sysext: list ephemeral/ephemeral-import in the list of options
[thirdparty/systemd.git] / src / libsystemd / sd-netlink / test-netlink.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
1c4baffc 2
e1578f60 3#include <linux/fou.h>
9104009e 4#include <linux/genetlink.h>
e1578f60
YW
5#include <linux/if_macsec.h>
6#include <linux/l2tp.h>
7#include <linux/nl80211.h>
89e546e9 8#include <linux/unix_diag.h>
5cdf13c7 9#include <net/ethernet.h>
1cf40697 10#include <net/if.h>
1cf40697 11#include <netinet/in.h>
89e546e9 12#include <sys/stat.h>
b338a8bb 13#include <unistd.h>
1c4baffc 14
5cdf13c7 15#include "sd-event.h"
1c4baffc 16#include "sd-netlink.h"
07630cea 17
0d0f02cd 18#include "alloc-util.h"
89e546e9 19#include "fd-util.h"
5cdf13c7 20#include "missing_network.h"
56fdc16d 21#include "netlink-genl.h"
409856d3 22#include "netlink-internal.h"
89e546e9 23#include "netlink-sock-diag.h"
b338a8bb 24#include "netlink-util.h"
07630cea 25#include "socket-util.h"
9104009e 26#include "stdio-util.h"
d08d92d5 27#include "strv.h"
0c45a60f 28#include "tests.h"
5cdf13c7 29#include "time-util.h"
1c4baffc 30
eafff21d
YW
31TEST(message_newlink_bridge) {
32 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
4afd3348 33 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
1c4baffc
TG
34 uint32_t cost;
35
3841288e 36 ASSERT_OK(sd_netlink_open(&rtnl));
0c45a60f 37
3841288e
YW
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));
1c4baffc 43
3841288e 44 ASSERT_OK(sd_netlink_message_rewind(message, rtnl));
1c4baffc 45
3841288e
YW
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));
1c4baffc
TG
50}
51
eafff21d
YW
52TEST(message_getlink) {
53 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
d7418b3b 54 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
eafff21d 55 int ifindex;
1c4baffc 56 uint8_t u8_data;
eafff21d 57 uint16_t u16_data;
1c4baffc 58 uint32_t u32_data;
eafff21d 59 const char *str_data;
1c4baffc
TG
60 struct ether_addr eth_data;
61
3841288e 62 ASSERT_OK(sd_netlink_open(&rtnl));
eafff21d 63 ifindex = (int) if_nametoindex("lo");
0c45a60f 64
eafff21d 65 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
3841288e
YW
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);
1c4baffc 68
eafff21d 69 /* u8 */
3841288e
YW
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));
1c4baffc 73
eafff21d 74 /* u16 */
3841288e
YW
75 ASSERT_OK(sd_netlink_message_get_type(reply, &u16_data));
76 ASSERT_EQ(u16_data, RTM_NEWLINK);
1c4baffc 77
eafff21d 78 /* u32 */
3841288e
YW
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));
1c4baffc 83
eafff21d 84 /* string */
3841288e 85 ASSERT_OK(sd_netlink_message_read_string(reply, IFLA_IFNAME, &str_data));
1c4baffc 86
eafff21d 87 /* ether_addr */
3841288e 88 ASSERT_OK(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &eth_data));
1c4baffc
TG
89}
90
eafff21d
YW
91TEST(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;
1c4baffc
TG
95 struct in_addr in_data;
96 struct ifa_cacheinfo cache;
97 const char *label;
d098b8df 98 int r;
1c4baffc 99
8df80dfb 100 ASSERT_OK(sd_netlink_open(&rtnl));
eafff21d 101 ifindex = (int) if_nametoindex("lo");
0c45a60f 102
8df80dfb
YW
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));
1c4baffc 105
d9000d70 106 ASSERT_OK(r = sd_netlink_call(rtnl, message, 0, &reply));
d098b8df
DDM
107
108 /* If the loopback device is down we won't get any results. */
109 if (r > 0) {
3841288e
YW
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));
d098b8df 114 }
1c4baffc
TG
115}
116
eafff21d
YW
117TEST(message_route) {
118 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
b9c54c46 119 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1c4baffc
TG
120 struct in_addr addr, addr_data;
121 uint32_t index = 2, u32_data;
1c4baffc 122
8df80dfb 123 ASSERT_OK(sd_netlink_open(&rtnl));
0c45a60f 124
8df80dfb 125 ASSERT_OK(sd_rtnl_message_new_route(rtnl, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC));
1c4baffc 126
d7a0f1f4 127 addr.s_addr = htobe32(INADDR_LOOPBACK);
1c4baffc 128
8df80dfb
YW
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));
1c4baffc 131
8df80dfb 132 ASSERT_OK(sd_netlink_message_rewind(req, rtnl));
1c4baffc 133
8df80dfb 134 ASSERT_OK(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data));
3841288e 135 ASSERT_EQ(addr_data.s_addr, addr.s_addr);
1c4baffc 136
8df80dfb 137 ASSERT_OK(sd_netlink_message_read_u32(req, RTA_OIF, &u32_data));
3841288e 138 ASSERT_EQ(u32_data, index);
1c4baffc 139
d9000d70 140 ASSERT_NULL(req = sd_netlink_message_unref(req));
1c4baffc
TG
141}
142
1c4baffc 143static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
1c4baffc
TG
144 const char *data;
145
3841288e
YW
146 ASSERT_NOT_NULL(rtnl);
147 ASSERT_NOT_NULL(m);
1c4baffc 148
3841288e 149 ASSERT_STREQ(userdata, "foo");
1c4baffc 150
3841288e
YW
151 ASSERT_OK(sd_netlink_message_read_string(m, IFLA_IFNAME, &data));
152 ASSERT_STREQ(data, "lo");
1c4baffc 153
eafff21d 154 log_info("%s: got link info about %s", __func__, data);
1c4baffc
TG
155 return 1;
156}
157
eafff21d 158TEST(netlink_event_loop) {
4afd3348
LP
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;
eafff21d
YW
162 _cleanup_free_ char *userdata = NULL;
163 int ifindex;
1c4baffc 164
3841288e 165 ASSERT_OK(sd_netlink_open(&rtnl));
eafff21d 166 ifindex = (int) if_nametoindex("lo");
1c4baffc 167
3841288e 168 ASSERT_NOT_NULL((userdata = strdup("foo")));
1c4baffc 169
3841288e
YW
170 ASSERT_OK(sd_event_default(&event));
171 ASSERT_OK(sd_netlink_attach_event(rtnl, event, 0));
1c4baffc 172
3841288e
YW
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));
eafff21d 175
3841288e 176 ASSERT_OK(sd_event_run(event, 0));
1c4baffc 177
3841288e 178 ASSERT_OK(sd_netlink_detach_event(rtnl));
d9000d70 179 ASSERT_NULL(rtnl = sd_netlink_unref(rtnl));
1c4baffc
TG
180}
181
c940a231
YW
182static void test_async_destroy(void *userdata) {
183}
184
eafff21d 185TEST(netlink_call_async) {
0d0f02cd 186 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
eafff21d 187 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
ee38400b 188 _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
eafff21d 189 _cleanup_free_ char *userdata = NULL;
c940a231
YW
190 sd_netlink_destroy_t destroy_callback;
191 const char *description;
eafff21d 192 int ifindex;
1c4baffc 193
3841288e 194 ASSERT_OK(sd_netlink_open(&rtnl));
eafff21d 195 ifindex = (int) if_nametoindex("lo");
1c4baffc 196
3841288e 197 ASSERT_NOT_NULL((userdata = strdup("foo")));
1c4baffc 198
3841288e
YW
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"));
c940a231 201
3841288e 202 ASSERT_PTR_EQ(sd_netlink_slot_get_netlink(slot), rtnl);
0d0f02cd 203
3841288e
YW
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);
915375ed 209
3841288e
YW
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);
eafff21d 218
3841288e
YW
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);
eafff21d 222
3841288e
YW
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);
915375ed 228
3841288e
YW
229 ASSERT_OK(sd_netlink_wait(rtnl, 0));
230 ASSERT_OK(sd_netlink_process(rtnl, &reply));
915375ed 231
d9000d70 232 ASSERT_NULL(rtnl = sd_netlink_unref(rtnl));
915375ed
YW
233}
234
0d0f02cd
YW
235struct test_async_object {
236 unsigned n_ref;
237 char *ifname;
238};
239
240static struct test_async_object *test_async_object_free(struct test_async_object *t) {
3841288e 241 ASSERT_NOT_NULL(t);
0d0f02cd
YW
242
243 free(t->ifname);
244 return mfree(t);
245}
246
247DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(struct test_async_object, test_async_object, test_async_object_free);
248DEFINE_TRIVIAL_CLEANUP_FUNC(struct test_async_object *, test_async_object_unref);
249
250static int link_handler2(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
251 struct test_async_object *t = userdata;
252 const char *data;
253
3841288e
YW
254 ASSERT_NOT_NULL(rtnl);
255 ASSERT_NOT_NULL(m);
256 ASSERT_NOT_NULL(userdata);
0d0f02cd
YW
257
258 log_info("%s: got link info about %s", __func__, t->ifname);
259
3841288e
YW
260 ASSERT_OK(sd_netlink_message_read_string(m, IFLA_IFNAME, &data));
261 ASSERT_STREQ(data, "lo");
1c4baffc
TG
262
263 return 1;
264}
265
0d0f02cd
YW
266static void test_async_object_destroy(void *userdata) {
267 struct test_async_object *t = userdata;
268
3841288e 269 ASSERT_NOT_NULL(userdata);
0d0f02cd
YW
270
271 log_info("%s: n_ref=%u", __func__, t->n_ref);
272 test_async_object_unref(t);
273}
274
eafff21d 275TEST(async_destroy_callback) {
4afd3348 276 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
eafff21d 277 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
0d0f02cd 278 _cleanup_(test_async_object_unrefp) struct test_async_object *t = NULL;
ee38400b 279 _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
eafff21d 280 int ifindex;
1c4baffc 281
3841288e 282 ASSERT_OK(sd_netlink_open(&rtnl));
eafff21d 283 ifindex = (int) if_nametoindex("lo");
0c45a60f 284
3841288e 285 ASSERT_NOT_NULL((t = new(struct test_async_object, 1)));
0d0f02cd
YW
286 *t = (struct test_async_object) {
287 .n_ref = 1,
0d0f02cd 288 };
3841288e 289 ASSERT_NOT_NULL((t->ifname = strdup("lo")));
1c4baffc 290
0d0f02cd 291 /* destroy callback is called after processing message */
3841288e
YW
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));
1c4baffc 294
3841288e
YW
295 ASSERT_EQ(t->n_ref, 1U);
296 ASSERT_PTR_EQ(test_async_object_ref(t), t);
297 ASSERT_EQ(t->n_ref, 2U);
1c4baffc 298
3841288e
YW
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);
0d0f02cd 302
3841288e 303 ASSERT_NULL(sd_netlink_message_unref(m));
0d0f02cd 304
ee38400b 305 /* destroy callback is called when asynchronous call is cancelled, that is, slot is freed. */
3841288e
YW
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));
0d0f02cd 308
3841288e
YW
309 ASSERT_EQ(t->n_ref, 1U);
310 ASSERT_PTR_EQ(test_async_object_ref(t), t);
311 ASSERT_EQ(t->n_ref, 2U);
0d0f02cd 312
d9000d70 313 ASSERT_NULL(slot = sd_netlink_slot_unref(slot));
3841288e 314 ASSERT_EQ(t->n_ref, 1U);
0d0f02cd 315
3841288e 316 ASSERT_NULL(sd_netlink_message_unref(m));
0d0f02cd
YW
317
318 /* destroy callback is also called by sd_netlink_unref() */
3841288e
YW
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));
0d0f02cd 321
3841288e
YW
322 ASSERT_EQ(t->n_ref, 1U);
323 ASSERT_PTR_EQ(test_async_object_ref(t), t);
324 ASSERT_EQ(t->n_ref, 2U);
1c4baffc 325
d9000d70 326 ASSERT_NULL(rtnl = sd_netlink_unref(rtnl));
3841288e 327 ASSERT_EQ(t->n_ref, 1U);
0d0f02cd
YW
328}
329
330static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
3841288e 331 int r, *counter = userdata;
0d0f02cd
YW
332
333 (*counter)--;
334
d9000d70 335 ASSERT_OK(r = sd_netlink_message_get_errno(m));
0d0f02cd 336 log_info_errno(r, "%d left in pipe. got reply: %m", *counter);
0d0f02cd 337 return 1;
1c4baffc
TG
338}
339
eafff21d 340TEST(pipe) {
4afd3348
LP
341 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
342 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL;
eafff21d 343 int ifindex, counter = 0;
0c45a60f 344
3841288e 345 ASSERT_OK(sd_netlink_open(&rtnl));
eafff21d 346 ifindex = (int) if_nametoindex("lo");
1c4baffc 347
3841288e
YW
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));
1c4baffc 350
313cefa1 351 counter++;
3841288e 352 ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m1, pipe_handler, NULL, &counter, 0, NULL));
1c4baffc 353
313cefa1 354 counter++;
3841288e 355 ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m2, pipe_handler, NULL, &counter, 0, NULL));
1c4baffc
TG
356
357 while (counter > 0) {
3841288e
YW
358 ASSERT_OK(sd_netlink_wait(rtnl, 0));
359 ASSERT_OK(sd_netlink_process(rtnl, NULL));
1c4baffc
TG
360 }
361
d9000d70 362 ASSERT_NULL(rtnl = sd_netlink_unref(rtnl));
1c4baffc
TG
363}
364
eafff21d
YW
365TEST(message_container) {
366 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
4afd3348 367 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
1c4baffc
TG
368 uint16_t u16_data;
369 uint32_t u32_data;
370 const char *string_data;
371
3841288e 372 ASSERT_OK(sd_netlink_open(&rtnl));
0c45a60f 373
3841288e 374 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0));
1c4baffc 375
3841288e
YW
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));
1c4baffc 381
3841288e 382 ASSERT_OK(sd_netlink_message_rewind(m, rtnl));
1c4baffc 383
3841288e
YW
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);
1c4baffc 387
3841288e
YW
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));
1c4baffc 391
3841288e
YW
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));
1c4baffc 395
3841288e 396 ASSERT_FAIL(sd_netlink_message_read_u32(m, IFLA_LINKINFO, &u32_data));
1c4baffc
TG
397}
398
eafff21d 399TEST(sd_netlink_add_match) {
ee38400b 400 _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *s1 = NULL, *s2 = NULL;
4afd3348 401 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
1c4baffc 402
3841288e 403 ASSERT_OK(sd_netlink_open(&rtnl));
1c4baffc 404
3841288e
YW
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));
1c4baffc 408
d9000d70
YW
409 ASSERT_NULL(s1 = sd_netlink_slot_unref(s1));
410 ASSERT_NULL(s2 = sd_netlink_slot_unref(s2));
1c4baffc 411
d9000d70 412 ASSERT_NULL(rtnl = sd_netlink_unref(rtnl));
1c4baffc
TG
413}
414
eafff21d
YW
415TEST(dump_addresses) {
416 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
4afd3348 417 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
1c4baffc 418
3841288e 419 ASSERT_OK(sd_netlink_open(&rtnl));
0c45a60f 420
3841288e
YW
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));
1c4baffc 424
eafff21d 425 for (sd_netlink_message *m = reply; m; m = sd_netlink_message_next(m)) {
1c4baffc 426 uint16_t type;
d50cfa98 427 unsigned char scope;
1c4baffc 428 int family, ifindex;
d50cfa98 429 uint32_t flags;
1c4baffc 430
3841288e
YW
431 ASSERT_OK(sd_netlink_message_get_type(m, &type));
432 ASSERT_EQ(type, RTM_NEWADDR);
1c4baffc 433
3841288e
YW
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));
d50cfa98 437 ASSERT_OK(sd_netlink_message_read_u32(m, IFA_FLAGS, &flags));
1c4baffc 438
3841288e
YW
439 ASSERT_GT(ifindex, 0);
440 ASSERT_TRUE(IN_SET(family, AF_INET, AF_INET6));
1c4baffc 441
c0f86d66 442 log_info("got IPv%i address on ifindex %i", family == AF_INET ? 4 : 6, ifindex);
1c4baffc
TG
443 }
444}
445
eafff21d
YW
446TEST(sd_netlink_message_get_errno) {
447 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
4afd3348 448 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
1c4baffc 449
3841288e 450 ASSERT_OK(sd_netlink_open(&rtnl));
0c45a60f 451
3841288e
YW
452 ASSERT_OK(message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m));
453 ASSERT_ERROR(sd_netlink_message_get_errno(m), ETIMEDOUT);
1c4baffc
TG
454}
455
eafff21d 456TEST(message_array) {
9104009e
YW
457 _cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
458 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
459
3841288e
YW
460 ASSERT_OK(sd_genl_socket_open(&genl));
461 ASSERT_OK(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m));
9104009e 462
3841288e 463 ASSERT_OK(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS));
9104009e
YW
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);
3841288e
YW
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));
9104009e 473 }
3841288e 474 ASSERT_OK(sd_netlink_message_close_container(m));
9104009e 475
409856d3 476 message_seal(m);
3841288e 477 ASSERT_OK(sd_netlink_message_rewind(m, genl));
9104009e 478
3841288e 479 ASSERT_OK(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS));
9104009e
YW
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
3841288e
YW
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));
9104009e 489
3841288e 490 ASSERT_EQ(id, i + 1000);
9104009e 491 xsprintf(expected, "hoge%" PRIu32, id);
3841288e 492 ASSERT_STREQ(name, expected);
9104009e 493 }
3841288e 494 ASSERT_OK(sd_netlink_message_exit_container(m));
d08d92d5
YW
495}
496
eafff21d
YW
497TEST(message_strv) {
498 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
d08d92d5
YW
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
3841288e 503 ASSERT_OK(sd_netlink_open(&rtnl));
0c45a60f 504
3841288e 505 ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINKPROP, 1));
d08d92d5
YW
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);
3841288e 511 ASSERT_OK(strv_extend(&names_in, name));
d08d92d5
YW
512 }
513
3841288e
YW
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));
d08d92d5 517
409856d3 518 message_seal(m);
3841288e 519 ASSERT_OK(sd_netlink_message_rewind(m, rtnl));
9104009e 520
3841288e
YW
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));
d08d92d5 523
3841288e
YW
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));
9104009e
YW
528}
529
e1578f60
YW
530static 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
3841288e
YW
535 ASSERT_NOT_NULL(genl);
536 ASSERT_NOT_NULL(m);
e1578f60 537
3841288e
YW
538 ASSERT_OK(sd_genl_message_get_family_name(genl, m, &name));
539 ASSERT_STREQ(name, CTRL_GENL_NAME);
e1578f60 540
3841288e 541 ASSERT_OK(sd_genl_message_get_command(genl, m, &cmd));
e1578f60
YW
542
543 switch (cmd) {
544 case CTRL_CMD_NEWFAMILY:
545 case CTRL_CMD_DELFAMILY:
3841288e
YW
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));
e1578f60
YW
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:
3841288e
YW
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));
e1578f60
YW
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
eafff21d 565TEST(genl) {
e1578f60 566 _cleanup_(sd_event_unrefp) sd_event *event = NULL;
56fdc16d
YW
567 _cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
568 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
569 const char *name;
ef90beb1 570 uint8_t cmd;
e1578f60 571 int r;
56fdc16d 572
3841288e
YW
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));
e1578f60 576
3841288e
YW
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);
56fdc16d 582
3841288e 583 ASSERT_OK(sd_genl_add_match(genl, NULL, CTRL_GENL_NAME, "notify", 0, genl_ctrl_match_callback, NULL, NULL, "genl-ctrl-notify"));
e1578f60 584
d9000d70 585 ASSERT_NULL(m = sd_netlink_message_unref(m));
3841288e
YW
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);
e1578f60
YW
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);
d9000d70 591 ASSERT_NULL(m = sd_netlink_message_unref(m));
e1578f60 592 (void) sd_genl_message_new(genl, L2TP_GENL_NAME, 0, &m);
d9000d70 593 ASSERT_NULL(m = sd_netlink_message_unref(m));
e1578f60 594 (void) sd_genl_message_new(genl, MACSEC_GENL_NAME, 0, &m);
d9000d70 595 ASSERT_NULL(m = sd_netlink_message_unref(m));
e1578f60 596 (void) sd_genl_message_new(genl, NL80211_GENL_NAME, 0, &m);
d9000d70 597 ASSERT_NULL(m = sd_netlink_message_unref(m));
5b198025 598 (void) sd_genl_message_new(genl, NETLBL_NLTYPE_UNLABELED_NAME, 0, &m);
e1578f60
YW
599
600 for (;;) {
d9000d70 601 ASSERT_OK(r = sd_event_run(event, 500 * USEC_PER_MSEC));
e1578f60
YW
602 if (r == 0)
603 return;
604 }
56fdc16d
YW
605}
606
5ccbe7fb
YW
607static 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
3841288e 614 ASSERT_OK(sd_netlink_open(&rtnl));
5ccbe7fb 615
3841288e
YW
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);
5ccbe7fb
YW
618}
619
eafff21d
YW
620TEST(rtnl_set_link_name) {
621 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
5ccbe7fb
YW
622 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
623 _cleanup_(remove_dummy_interfacep) int ifindex = 0;
b338a8bb 624 _cleanup_strv_free_ char **alternative_names = NULL;
5ccbe7fb 625 int r;
b338a8bb
NR
626
627 if (geteuid() != 0)
628 return (void) log_tests_skipped("not root");
629
3841288e 630 ASSERT_OK(sd_netlink_open(&rtnl));
5ccbe7fb 631
3841288e
YW
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"));
5ccbe7fb
YW
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");
3841288e 641 ASSERT_OK(r);
5ccbe7fb 642
d9000d70
YW
643 ASSERT_NULL(message = sd_netlink_message_unref(message));
644 ASSERT_NULL(reply = sd_netlink_message_unref(reply));
5ccbe7fb 645
3841288e
YW
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);
5ccbe7fb 649
3841288e
YW
650 ASSERT_OK(sd_rtnl_message_link_get_ifindex(reply, &ifindex));
651 ASSERT_GT(ifindex, 0);
eafff21d 652
b338a8bb
NR
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). */
5ccbe7fb 657 r = rtnl_set_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename", "test-shortname"));
b338a8bb
NR
658 if (r == -EPERM)
659 return (void) log_tests_skipped("missing required capabilities");
5ccbe7fb
YW
660 if (r == -EOPNOTSUPP)
661 return (void) log_tests_skipped("alternative name is not supported");
3841288e 662 ASSERT_OK(r);
5ccbe7fb 663
3841288e
YW
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"));
5ccbe7fb 667
3841288e
YW
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")));
5ccbe7fb 670
d9000d70 671 ASSERT_NULL(alternative_names = strv_free(alternative_names));
3841288e
YW
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"));
5ccbe7fb 676
3841288e 677 ASSERT_OK(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")));
5ccbe7fb 678
d9000d70 679 ASSERT_NULL(alternative_names = strv_free(alternative_names));
0e44a7c0 680 ASSERT_OK_EQ(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names), ifindex);
3841288e
YW
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"));
1cdd8b1b
YW
684
685 _cleanup_free_ char *resolved = NULL;
0e44a7c0 686 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", NULL), ifindex);
3841288e
YW
687 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", &resolved), ifindex);
688 ASSERT_STREQ(resolved, "test-shortname");
d9000d70 689 ASSERT_NULL(resolved = mfree(resolved));
6e931bc5 690
3841288e
YW
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"));
6e931bc5 694
0e44a7c0 695 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", NULL), ifindex);
3841288e
YW
696 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", &resolved), ifindex);
697 ASSERT_STREQ(resolved, "test-shortname3");
d9000d70 698 ASSERT_NULL(resolved = mfree(resolved));
6e931bc5 699
0e44a7c0 700 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-shortname3", NULL), ifindex);
3841288e
YW
701 ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-shortname3", &resolved), ifindex);
702 ASSERT_STREQ(resolved, "test-shortname3");
d9000d70 703 ASSERT_NULL(resolved = mfree(resolved));
b338a8bb
NR
704}
705
89e546e9
LP
706TEST(sock_diag_unix) {
707 _cleanup_(sd_netlink_unrefp) sd_netlink *nl = NULL;
74acb358 708 int r;
89e546e9
LP
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;
272017d3 720 ASSERT_OK(socket_get_cookie(unix_fd, &cookie));
89e546e9
LP
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;
09503168 726 r = sd_netlink_call(nl, message, /* timeout= */ 0, &reply);
74acb358
LB
727 if (r == -ENOENT)
728 return (void) log_tests_skipped("CONFIG_UNIX_DIAG disabled");
729 ASSERT_OK(r);
89e546e9
LP
730}
731
eafff21d 732DEFINE_TEST_MAIN(LOG_DEBUG);