1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <netinet/ether.h>
5 #include <linux/genetlink.h>
7 #include "sd-netlink.h"
9 #include "alloc-util.h"
10 #include "ether-addr-util.h"
12 #include "netlink-util.h"
13 #include "socket-util.h"
14 #include "stdio-util.h"
15 #include "string-util.h"
19 static void test_message_link_bridge(sd_netlink
*rtnl
) {
20 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*message
= NULL
;
23 assert_se(sd_rtnl_message_new_link(rtnl
, &message
, RTM_NEWLINK
, 1) >= 0);
24 assert_se(sd_rtnl_message_link_set_family(message
, AF_BRIDGE
) >= 0);
25 assert_se(sd_netlink_message_open_container(message
, IFLA_PROTINFO
) >= 0);
26 assert_se(sd_netlink_message_append_u32(message
, IFLA_BRPORT_COST
, 10) >= 0);
27 assert_se(sd_netlink_message_close_container(message
) >= 0);
29 assert_se(sd_netlink_message_rewind(message
, NULL
) >= 0);
31 assert_se(sd_netlink_message_enter_container(message
, IFLA_PROTINFO
) >= 0);
32 assert_se(sd_netlink_message_read_u32(message
, IFLA_BRPORT_COST
, &cost
) >= 0);
33 assert_se(cost
== 10);
34 assert_se(sd_netlink_message_exit_container(message
) >= 0);
37 static void test_link_configure(sd_netlink
*rtnl
, int ifindex
) {
38 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*message
= NULL
;
39 const char *mac
= "98:fe:94:3f:c6:18", *name
= "test";
40 char buffer
[ETHER_ADDR_TO_STRING_MAX
];
41 uint32_t mtu
= 1450, mtu_out
;
43 struct ether_addr mac_out
;
45 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
46 assert_se(sd_rtnl_message_new_link(rtnl
, &message
, RTM_GETLINK
, ifindex
) >= 0);
47 assert_se(sd_netlink_message_append_string(message
, IFLA_IFNAME
, name
) >= 0);
48 assert_se(sd_netlink_message_append_ether_addr(message
, IFLA_ADDRESS
, ether_aton(mac
)) >= 0);
49 assert_se(sd_netlink_message_append_u32(message
, IFLA_MTU
, mtu
) >= 0);
51 assert_se(sd_netlink_call(rtnl
, message
, 0, NULL
) == 1);
52 assert_se(sd_netlink_message_rewind(message
, NULL
) >= 0);
54 assert_se(sd_netlink_message_read_string(message
, IFLA_IFNAME
, &name_out
) >= 0);
55 assert_se(streq(name
, name_out
));
57 assert_se(sd_netlink_message_read_ether_addr(message
, IFLA_ADDRESS
, &mac_out
) >= 0);
58 assert_se(streq(mac
, ether_addr_to_string(&mac_out
, buffer
)));
60 assert_se(sd_netlink_message_read_u32(message
, IFLA_MTU
, &mtu_out
) >= 0);
61 assert_se(mtu
== mtu_out
);
64 static void test_link_get(sd_netlink
*rtnl
, int ifindex
) {
65 sd_netlink_message
*m
;
66 sd_netlink_message
*r
;
71 struct ether_addr eth_data
;
73 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
77 assert_se(sd_netlink_message_append_u8(m
, IFLA_CARRIER
, 0) >= 0);
78 assert_se(sd_netlink_message_append_u8(m
, IFLA_OPERSTATE
, 0) >= 0);
79 assert_se(sd_netlink_message_append_u8(m
, IFLA_LINKMODE
, 0) >= 0);
82 assert_se(sd_netlink_message_append_u32(m
, IFLA_MTU
, mtu
) >= 0);
83 assert_se(sd_netlink_message_append_u32(m
, IFLA_GROUP
, 0) >= 0);
84 assert_se(sd_netlink_message_append_u32(m
, IFLA_TXQLEN
, 0) >= 0);
85 assert_se(sd_netlink_message_append_u32(m
, IFLA_NUM_TX_QUEUES
, 0) >= 0);
86 assert_se(sd_netlink_message_append_u32(m
, IFLA_NUM_RX_QUEUES
, 0) >= 0);
88 assert_se(sd_netlink_call(rtnl
, m
, -1, &r
) == 1);
90 assert_se(sd_netlink_message_read_string(r
, IFLA_IFNAME
, &str_data
) == 0);
92 assert_se(sd_netlink_message_read_u8(r
, IFLA_CARRIER
, &u8_data
) == 0);
93 assert_se(sd_netlink_message_read_u8(r
, IFLA_OPERSTATE
, &u8_data
) == 0);
94 assert_se(sd_netlink_message_read_u8(r
, IFLA_LINKMODE
, &u8_data
) == 0);
96 assert_se(sd_netlink_message_read_u32(r
, IFLA_MTU
, &u32_data
) == 0);
97 assert_se(sd_netlink_message_read_u32(r
, IFLA_GROUP
, &u32_data
) == 0);
98 assert_se(sd_netlink_message_read_u32(r
, IFLA_TXQLEN
, &u32_data
) == 0);
99 assert_se(sd_netlink_message_read_u32(r
, IFLA_NUM_TX_QUEUES
, &u32_data
) == 0);
100 assert_se(sd_netlink_message_read_u32(r
, IFLA_NUM_RX_QUEUES
, &u32_data
) == 0);
102 assert_se(sd_netlink_message_read_ether_addr(r
, IFLA_ADDRESS
, ð_data
) == 0);
104 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
105 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
108 static void test_address_get(sd_netlink
*rtnl
, int ifindex
) {
109 sd_netlink_message
*m
;
110 sd_netlink_message
*r
;
111 struct in_addr in_data
;
112 struct ifa_cacheinfo cache
;
115 assert_se(sd_rtnl_message_new_addr(rtnl
, &m
, RTM_GETADDR
, ifindex
, AF_INET
) >= 0);
118 assert_se(sd_netlink_call(rtnl
, m
, -1, &r
) == 1);
120 assert_se(sd_netlink_message_read_in_addr(r
, IFA_LOCAL
, &in_data
) == 0);
121 assert_se(sd_netlink_message_read_in_addr(r
, IFA_ADDRESS
, &in_data
) == 0);
122 assert_se(sd_netlink_message_read_string(r
, IFA_LABEL
, &label
) == 0);
123 assert_se(sd_netlink_message_read_cache_info(r
, IFA_CACHEINFO
, &cache
) == 0);
125 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
126 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
130 static void test_route(sd_netlink
*rtnl
) {
131 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
132 struct in_addr addr
, addr_data
;
133 uint32_t index
= 2, u32_data
;
136 r
= sd_rtnl_message_new_route(rtnl
, &req
, RTM_NEWROUTE
, AF_INET
, RTPROT_STATIC
);
138 log_error_errno(r
, "Could not create RTM_NEWROUTE message: %m");
142 addr
.s_addr
= htobe32(INADDR_LOOPBACK
);
144 r
= sd_netlink_message_append_in_addr(req
, RTA_GATEWAY
, &addr
);
146 log_error_errno(r
, "Could not append RTA_GATEWAY attribute: %m");
150 r
= sd_netlink_message_append_u32(req
, RTA_OIF
, index
);
152 log_error_errno(r
, "Could not append RTA_OIF attribute: %m");
156 assert_se(sd_netlink_message_rewind(req
, NULL
) >= 0);
158 assert_se(sd_netlink_message_read_in_addr(req
, RTA_GATEWAY
, &addr_data
) >= 0);
159 assert_se(addr_data
.s_addr
== addr
.s_addr
);
161 assert_se(sd_netlink_message_read_u32(req
, RTA_OIF
, &u32_data
) >= 0);
162 assert_se(u32_data
== index
);
164 assert_se((req
= sd_netlink_message_unref(req
)) == NULL
);
167 static void test_multiple(void) {
168 sd_netlink
*rtnl1
, *rtnl2
;
170 assert_se(sd_netlink_open(&rtnl1
) >= 0);
171 assert_se(sd_netlink_open(&rtnl2
) >= 0);
173 rtnl1
= sd_netlink_unref(rtnl1
);
174 rtnl2
= sd_netlink_unref(rtnl2
);
177 static int link_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
178 char *ifname
= userdata
;
185 log_info("%s: got link info about %s", __func__
, ifname
);
188 assert_se(sd_netlink_message_read_string(m
, IFLA_IFNAME
, &data
) >= 0);
189 assert_se(streq(data
, "lo"));
194 static void test_event_loop(int ifindex
) {
195 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
196 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
197 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
200 ifname
= strdup("lo2");
203 assert_se(sd_netlink_open(&rtnl
) >= 0);
204 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
206 assert_se(sd_netlink_call_async(rtnl
, NULL
, m
, link_handler
, NULL
, ifname
, 0, NULL
) >= 0);
208 assert_se(sd_event_default(&event
) >= 0);
210 assert_se(sd_netlink_attach_event(rtnl
, event
, 0) >= 0);
212 assert_se(sd_event_run(event
, 0) >= 0);
214 assert_se(sd_netlink_detach_event(rtnl
) >= 0);
216 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
219 static void test_async_destroy(void *userdata
) {
222 static void test_async(int ifindex
) {
223 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
224 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
, *r
= NULL
;
225 _cleanup_(sd_netlink_slot_unrefp
) sd_netlink_slot
*slot
= NULL
;
226 sd_netlink_destroy_t destroy_callback
;
227 const char *description
;
230 ifname
= strdup("lo");
233 assert_se(sd_netlink_open(&rtnl
) >= 0);
235 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
237 assert_se(sd_netlink_call_async(rtnl
, &slot
, m
, link_handler
, test_async_destroy
, ifname
, 0, "hogehoge") >= 0);
239 assert_se(sd_netlink_slot_get_netlink(slot
) == rtnl
);
240 assert_se(sd_netlink_slot_get_userdata(slot
) == ifname
);
241 assert_se(sd_netlink_slot_get_destroy_callback(slot
, &destroy_callback
) == 1);
242 assert_se(destroy_callback
== test_async_destroy
);
243 assert_se(sd_netlink_slot_get_floating(slot
) == 0);
244 assert_se(sd_netlink_slot_get_description(slot
, &description
) == 1);
245 assert_se(streq(description
, "hogehoge"));
247 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
248 assert_se(sd_netlink_process(rtnl
, &r
) >= 0);
250 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
253 static void test_slot_set(int ifindex
) {
254 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
255 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
, *r
= NULL
;
256 _cleanup_(sd_netlink_slot_unrefp
) sd_netlink_slot
*slot
= NULL
;
257 sd_netlink_destroy_t destroy_callback
;
258 const char *description
;
261 ifname
= strdup("lo");
264 assert_se(sd_netlink_open(&rtnl
) >= 0);
266 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
268 assert_se(sd_netlink_call_async(rtnl
, &slot
, m
, link_handler
, NULL
, NULL
, 0, NULL
) >= 0);
270 assert_se(sd_netlink_slot_get_netlink(slot
) == rtnl
);
271 assert_se(!sd_netlink_slot_get_userdata(slot
));
272 assert_se(!sd_netlink_slot_set_userdata(slot
, ifname
));
273 assert_se(sd_netlink_slot_get_userdata(slot
) == ifname
);
274 assert_se(sd_netlink_slot_get_destroy_callback(slot
, NULL
) == 0);
275 assert_se(sd_netlink_slot_set_destroy_callback(slot
, test_async_destroy
) >= 0);
276 assert_se(sd_netlink_slot_get_destroy_callback(slot
, &destroy_callback
) == 1);
277 assert_se(destroy_callback
== test_async_destroy
);
278 assert_se(sd_netlink_slot_get_floating(slot
) == 0);
279 assert_se(sd_netlink_slot_set_floating(slot
, 1) == 1);
280 assert_se(sd_netlink_slot_get_floating(slot
) == 1);
281 assert_se(sd_netlink_slot_get_description(slot
, NULL
) == 0);
282 assert_se(sd_netlink_slot_set_description(slot
, "hogehoge") >= 0);
283 assert_se(sd_netlink_slot_get_description(slot
, &description
) == 1);
284 assert_se(streq(description
, "hogehoge"));
286 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
287 assert_se(sd_netlink_process(rtnl
, &r
) >= 0);
289 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
292 struct test_async_object
{
297 static struct test_async_object
*test_async_object_free(struct test_async_object
*t
) {
304 DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(struct test_async_object
, test_async_object
, test_async_object_free
);
305 DEFINE_TRIVIAL_CLEANUP_FUNC(struct test_async_object
*, test_async_object_unref
);
307 static int link_handler2(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
308 struct test_async_object
*t
= userdata
;
315 log_info("%s: got link info about %s", __func__
, t
->ifname
);
317 assert_se(sd_netlink_message_read_string(m
, IFLA_IFNAME
, &data
) >= 0);
318 assert_se(streq(data
, "lo"));
323 static void test_async_object_destroy(void *userdata
) {
324 struct test_async_object
*t
= userdata
;
328 log_info("%s: n_ref=%u", __func__
, t
->n_ref
);
329 test_async_object_unref(t
);
332 static void test_async_destroy_callback(int ifindex
) {
333 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
334 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
, *r
= NULL
;
335 _cleanup_(test_async_object_unrefp
) struct test_async_object
*t
= NULL
;
336 _cleanup_(sd_netlink_slot_unrefp
) sd_netlink_slot
*slot
= NULL
;
339 assert_se(t
= new(struct test_async_object
, 1));
340 assert_se(ifname
= strdup("lo"));
341 *t
= (struct test_async_object
) {
346 assert_se(sd_netlink_open(&rtnl
) >= 0);
348 /* destroy callback is called after processing message */
349 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
350 assert_se(sd_netlink_call_async(rtnl
, NULL
, m
, link_handler2
, test_async_object_destroy
, t
, 0, NULL
) >= 0);
352 assert_se(t
->n_ref
== 1);
353 assert_se(test_async_object_ref(t
));
354 assert_se(t
->n_ref
== 2);
356 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
357 assert_se(sd_netlink_process(rtnl
, &r
) == 1);
358 assert_se(t
->n_ref
== 1);
360 assert_se(!sd_netlink_message_unref(m
));
362 /* destroy callback is called when asynchronous call is cancelled, that is, slot is freed. */
363 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
364 assert_se(sd_netlink_call_async(rtnl
, &slot
, m
, link_handler2
, test_async_object_destroy
, t
, 0, NULL
) >= 0);
366 assert_se(t
->n_ref
== 1);
367 assert_se(test_async_object_ref(t
));
368 assert_se(t
->n_ref
== 2);
370 assert_se(!(slot
= sd_netlink_slot_unref(slot
)));
371 assert_se(t
->n_ref
== 1);
373 assert_se(!sd_netlink_message_unref(m
));
375 /* destroy callback is also called by sd_netlink_unref() */
376 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
377 assert_se(sd_netlink_call_async(rtnl
, NULL
, m
, link_handler2
, test_async_object_destroy
, t
, 0, NULL
) >= 0);
379 assert_se(t
->n_ref
== 1);
380 assert_se(test_async_object_ref(t
));
381 assert_se(t
->n_ref
== 2);
383 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
384 assert_se(t
->n_ref
== 1);
387 static int pipe_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
388 int *counter
= userdata
;
393 r
= sd_netlink_message_get_errno(m
);
395 log_info_errno(r
, "%d left in pipe. got reply: %m", *counter
);
402 static void test_pipe(int ifindex
) {
403 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
404 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m1
= NULL
, *m2
= NULL
;
407 assert_se(sd_netlink_open(&rtnl
) >= 0);
409 assert_se(sd_rtnl_message_new_link(rtnl
, &m1
, RTM_GETLINK
, ifindex
) >= 0);
410 assert_se(sd_rtnl_message_new_link(rtnl
, &m2
, RTM_GETLINK
, ifindex
) >= 0);
413 assert_se(sd_netlink_call_async(rtnl
, NULL
, m1
, pipe_handler
, NULL
, &counter
, 0, NULL
) >= 0);
416 assert_se(sd_netlink_call_async(rtnl
, NULL
, m2
, pipe_handler
, NULL
, &counter
, 0, NULL
) >= 0);
418 while (counter
> 0) {
419 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
420 assert_se(sd_netlink_process(rtnl
, NULL
) >= 0);
423 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
426 static void test_container(sd_netlink
*rtnl
) {
427 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
430 const char *string_data
;
432 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0) >= 0);
434 assert_se(sd_netlink_message_open_container(m
, IFLA_LINKINFO
) >= 0);
435 assert_se(sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "vlan") >= 0);
436 assert_se(sd_netlink_message_append_u16(m
, IFLA_VLAN_ID
, 100) >= 0);
437 assert_se(sd_netlink_message_close_container(m
) >= 0);
438 assert_se(sd_netlink_message_append_string(m
, IFLA_INFO_KIND
, "vlan") >= 0);
439 assert_se(sd_netlink_message_close_container(m
) >= 0);
440 assert_se(sd_netlink_message_close_container(m
) == -EINVAL
);
442 assert_se(sd_netlink_message_rewind(m
, NULL
) >= 0);
444 assert_se(sd_netlink_message_enter_container(m
, IFLA_LINKINFO
) >= 0);
445 assert_se(sd_netlink_message_read_string(m
, IFLA_INFO_KIND
, &string_data
) >= 0);
446 assert_se(streq("vlan", string_data
));
448 assert_se(sd_netlink_message_enter_container(m
, IFLA_INFO_DATA
) >= 0);
449 assert_se(sd_netlink_message_read_u16(m
, IFLA_VLAN_ID
, &u16_data
) >= 0);
450 assert_se(sd_netlink_message_exit_container(m
) >= 0);
452 assert_se(sd_netlink_message_read_string(m
, IFLA_INFO_KIND
, &string_data
) >= 0);
453 assert_se(streq("vlan", string_data
));
454 assert_se(sd_netlink_message_exit_container(m
) >= 0);
456 assert_se(sd_netlink_message_read_u32(m
, IFLA_LINKINFO
, &u32_data
) < 0);
458 assert_se(sd_netlink_message_exit_container(m
) == -EINVAL
);
461 static void test_match(void) {
462 _cleanup_(sd_netlink_slot_unrefp
) sd_netlink_slot
*s1
= NULL
, *s2
= NULL
;
463 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
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 assert_se(sd_rtnl_message_new_addr(rtnl
, &req
, RTM_GETADDR
, 0, AF_UNSPEC
) >= 0);
483 assert_se(sd_netlink_call(rtnl
, req
, 0, &reply
) >= 0);
485 for (m
= reply
; m
; m
= sd_netlink_message_next(m
)) {
487 unsigned char scope
, flags
;
490 assert_se(sd_netlink_message_get_type(m
, &type
) >= 0);
491 assert_se(type
== RTM_NEWADDR
);
493 assert_se(sd_rtnl_message_addr_get_ifindex(m
, &ifindex
) >= 0);
494 assert_se(sd_rtnl_message_addr_get_family(m
, &family
) >= 0);
495 assert_se(sd_rtnl_message_addr_get_scope(m
, &scope
) >= 0);
496 assert_se(sd_rtnl_message_addr_get_flags(m
, &flags
) >= 0);
498 assert_se(ifindex
> 0);
499 assert_se(IN_SET(family
, AF_INET
, AF_INET6
));
501 log_info("got IPv%u address on ifindex %i", family
== AF_INET
? 4: 6, ifindex
);
505 static void test_message(sd_netlink
*rtnl
) {
506 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
508 assert_se(rtnl_message_new_synthetic_error(rtnl
, -ETIMEDOUT
, 1, &m
) >= 0);
509 assert_se(sd_netlink_message_get_errno(m
) == -ETIMEDOUT
);
512 static void test_array(void) {
513 _cleanup_(sd_netlink_unrefp
) sd_netlink
*genl
= NULL
;
514 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
516 assert_se(sd_genl_socket_open(&genl
) >= 0);
517 assert_se(sd_genl_message_new(genl
, SD_GENL_ID_CTRL
, CTRL_CMD_GETFAMILY
, &m
) >= 0);
519 assert_se(sd_netlink_message_open_container(m
, CTRL_ATTR_MCAST_GROUPS
) >= 0);
520 for (unsigned i
= 0; i
< 10; i
++) {
521 char name
[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
522 uint32_t id
= i
+ 1000;
524 xsprintf(name
, "hoge%" PRIu32
, id
);
525 assert_se(sd_netlink_message_open_array(m
, i
+ 1) >= 0);
526 assert_se(sd_netlink_message_append_u32(m
, CTRL_ATTR_MCAST_GRP_ID
, id
) >= 0);
527 assert_se(sd_netlink_message_append_string(m
, CTRL_ATTR_MCAST_GRP_NAME
, name
) >= 0);
528 assert_se(sd_netlink_message_close_container(m
) >= 0);
530 assert_se(sd_netlink_message_close_container(m
) >= 0);
532 rtnl_message_seal(m
);
533 assert_se(sd_netlink_message_rewind(m
, genl
) >= 0);
535 assert_se(sd_netlink_message_enter_container(m
, CTRL_ATTR_MCAST_GROUPS
) >= 0);
536 for (unsigned i
= 0; i
< 10; i
++) {
537 char expected
[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
541 assert_se(sd_netlink_message_enter_array(m
, i
+ 1) >= 0);
542 assert_se(sd_netlink_message_read_u32(m
, CTRL_ATTR_MCAST_GRP_ID
, &id
) >= 0);
543 assert_se(sd_netlink_message_read_string(m
, CTRL_ATTR_MCAST_GRP_NAME
, &name
) >= 0);
544 assert_se(sd_netlink_message_exit_container(m
) >= 0);
546 assert_se(id
== i
+ 1000);
547 xsprintf(expected
, "hoge%" PRIu32
, id
);
548 assert_se(streq(name
, expected
));
550 assert_se(sd_netlink_message_exit_container(m
) >= 0);
553 static void test_strv(sd_netlink
*rtnl
) {
554 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
555 _cleanup_strv_free_
char **names_in
= NULL
, **names_out
;
558 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINKPROP
, 1) >= 0);
560 for (unsigned i
= 0; i
< 10; i
++) {
561 char name
[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
563 xsprintf(name
, "hoge%" PRIu32
, i
+ 1000);
564 assert_se(strv_extend(&names_in
, name
) >= 0);
567 assert_se(sd_netlink_message_open_container(m
, IFLA_PROP_LIST
) >= 0);
568 assert_se(sd_netlink_message_append_strv(m
, IFLA_ALT_IFNAME
, names_in
) >= 0);
569 assert_se(sd_netlink_message_close_container(m
) >= 0);
571 rtnl_message_seal(m
);
572 assert_se(sd_netlink_message_rewind(m
, NULL
) >= 0);
574 assert_se(sd_netlink_message_read_strv(m
, IFLA_PROP_LIST
, IFLA_ALT_IFNAME
, &names_out
) >= 0);
575 assert_se(strv_equal(names_in
, names_out
));
577 assert_se(sd_netlink_message_enter_container(m
, IFLA_PROP_LIST
) >= 0);
578 assert_se(sd_netlink_message_read_string(m
, IFLA_ALT_IFNAME
, &p
) >= 0);
579 assert_se(streq(p
, "hoge1009"));
580 assert_se(sd_netlink_message_exit_container(m
) >= 0);
585 sd_netlink_message
*m
;
586 sd_netlink_message
*r
;
587 const char *string_data
;
594 assert_se(sd_netlink_open(&rtnl
) >= 0);
599 test_container(rtnl
);
603 if_loopback
= (int) if_nametoindex("lo");
604 assert_se(if_loopback
> 0);
606 test_async(if_loopback
);
607 test_slot_set(if_loopback
);
608 test_async_destroy_callback(if_loopback
);
609 test_pipe(if_loopback
);
610 test_event_loop(if_loopback
);
611 test_link_configure(rtnl
, if_loopback
);
613 test_get_addresses(rtnl
);
614 test_message_link_bridge(rtnl
);
616 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, if_loopback
) >= 0);
619 assert_se(sd_netlink_message_get_type(m
, &type
) >= 0);
620 assert_se(type
== RTM_GETLINK
);
622 assert_se(sd_netlink_message_read_string(m
, IFLA_IFNAME
, &string_data
) == -EPERM
);
624 assert_se(sd_netlink_call(rtnl
, m
, 0, &r
) == 1);
625 assert_se(sd_netlink_message_get_type(r
, &type
) >= 0);
626 assert_se(type
== RTM_NEWLINK
);
628 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
630 assert_se(sd_netlink_call(rtnl
, m
, -1, &r
) == -EPERM
);
631 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
632 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
634 test_link_get(rtnl
, if_loopback
);
635 test_address_get(rtnl
, if_loopback
);
637 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
638 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
639 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);