1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Tom Gundersen <teg@jklm.no>
7 #include <netinet/ether.h>
9 #include "sd-netlink.h"
11 #include "ether-addr-util.h"
14 #include "netlink-util.h"
15 #include "socket-util.h"
16 #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
, PF_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
) >= 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
) >= 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
;
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
= htonl(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
) >= 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
;
184 log_info("got link info about %s", ifname
);
187 assert_se(sd_netlink_message_read_string(m
, IFLA_IFNAME
, &data
) >= 0);
188 assert_se(streq(data
, "lo"));
193 static void test_event_loop(int ifindex
) {
194 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
195 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
196 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
199 ifname
= strdup("lo2");
202 assert_se(sd_netlink_open(&rtnl
) >= 0);
203 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
205 assert_se(sd_netlink_call_async(rtnl
, m
, link_handler
, ifname
, 0, NULL
) >= 0);
207 assert_se(sd_event_default(&event
) >= 0);
209 assert_se(sd_netlink_attach_event(rtnl
, event
, 0) >= 0);
211 assert_se(sd_event_run(event
, 0) >= 0);
213 assert_se(sd_netlink_detach_event(rtnl
) >= 0);
215 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
218 static int pipe_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
219 int *counter
= userdata
;
224 r
= sd_netlink_message_get_errno(m
);
226 log_info_errno(r
, "%d left in pipe. got reply: %m", *counter
);
233 static void test_async(int ifindex
) {
234 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
235 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
, *r
= NULL
;
239 ifname
= strdup("lo");
242 assert_se(sd_netlink_open(&rtnl
) >= 0);
244 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
246 assert_se(sd_netlink_call_async(rtnl
, m
, link_handler
, ifname
, 0, &serial
) >= 0);
248 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
249 assert_se(sd_netlink_process(rtnl
, &r
) >= 0);
251 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
254 static void test_pipe(int ifindex
) {
255 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
256 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m1
= NULL
, *m2
= NULL
;
259 assert_se(sd_netlink_open(&rtnl
) >= 0);
261 assert_se(sd_rtnl_message_new_link(rtnl
, &m1
, RTM_GETLINK
, ifindex
) >= 0);
262 assert_se(sd_rtnl_message_new_link(rtnl
, &m2
, RTM_GETLINK
, ifindex
) >= 0);
265 assert_se(sd_netlink_call_async(rtnl
, m1
, pipe_handler
, &counter
, 0, NULL
) >= 0);
268 assert_se(sd_netlink_call_async(rtnl
, m2
, pipe_handler
, &counter
, 0, NULL
) >= 0);
270 while (counter
> 0) {
271 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
272 assert_se(sd_netlink_process(rtnl
, NULL
) >= 0);
275 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
278 static void test_container(sd_netlink
*rtnl
) {
279 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
282 const char *string_data
;
284 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0) >= 0);
286 assert_se(sd_netlink_message_open_container(m
, IFLA_LINKINFO
) >= 0);
287 assert_se(sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "vlan") >= 0);
288 assert_se(sd_netlink_message_append_u16(m
, IFLA_VLAN_ID
, 100) >= 0);
289 assert_se(sd_netlink_message_close_container(m
) >= 0);
290 assert_se(sd_netlink_message_append_string(m
, IFLA_INFO_KIND
, "vlan") >= 0);
291 assert_se(sd_netlink_message_close_container(m
) >= 0);
292 assert_se(sd_netlink_message_close_container(m
) == -EINVAL
);
294 assert_se(sd_netlink_message_rewind(m
) >= 0);
296 assert_se(sd_netlink_message_enter_container(m
, IFLA_LINKINFO
) >= 0);
297 assert_se(sd_netlink_message_read_string(m
, IFLA_INFO_KIND
, &string_data
) >= 0);
298 assert_se(streq("vlan", string_data
));
300 assert_se(sd_netlink_message_enter_container(m
, IFLA_INFO_DATA
) >= 0);
301 assert_se(sd_netlink_message_read_u16(m
, IFLA_VLAN_ID
, &u16_data
) >= 0);
302 assert_se(sd_netlink_message_exit_container(m
) >= 0);
304 assert_se(sd_netlink_message_read_string(m
, IFLA_INFO_KIND
, &string_data
) >= 0);
305 assert_se(streq("vlan", string_data
));
306 assert_se(sd_netlink_message_exit_container(m
) >= 0);
308 assert_se(sd_netlink_message_read_u32(m
, IFLA_LINKINFO
, &u32_data
) < 0);
310 assert_se(sd_netlink_message_exit_container(m
) == -EINVAL
);
313 static void test_match(void) {
314 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
316 assert_se(sd_netlink_open(&rtnl
) >= 0);
318 assert_se(sd_netlink_add_match(rtnl
, RTM_NEWLINK
, link_handler
, NULL
) >= 0);
319 assert_se(sd_netlink_add_match(rtnl
, RTM_NEWLINK
, link_handler
, NULL
) >= 0);
321 assert_se(sd_netlink_remove_match(rtnl
, RTM_NEWLINK
, link_handler
, NULL
) == 1);
322 assert_se(sd_netlink_remove_match(rtnl
, RTM_NEWLINK
, link_handler
, NULL
) == 1);
323 assert_se(sd_netlink_remove_match(rtnl
, RTM_NEWLINK
, link_handler
, NULL
) == 0);
325 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
328 static void test_get_addresses(sd_netlink
*rtnl
) {
329 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
330 sd_netlink_message
*m
;
332 assert_se(sd_rtnl_message_new_addr(rtnl
, &req
, RTM_GETADDR
, 0, AF_UNSPEC
) >= 0);
334 assert_se(sd_netlink_call(rtnl
, req
, 0, &reply
) >= 0);
336 for (m
= reply
; m
; m
= sd_netlink_message_next(m
)) {
338 unsigned char scope
, flags
;
341 assert_se(sd_netlink_message_get_type(m
, &type
) >= 0);
342 assert_se(type
== RTM_NEWADDR
);
344 assert_se(sd_rtnl_message_addr_get_ifindex(m
, &ifindex
) >= 0);
345 assert_se(sd_rtnl_message_addr_get_family(m
, &family
) >= 0);
346 assert_se(sd_rtnl_message_addr_get_scope(m
, &scope
) >= 0);
347 assert_se(sd_rtnl_message_addr_get_flags(m
, &flags
) >= 0);
349 assert_se(ifindex
> 0);
350 assert_se(IN_SET(family
, AF_INET
, AF_INET6
));
352 log_info("got IPv%u address on ifindex %i", family
== AF_INET
? 4: 6, ifindex
);
356 static void test_message(sd_netlink
*rtnl
) {
357 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
359 assert_se(rtnl_message_new_synthetic_error(rtnl
, -ETIMEDOUT
, 1, &m
) >= 0);
360 assert_se(sd_netlink_message_get_errno(m
) == -ETIMEDOUT
);
365 sd_netlink_message
*m
;
366 sd_netlink_message
*r
;
367 const char *string_data
;
375 assert_se(sd_netlink_open(&rtnl
) >= 0);
382 test_container(rtnl
);
384 if_loopback
= (int) if_nametoindex("lo");
385 assert_se(if_loopback
> 0);
387 test_async(if_loopback
);
389 test_pipe(if_loopback
);
391 test_event_loop(if_loopback
);
393 test_link_configure(rtnl
, if_loopback
);
395 test_get_addresses(rtnl
);
397 test_message_link_bridge(rtnl
);
399 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, if_loopback
) >= 0);
402 assert_se(sd_netlink_message_get_type(m
, &type
) >= 0);
403 assert_se(type
== RTM_GETLINK
);
405 assert_se(sd_netlink_message_read_string(m
, IFLA_IFNAME
, &string_data
) == -EPERM
);
407 assert_se(sd_netlink_call(rtnl
, m
, 0, &r
) == 1);
408 assert_se(sd_netlink_message_get_type(r
, &type
) >= 0);
409 assert_se(type
== RTM_NEWLINK
);
411 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
413 assert_se(sd_netlink_call(rtnl
, m
, -1, &r
) == -EPERM
);
414 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
415 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
417 test_link_get(rtnl
, if_loopback
);
418 test_address_get(rtnl
, if_loopback
);
420 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
421 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
422 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);