1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <netinet/ether.h>
5 #include <netinet/in.h>
7 #include <linux/genetlink.h>
8 #include <linux/if_macsec.h>
9 #include <linux/l2tp.h>
10 #include <linux/nl80211.h>
12 #include "sd-netlink.h"
14 #include "alloc-util.h"
15 #include "ether-addr-util.h"
17 #include "netlink-genl.h"
18 #include "netlink-internal.h"
19 #include "netlink-util.h"
20 #include "socket-util.h"
21 #include "stdio-util.h"
22 #include "string-util.h"
26 static void test_message_link_bridge(sd_netlink
*rtnl
) {
27 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*message
= NULL
;
30 log_debug("/* %s */", __func__
);
32 assert_se(sd_rtnl_message_new_link(rtnl
, &message
, RTM_NEWLINK
, 1) >= 0);
33 assert_se(sd_rtnl_message_link_set_family(message
, AF_BRIDGE
) >= 0);
34 assert_se(sd_netlink_message_open_container(message
, IFLA_PROTINFO
) >= 0);
35 assert_se(sd_netlink_message_append_u32(message
, IFLA_BRPORT_COST
, 10) >= 0);
36 assert_se(sd_netlink_message_close_container(message
) >= 0);
38 assert_se(sd_netlink_message_rewind(message
, rtnl
) >= 0);
40 assert_se(sd_netlink_message_enter_container(message
, IFLA_PROTINFO
) >= 0);
41 assert_se(sd_netlink_message_read_u32(message
, IFLA_BRPORT_COST
, &cost
) >= 0);
42 assert_se(cost
== 10);
43 assert_se(sd_netlink_message_exit_container(message
) >= 0);
46 static void test_link_configure(sd_netlink
*rtnl
, int ifindex
) {
47 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*message
= NULL
, *reply
= NULL
;
50 struct ether_addr mac_out
;
52 log_debug("/* %s */", __func__
);
54 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
55 assert_se(sd_rtnl_message_new_link(rtnl
, &message
, RTM_GETLINK
, ifindex
) >= 0);
57 assert_se(sd_netlink_call(rtnl
, message
, 0, &reply
) == 1);
59 assert_se(sd_netlink_message_read_string(reply
, IFLA_IFNAME
, &name_out
) >= 0);
60 assert_se(sd_netlink_message_read_ether_addr(reply
, IFLA_ADDRESS
, &mac_out
) >= 0);
61 assert_se(sd_netlink_message_read_u32(reply
, IFLA_MTU
, &mtu_out
) >= 0);
64 static void test_link_get(sd_netlink
*rtnl
, int ifindex
) {
65 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
, *r
= NULL
;
69 struct ether_addr eth_data
;
71 log_debug("/* %s */", __func__
);
73 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
76 assert_se(sd_netlink_call(rtnl
, m
, 0, &r
) == 1);
78 assert_se(sd_netlink_message_read_string(r
, IFLA_IFNAME
, &str_data
) == 0);
80 assert_se(sd_netlink_message_read_u8(r
, IFLA_CARRIER
, &u8_data
) == 0);
81 assert_se(sd_netlink_message_read_u8(r
, IFLA_OPERSTATE
, &u8_data
) == 0);
82 assert_se(sd_netlink_message_read_u8(r
, IFLA_LINKMODE
, &u8_data
) == 0);
84 assert_se(sd_netlink_message_read_u32(r
, IFLA_MTU
, &u32_data
) == 0);
85 assert_se(sd_netlink_message_read_u32(r
, IFLA_GROUP
, &u32_data
) == 0);
86 assert_se(sd_netlink_message_read_u32(r
, IFLA_TXQLEN
, &u32_data
) == 0);
87 assert_se(sd_netlink_message_read_u32(r
, IFLA_NUM_TX_QUEUES
, &u32_data
) == 0);
88 assert_se(sd_netlink_message_read_u32(r
, IFLA_NUM_RX_QUEUES
, &u32_data
) == 0);
90 assert_se(sd_netlink_message_read_ether_addr(r
, IFLA_ADDRESS
, ð_data
) == 0);
93 static void test_address_get(sd_netlink
*rtnl
, int ifindex
) {
94 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
, *r
= NULL
;
95 struct in_addr in_data
;
96 struct ifa_cacheinfo cache
;
99 log_debug("/* %s */", __func__
);
101 assert_se(sd_rtnl_message_new_addr(rtnl
, &m
, RTM_GETADDR
, ifindex
, AF_INET
) >= 0);
103 assert_se(sd_netlink_message_request_dump(m
, true) >= 0);
104 assert_se(sd_netlink_call(rtnl
, m
, -1, &r
) == 1);
106 assert_se(sd_netlink_message_read_in_addr(r
, IFA_LOCAL
, &in_data
) == 0);
107 assert_se(sd_netlink_message_read_in_addr(r
, IFA_ADDRESS
, &in_data
) == 0);
108 assert_se(sd_netlink_message_read_string(r
, IFA_LABEL
, &label
) == 0);
109 assert_se(sd_netlink_message_read_cache_info(r
, IFA_CACHEINFO
, &cache
) == 0);
112 static void test_route(sd_netlink
*rtnl
) {
113 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
114 struct in_addr addr
, addr_data
;
115 uint32_t index
= 2, u32_data
;
118 log_debug("/* %s */", __func__
);
120 r
= sd_rtnl_message_new_route(rtnl
, &req
, RTM_NEWROUTE
, AF_INET
, RTPROT_STATIC
);
122 log_error_errno(r
, "Could not create RTM_NEWROUTE message: %m");
126 addr
.s_addr
= htobe32(INADDR_LOOPBACK
);
128 r
= sd_netlink_message_append_in_addr(req
, RTA_GATEWAY
, &addr
);
130 log_error_errno(r
, "Could not append RTA_GATEWAY attribute: %m");
134 r
= sd_netlink_message_append_u32(req
, RTA_OIF
, index
);
136 log_error_errno(r
, "Could not append RTA_OIF attribute: %m");
140 assert_se(sd_netlink_message_rewind(req
, rtnl
) >= 0);
142 assert_se(sd_netlink_message_read_in_addr(req
, RTA_GATEWAY
, &addr_data
) >= 0);
143 assert_se(addr_data
.s_addr
== addr
.s_addr
);
145 assert_se(sd_netlink_message_read_u32(req
, RTA_OIF
, &u32_data
) >= 0);
146 assert_se(u32_data
== index
);
148 assert_se((req
= sd_netlink_message_unref(req
)) == NULL
);
151 static void test_multiple(void) {
152 sd_netlink
*rtnl1
, *rtnl2
;
154 log_debug("/* %s */", __func__
);
156 assert_se(sd_netlink_open(&rtnl1
) >= 0);
157 assert_se(sd_netlink_open(&rtnl2
) >= 0);
159 rtnl1
= sd_netlink_unref(rtnl1
);
160 rtnl2
= sd_netlink_unref(rtnl2
);
163 static int link_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
164 char *ifname
= userdata
;
171 log_info("%s: got link info about %s", __func__
, ifname
);
174 assert_se(sd_netlink_message_read_string(m
, IFLA_IFNAME
, &data
) >= 0);
175 assert_se(streq(data
, "lo"));
180 static void test_event_loop(int ifindex
) {
181 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
182 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
183 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
186 log_debug("/* %s */", __func__
);
188 ifname
= strdup("lo2");
191 assert_se(sd_netlink_open(&rtnl
) >= 0);
192 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
194 assert_se(sd_netlink_call_async(rtnl
, NULL
, m
, link_handler
, NULL
, ifname
, 0, NULL
) >= 0);
196 assert_se(sd_event_default(&event
) >= 0);
198 assert_se(sd_netlink_attach_event(rtnl
, event
, 0) >= 0);
200 assert_se(sd_event_run(event
, 0) >= 0);
202 assert_se(sd_netlink_detach_event(rtnl
) >= 0);
204 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
207 static void test_async_destroy(void *userdata
) {
210 static void test_async(int ifindex
) {
211 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
212 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
, *r
= NULL
;
213 _cleanup_(sd_netlink_slot_unrefp
) sd_netlink_slot
*slot
= NULL
;
214 sd_netlink_destroy_t destroy_callback
;
215 const char *description
;
218 log_debug("/* %s */", __func__
);
220 ifname
= strdup("lo");
223 assert_se(sd_netlink_open(&rtnl
) >= 0);
225 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
227 assert_se(sd_netlink_call_async(rtnl
, &slot
, m
, link_handler
, test_async_destroy
, ifname
, 0, "hogehoge") >= 0);
229 assert_se(sd_netlink_slot_get_netlink(slot
) == rtnl
);
230 assert_se(sd_netlink_slot_get_userdata(slot
) == ifname
);
231 assert_se(sd_netlink_slot_get_destroy_callback(slot
, &destroy_callback
) == 1);
232 assert_se(destroy_callback
== test_async_destroy
);
233 assert_se(sd_netlink_slot_get_floating(slot
) == 0);
234 assert_se(sd_netlink_slot_get_description(slot
, &description
) == 1);
235 assert_se(streq(description
, "hogehoge"));
237 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
238 assert_se(sd_netlink_process(rtnl
, &r
) >= 0);
240 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
243 static void test_slot_set(int ifindex
) {
244 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
245 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
, *r
= NULL
;
246 _cleanup_(sd_netlink_slot_unrefp
) sd_netlink_slot
*slot
= NULL
;
247 sd_netlink_destroy_t destroy_callback
;
248 const char *description
;
251 log_debug("/* %s */", __func__
);
253 ifname
= strdup("lo");
256 assert_se(sd_netlink_open(&rtnl
) >= 0);
258 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
260 assert_se(sd_netlink_call_async(rtnl
, &slot
, m
, link_handler
, NULL
, NULL
, 0, NULL
) >= 0);
262 assert_se(sd_netlink_slot_get_netlink(slot
) == rtnl
);
263 assert_se(!sd_netlink_slot_get_userdata(slot
));
264 assert_se(!sd_netlink_slot_set_userdata(slot
, ifname
));
265 assert_se(sd_netlink_slot_get_userdata(slot
) == ifname
);
266 assert_se(sd_netlink_slot_get_destroy_callback(slot
, NULL
) == 0);
267 assert_se(sd_netlink_slot_set_destroy_callback(slot
, test_async_destroy
) >= 0);
268 assert_se(sd_netlink_slot_get_destroy_callback(slot
, &destroy_callback
) == 1);
269 assert_se(destroy_callback
== test_async_destroy
);
270 assert_se(sd_netlink_slot_get_floating(slot
) == 0);
271 assert_se(sd_netlink_slot_set_floating(slot
, 1) == 1);
272 assert_se(sd_netlink_slot_get_floating(slot
) == 1);
273 assert_se(sd_netlink_slot_get_description(slot
, NULL
) == 0);
274 assert_se(sd_netlink_slot_set_description(slot
, "hogehoge") >= 0);
275 assert_se(sd_netlink_slot_get_description(slot
, &description
) == 1);
276 assert_se(streq(description
, "hogehoge"));
278 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
279 assert_se(sd_netlink_process(rtnl
, &r
) >= 0);
281 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
284 struct test_async_object
{
289 static struct test_async_object
*test_async_object_free(struct test_async_object
*t
) {
296 DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(struct test_async_object
, test_async_object
, test_async_object_free
);
297 DEFINE_TRIVIAL_CLEANUP_FUNC(struct test_async_object
*, test_async_object_unref
);
299 static int link_handler2(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
300 struct test_async_object
*t
= userdata
;
307 log_info("%s: got link info about %s", __func__
, t
->ifname
);
309 assert_se(sd_netlink_message_read_string(m
, IFLA_IFNAME
, &data
) >= 0);
310 assert_se(streq(data
, "lo"));
315 static void test_async_object_destroy(void *userdata
) {
316 struct test_async_object
*t
= userdata
;
320 log_info("%s: n_ref=%u", __func__
, t
->n_ref
);
321 test_async_object_unref(t
);
324 static void test_async_destroy_callback(int ifindex
) {
325 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
326 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
, *r
= NULL
;
327 _cleanup_(test_async_object_unrefp
) struct test_async_object
*t
= NULL
;
328 _cleanup_(sd_netlink_slot_unrefp
) sd_netlink_slot
*slot
= NULL
;
331 log_debug("/* %s */", __func__
);
333 assert_se(t
= new(struct test_async_object
, 1));
334 assert_se(ifname
= strdup("lo"));
335 *t
= (struct test_async_object
) {
340 assert_se(sd_netlink_open(&rtnl
) >= 0);
342 /* destroy callback is called after processing message */
343 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
344 assert_se(sd_netlink_call_async(rtnl
, NULL
, m
, link_handler2
, test_async_object_destroy
, t
, 0, NULL
) >= 0);
346 assert_se(t
->n_ref
== 1);
347 assert_se(test_async_object_ref(t
));
348 assert_se(t
->n_ref
== 2);
350 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
351 assert_se(sd_netlink_process(rtnl
, &r
) == 1);
352 assert_se(t
->n_ref
== 1);
354 assert_se(!sd_netlink_message_unref(m
));
356 /* destroy callback is called when asynchronous call is cancelled, that is, slot is freed. */
357 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
358 assert_se(sd_netlink_call_async(rtnl
, &slot
, m
, link_handler2
, test_async_object_destroy
, t
, 0, NULL
) >= 0);
360 assert_se(t
->n_ref
== 1);
361 assert_se(test_async_object_ref(t
));
362 assert_se(t
->n_ref
== 2);
364 assert_se(!(slot
= sd_netlink_slot_unref(slot
)));
365 assert_se(t
->n_ref
== 1);
367 assert_se(!sd_netlink_message_unref(m
));
369 /* destroy callback is also called by sd_netlink_unref() */
370 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
371 assert_se(sd_netlink_call_async(rtnl
, NULL
, m
, link_handler2
, test_async_object_destroy
, t
, 0, NULL
) >= 0);
373 assert_se(t
->n_ref
== 1);
374 assert_se(test_async_object_ref(t
));
375 assert_se(t
->n_ref
== 2);
377 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
378 assert_se(t
->n_ref
== 1);
381 static int pipe_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
382 int *counter
= userdata
;
387 r
= sd_netlink_message_get_errno(m
);
389 log_info_errno(r
, "%d left in pipe. got reply: %m", *counter
);
396 static void test_pipe(int ifindex
) {
397 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
398 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m1
= NULL
, *m2
= NULL
;
401 log_debug("/* %s */", __func__
);
403 assert_se(sd_netlink_open(&rtnl
) >= 0);
405 assert_se(sd_rtnl_message_new_link(rtnl
, &m1
, RTM_GETLINK
, ifindex
) >= 0);
406 assert_se(sd_rtnl_message_new_link(rtnl
, &m2
, RTM_GETLINK
, ifindex
) >= 0);
409 assert_se(sd_netlink_call_async(rtnl
, NULL
, m1
, pipe_handler
, NULL
, &counter
, 0, NULL
) >= 0);
412 assert_se(sd_netlink_call_async(rtnl
, NULL
, m2
, pipe_handler
, NULL
, &counter
, 0, NULL
) >= 0);
414 while (counter
> 0) {
415 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
416 assert_se(sd_netlink_process(rtnl
, NULL
) >= 0);
419 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
422 static void test_container(sd_netlink
*rtnl
) {
423 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
426 const char *string_data
;
428 log_debug("/* %s */", __func__
);
430 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0) >= 0);
432 assert_se(sd_netlink_message_open_container(m
, IFLA_LINKINFO
) >= 0);
433 assert_se(sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "vlan") >= 0);
434 assert_se(sd_netlink_message_append_u16(m
, IFLA_VLAN_ID
, 100) >= 0);
435 assert_se(sd_netlink_message_close_container(m
) >= 0);
436 assert_se(sd_netlink_message_append_string(m
, IFLA_INFO_KIND
, "vlan") >= 0);
437 assert_se(sd_netlink_message_close_container(m
) >= 0);
438 assert_se(sd_netlink_message_close_container(m
) == -EINVAL
);
440 assert_se(sd_netlink_message_rewind(m
, rtnl
) >= 0);
442 assert_se(sd_netlink_message_enter_container(m
, IFLA_LINKINFO
) >= 0);
443 assert_se(sd_netlink_message_read_string(m
, IFLA_INFO_KIND
, &string_data
) >= 0);
444 assert_se(streq("vlan", string_data
));
446 assert_se(sd_netlink_message_enter_container(m
, IFLA_INFO_DATA
) >= 0);
447 assert_se(sd_netlink_message_read_u16(m
, IFLA_VLAN_ID
, &u16_data
) >= 0);
448 assert_se(sd_netlink_message_exit_container(m
) >= 0);
450 assert_se(sd_netlink_message_read_string(m
, IFLA_INFO_KIND
, &string_data
) >= 0);
451 assert_se(streq("vlan", string_data
));
452 assert_se(sd_netlink_message_exit_container(m
) >= 0);
454 assert_se(sd_netlink_message_read_u32(m
, IFLA_LINKINFO
, &u32_data
) < 0);
456 assert_se(sd_netlink_message_exit_container(m
) == -EINVAL
);
459 static void test_match(void) {
460 _cleanup_(sd_netlink_slot_unrefp
) sd_netlink_slot
*s1
= NULL
, *s2
= NULL
;
461 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
463 log_debug("/* %s */", __func__
);
465 assert_se(sd_netlink_open(&rtnl
) >= 0);
467 assert_se(sd_netlink_add_match(rtnl
, &s1
, RTM_NEWLINK
, link_handler
, NULL
, NULL
, NULL
) >= 0);
468 assert_se(sd_netlink_add_match(rtnl
, &s2
, RTM_NEWLINK
, link_handler
, NULL
, NULL
, NULL
) >= 0);
469 assert_se(sd_netlink_add_match(rtnl
, NULL
, RTM_NEWLINK
, link_handler
, NULL
, NULL
, NULL
) >= 0);
471 assert_se(!(s1
= sd_netlink_slot_unref(s1
)));
472 assert_se(!(s2
= sd_netlink_slot_unref(s2
)));
474 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
477 static void test_get_addresses(sd_netlink
*rtnl
) {
478 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
479 sd_netlink_message
*m
;
481 log_debug("/* %s */", __func__
);
483 assert_se(sd_rtnl_message_new_addr(rtnl
, &req
, RTM_GETADDR
, 0, AF_UNSPEC
) >= 0);
484 assert_se(sd_netlink_message_request_dump(req
, true) >= 0);
485 assert_se(sd_netlink_call(rtnl
, req
, 0, &reply
) >= 0);
487 for (m
= reply
; m
; m
= sd_netlink_message_next(m
)) {
489 unsigned char scope
, flags
;
492 assert_se(sd_netlink_message_get_type(m
, &type
) >= 0);
493 assert_se(type
== RTM_NEWADDR
);
495 assert_se(sd_rtnl_message_addr_get_ifindex(m
, &ifindex
) >= 0);
496 assert_se(sd_rtnl_message_addr_get_family(m
, &family
) >= 0);
497 assert_se(sd_rtnl_message_addr_get_scope(m
, &scope
) >= 0);
498 assert_se(sd_rtnl_message_addr_get_flags(m
, &flags
) >= 0);
500 assert_se(ifindex
> 0);
501 assert_se(IN_SET(family
, AF_INET
, AF_INET6
));
503 log_info("got IPv%u address on ifindex %i", family
== AF_INET
? 4: 6, ifindex
);
507 static void test_message(sd_netlink
*rtnl
) {
508 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
510 log_debug("/* %s */", __func__
);
512 assert_se(message_new_synthetic_error(rtnl
, -ETIMEDOUT
, 1, &m
) >= 0);
513 assert_se(sd_netlink_message_get_errno(m
) == -ETIMEDOUT
);
516 static void test_array(void) {
517 _cleanup_(sd_netlink_unrefp
) sd_netlink
*genl
= NULL
;
518 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
520 log_debug("/* %s */", __func__
);
522 assert_se(sd_genl_socket_open(&genl
) >= 0);
523 assert_se(sd_genl_message_new(genl
, CTRL_GENL_NAME
, CTRL_CMD_GETFAMILY
, &m
) >= 0);
525 assert_se(sd_netlink_message_open_container(m
, CTRL_ATTR_MCAST_GROUPS
) >= 0);
526 for (unsigned i
= 0; i
< 10; i
++) {
527 char name
[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
528 uint32_t id
= i
+ 1000;
530 xsprintf(name
, "hoge%" PRIu32
, id
);
531 assert_se(sd_netlink_message_open_array(m
, i
+ 1) >= 0);
532 assert_se(sd_netlink_message_append_u32(m
, CTRL_ATTR_MCAST_GRP_ID
, id
) >= 0);
533 assert_se(sd_netlink_message_append_string(m
, CTRL_ATTR_MCAST_GRP_NAME
, name
) >= 0);
534 assert_se(sd_netlink_message_close_container(m
) >= 0);
536 assert_se(sd_netlink_message_close_container(m
) >= 0);
539 assert_se(sd_netlink_message_rewind(m
, genl
) >= 0);
541 assert_se(sd_netlink_message_enter_container(m
, CTRL_ATTR_MCAST_GROUPS
) >= 0);
542 for (unsigned i
= 0; i
< 10; i
++) {
543 char expected
[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
547 assert_se(sd_netlink_message_enter_array(m
, i
+ 1) >= 0);
548 assert_se(sd_netlink_message_read_u32(m
, CTRL_ATTR_MCAST_GRP_ID
, &id
) >= 0);
549 assert_se(sd_netlink_message_read_string(m
, CTRL_ATTR_MCAST_GRP_NAME
, &name
) >= 0);
550 assert_se(sd_netlink_message_exit_container(m
) >= 0);
552 assert_se(id
== i
+ 1000);
553 xsprintf(expected
, "hoge%" PRIu32
, id
);
554 assert_se(streq(name
, expected
));
556 assert_se(sd_netlink_message_exit_container(m
) >= 0);
559 static void test_strv(sd_netlink
*rtnl
) {
560 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
561 _cleanup_strv_free_
char **names_in
= NULL
, **names_out
;
564 log_debug("/* %s */", __func__
);
566 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINKPROP
, 1) >= 0);
568 for (unsigned i
= 0; i
< 10; i
++) {
569 char name
[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
571 xsprintf(name
, "hoge%" PRIu32
, i
+ 1000);
572 assert_se(strv_extend(&names_in
, name
) >= 0);
575 assert_se(sd_netlink_message_open_container(m
, IFLA_PROP_LIST
) >= 0);
576 assert_se(sd_netlink_message_append_strv(m
, IFLA_ALT_IFNAME
, names_in
) >= 0);
577 assert_se(sd_netlink_message_close_container(m
) >= 0);
580 assert_se(sd_netlink_message_rewind(m
, rtnl
) >= 0);
582 assert_se(sd_netlink_message_read_strv(m
, IFLA_PROP_LIST
, IFLA_ALT_IFNAME
, &names_out
) >= 0);
583 assert_se(strv_equal(names_in
, names_out
));
585 assert_se(sd_netlink_message_enter_container(m
, IFLA_PROP_LIST
) >= 0);
586 assert_se(sd_netlink_message_read_string(m
, IFLA_ALT_IFNAME
, &p
) >= 0);
587 assert_se(streq(p
, "hoge1009"));
588 assert_se(sd_netlink_message_exit_container(m
) >= 0);
591 static int genl_ctrl_match_callback(sd_netlink
*genl
, sd_netlink_message
*m
, void *userdata
) {
599 assert_se(sd_genl_message_get_family_name(genl
, m
, &name
) >= 0);
600 assert_se(streq(name
, CTRL_GENL_NAME
));
602 assert_se(sd_genl_message_get_command(genl
, m
, &cmd
) >= 0);
605 case CTRL_CMD_NEWFAMILY
:
606 case CTRL_CMD_DELFAMILY
:
607 assert_se(sd_netlink_message_read_string(m
, CTRL_ATTR_FAMILY_NAME
, &name
) >= 0);
608 assert_se(sd_netlink_message_read_u16(m
, CTRL_ATTR_FAMILY_ID
, &id
) >= 0);
609 log_debug("%s: %s (id=%"PRIu16
") family is %s.",
610 __func__
, name
, id
, cmd
== CTRL_CMD_NEWFAMILY
? "added" : "removed");
612 case CTRL_CMD_NEWMCAST_GRP
:
613 case CTRL_CMD_DELMCAST_GRP
:
614 assert_se(sd_netlink_message_read_string(m
, CTRL_ATTR_FAMILY_NAME
, &name
) >= 0);
615 assert_se(sd_netlink_message_read_u16(m
, CTRL_ATTR_FAMILY_ID
, &id
) >= 0);
616 log_debug("%s: multicast group for %s (id=%"PRIu16
") family is %s.",
617 __func__
, name
, id
, cmd
== CTRL_CMD_NEWMCAST_GRP
? "added" : "removed");
620 log_debug("%s: received nlctrl message with unknown command '%"PRIu8
"'.", __func__
, cmd
);
626 static void test_genl(void) {
627 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
628 _cleanup_(sd_netlink_unrefp
) sd_netlink
*genl
= NULL
;
629 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
634 log_debug("/* %s */", __func__
);
636 assert_se(sd_genl_socket_open(&genl
) >= 0);
637 assert_se(sd_event_default(&event
) >= 0);
638 assert_se(sd_netlink_attach_event(genl
, event
, 0) >= 0);
640 assert_se(sd_genl_message_new(genl
, CTRL_GENL_NAME
, CTRL_CMD_GETFAMILY
, &m
) >= 0);
641 assert_se(sd_genl_message_get_family_name(genl
, m
, &name
) >= 0);
642 assert_se(streq(name
, CTRL_GENL_NAME
));
643 assert_se(sd_genl_message_get_command(genl
, m
, &cmd
) >= 0);
644 assert_se(cmd
== CTRL_CMD_GETFAMILY
);
646 assert_se(sd_genl_add_match(genl
, NULL
, CTRL_GENL_NAME
, "notify", 0, genl_ctrl_match_callback
, NULL
, NULL
, "genl-ctrl-notify") >= 0);
648 m
= sd_netlink_message_unref(m
);
649 assert_se(sd_genl_message_new(genl
, "should-not-exist", CTRL_CMD_GETFAMILY
, &m
) < 0);
650 assert_se(sd_genl_message_new(genl
, "should-not-exist", CTRL_CMD_GETFAMILY
, &m
) == -EOPNOTSUPP
);
652 /* These families may not be supported by kernel. Hence, ignore results. */
653 (void) sd_genl_message_new(genl
, FOU_GENL_NAME
, 0, &m
);
654 m
= sd_netlink_message_unref(m
);
655 (void) sd_genl_message_new(genl
, L2TP_GENL_NAME
, 0, &m
);
656 m
= sd_netlink_message_unref(m
);
657 (void) sd_genl_message_new(genl
, MACSEC_GENL_NAME
, 0, &m
);
658 m
= sd_netlink_message_unref(m
);
659 (void) sd_genl_message_new(genl
, NL80211_GENL_NAME
, 0, &m
);
662 r
= sd_event_run(event
, 500 * USEC_PER_MSEC
);
671 sd_netlink_message
*m
;
672 sd_netlink_message
*r
;
673 const char *string_data
;
677 test_setup_logging(LOG_DEBUG
);
682 assert_se(sd_netlink_open(&rtnl
) >= 0);
687 test_container(rtnl
);
691 if_loopback
= (int) if_nametoindex("lo");
692 assert_se(if_loopback
> 0);
694 test_async(if_loopback
);
695 test_slot_set(if_loopback
);
696 test_async_destroy_callback(if_loopback
);
697 test_pipe(if_loopback
);
698 test_event_loop(if_loopback
);
699 test_link_configure(rtnl
, if_loopback
);
701 test_get_addresses(rtnl
);
702 test_message_link_bridge(rtnl
);
704 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, if_loopback
) >= 0);
707 assert_se(sd_netlink_message_get_type(m
, &type
) >= 0);
708 assert_se(type
== RTM_GETLINK
);
710 assert_se(sd_netlink_message_read_string(m
, IFLA_IFNAME
, &string_data
) == -EPERM
);
712 assert_se(sd_netlink_call(rtnl
, m
, 0, &r
) == 1);
713 assert_se(sd_netlink_message_get_type(r
, &type
) >= 0);
714 assert_se(type
== RTM_NEWLINK
);
716 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
718 assert_se(sd_netlink_call(rtnl
, m
, -1, &r
) == -EPERM
);
719 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
720 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
722 test_link_get(rtnl
, if_loopback
);
723 test_address_get(rtnl
, if_loopback
);
725 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
726 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
727 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);