1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/ether.h>
24 #include "sd-netlink.h"
26 #include "ether-addr-util.h"
29 #include "netlink-util.h"
30 #include "socket-util.h"
31 #include "string-util.h"
34 static void test_message_link_bridge(sd_netlink
*rtnl
) {
35 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*message
= NULL
;
38 assert_se(sd_rtnl_message_new_link(rtnl
, &message
, RTM_NEWLINK
, 1) >= 0);
39 assert_se(sd_rtnl_message_link_set_family(message
, PF_BRIDGE
) >= 0);
40 assert_se(sd_netlink_message_open_container(message
, IFLA_PROTINFO
) >= 0);
41 assert_se(sd_netlink_message_append_u32(message
, IFLA_BRPORT_COST
, 10) >= 0);
42 assert_se(sd_netlink_message_close_container(message
) >= 0);
44 assert_se(sd_netlink_message_rewind(message
) >= 0);
46 assert_se(sd_netlink_message_enter_container(message
, IFLA_PROTINFO
) >= 0);
47 assert_se(sd_netlink_message_read_u32(message
, IFLA_BRPORT_COST
, &cost
) >= 0);
48 assert_se(cost
== 10);
49 assert_se(sd_netlink_message_exit_container(message
) >= 0);
52 static void test_link_configure(sd_netlink
*rtnl
, int ifindex
) {
53 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*message
= NULL
;
54 const char *mac
= "98:fe:94:3f:c6:18", *name
= "test";
55 char buffer
[ETHER_ADDR_TO_STRING_MAX
];
56 unsigned int mtu
= 1450, mtu_out
;
58 struct ether_addr mac_out
;
60 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
61 assert_se(sd_rtnl_message_new_link(rtnl
, &message
, RTM_GETLINK
, ifindex
) >= 0);
62 assert_se(sd_netlink_message_append_string(message
, IFLA_IFNAME
, name
) >= 0);
63 assert_se(sd_netlink_message_append_ether_addr(message
, IFLA_ADDRESS
, ether_aton(mac
)) >= 0);
64 assert_se(sd_netlink_message_append_u32(message
, IFLA_MTU
, mtu
) >= 0);
66 assert_se(sd_netlink_call(rtnl
, message
, 0, NULL
) == 1);
67 assert_se(sd_netlink_message_rewind(message
) >= 0);
69 assert_se(sd_netlink_message_read_string(message
, IFLA_IFNAME
, &name_out
) >= 0);
70 assert_se(streq(name
, name_out
));
72 assert_se(sd_netlink_message_read_ether_addr(message
, IFLA_ADDRESS
, &mac_out
) >= 0);
73 assert_se(streq(mac
, ether_addr_to_string(&mac_out
, buffer
)));
75 assert_se(sd_netlink_message_read_u32(message
, IFLA_MTU
, &mtu_out
) >= 0);
76 assert_se(mtu
== mtu_out
);
79 static void test_link_get(sd_netlink
*rtnl
, int ifindex
) {
80 sd_netlink_message
*m
;
81 sd_netlink_message
*r
;
82 unsigned int mtu
= 1500;
86 struct ether_addr eth_data
;
88 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
92 assert_se(sd_netlink_message_append_u8(m
, IFLA_CARRIER
, 0) >= 0);
93 assert_se(sd_netlink_message_append_u8(m
, IFLA_OPERSTATE
, 0) >= 0);
94 assert_se(sd_netlink_message_append_u8(m
, IFLA_LINKMODE
, 0) >= 0);
97 assert_se(sd_netlink_message_append_u32(m
, IFLA_MTU
, mtu
) >= 0);
98 assert_se(sd_netlink_message_append_u32(m
, IFLA_GROUP
, 0) >= 0);
99 assert_se(sd_netlink_message_append_u32(m
, IFLA_TXQLEN
, 0) >= 0);
100 assert_se(sd_netlink_message_append_u32(m
, IFLA_NUM_TX_QUEUES
, 0) >= 0);
101 assert_se(sd_netlink_message_append_u32(m
, IFLA_NUM_RX_QUEUES
, 0) >= 0);
103 assert_se(sd_netlink_call(rtnl
, m
, -1, &r
) == 1);
105 assert_se(sd_netlink_message_read_string(r
, IFLA_IFNAME
, &str_data
) == 0);
107 assert_se(sd_netlink_message_read_u8(r
, IFLA_CARRIER
, &u8_data
) == 0);
108 assert_se(sd_netlink_message_read_u8(r
, IFLA_OPERSTATE
, &u8_data
) == 0);
109 assert_se(sd_netlink_message_read_u8(r
, IFLA_LINKMODE
, &u8_data
) == 0);
111 assert_se(sd_netlink_message_read_u32(r
, IFLA_MTU
, &u32_data
) == 0);
112 assert_se(sd_netlink_message_read_u32(r
, IFLA_GROUP
, &u32_data
) == 0);
113 assert_se(sd_netlink_message_read_u32(r
, IFLA_TXQLEN
, &u32_data
) == 0);
114 assert_se(sd_netlink_message_read_u32(r
, IFLA_NUM_TX_QUEUES
, &u32_data
) == 0);
115 assert_se(sd_netlink_message_read_u32(r
, IFLA_NUM_RX_QUEUES
, &u32_data
) == 0);
117 assert_se(sd_netlink_message_read_ether_addr(r
, IFLA_ADDRESS
, ð_data
) == 0);
119 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
120 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
124 static void test_address_get(sd_netlink
*rtnl
, int ifindex
) {
125 sd_netlink_message
*m
;
126 sd_netlink_message
*r
;
127 struct in_addr in_data
;
128 struct ifa_cacheinfo cache
;
131 assert_se(sd_rtnl_message_new_addr(rtnl
, &m
, RTM_GETADDR
, ifindex
, AF_INET
) >= 0);
134 assert_se(sd_netlink_call(rtnl
, m
, -1, &r
) == 1);
136 assert_se(sd_netlink_message_read_in_addr(r
, IFA_LOCAL
, &in_data
) == 0);
137 assert_se(sd_netlink_message_read_in_addr(r
, IFA_ADDRESS
, &in_data
) == 0);
138 assert_se(sd_netlink_message_read_string(r
, IFA_LABEL
, &label
) == 0);
139 assert_se(sd_netlink_message_read_cache_info(r
, IFA_CACHEINFO
, &cache
) == 0);
141 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
142 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
146 static void test_route(void) {
147 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
;
148 struct in_addr addr
, addr_data
;
149 uint32_t index
= 2, u32_data
;
152 r
= sd_rtnl_message_new_route(NULL
, &req
, RTM_NEWROUTE
, AF_INET
, RTPROT_STATIC
);
154 log_error_errno(r
, "Could not create RTM_NEWROUTE message: %m");
158 addr
.s_addr
= htonl(INADDR_LOOPBACK
);
160 r
= sd_netlink_message_append_in_addr(req
, RTA_GATEWAY
, &addr
);
162 log_error_errno(r
, "Could not append RTA_GATEWAY attribute: %m");
166 r
= sd_netlink_message_append_u32(req
, RTA_OIF
, index
);
168 log_error_errno(r
, "Could not append RTA_OIF attribute: %m");
172 assert_se(sd_netlink_message_rewind(req
) >= 0);
174 assert_se(sd_netlink_message_read_in_addr(req
, RTA_GATEWAY
, &addr_data
) >= 0);
175 assert_se(addr_data
.s_addr
== addr
.s_addr
);
177 assert_se(sd_netlink_message_read_u32(req
, RTA_OIF
, &u32_data
) >= 0);
178 assert_se(u32_data
== index
);
180 assert_se((req
= sd_netlink_message_unref(req
)) == NULL
);
183 static void test_multiple(void) {
184 sd_netlink
*rtnl1
, *rtnl2
;
186 assert_se(sd_netlink_open(&rtnl1
) >= 0);
187 assert_se(sd_netlink_open(&rtnl2
) >= 0);
189 rtnl1
= sd_netlink_unref(rtnl1
);
190 rtnl2
= sd_netlink_unref(rtnl2
);
193 static int link_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
194 char *ifname
= userdata
;
200 log_info("got link info about %s", ifname
);
203 assert_se(sd_netlink_message_read_string(m
, IFLA_IFNAME
, &data
) >= 0);
204 assert_se(streq(data
, "lo"));
209 static void test_event_loop(int ifindex
) {
210 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
211 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
212 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
215 ifname
= strdup("lo2");
218 assert_se(sd_netlink_open(&rtnl
) >= 0);
219 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
221 assert_se(sd_netlink_call_async(rtnl
, m
, link_handler
, ifname
, 0, NULL
) >= 0);
223 assert_se(sd_event_default(&event
) >= 0);
225 assert_se(sd_netlink_attach_event(rtnl
, event
, 0) >= 0);
227 assert_se(sd_event_run(event
, 0) >= 0);
229 assert_se(sd_netlink_detach_event(rtnl
) >= 0);
231 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
234 static int pipe_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
235 int *counter
= userdata
;
240 r
= sd_netlink_message_get_errno(m
);
242 log_info_errno(r
, "%d left in pipe. got reply: %m", *counter
);
249 static void test_async(int ifindex
) {
250 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
251 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
, *r
= NULL
;
255 ifname
= strdup("lo");
258 assert_se(sd_netlink_open(&rtnl
) >= 0);
260 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
262 assert_se(sd_netlink_call_async(rtnl
, m
, link_handler
, ifname
, 0, &serial
) >= 0);
264 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
265 assert_se(sd_netlink_process(rtnl
, &r
) >= 0);
267 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
270 static void test_pipe(int ifindex
) {
271 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
272 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m1
= NULL
, *m2
= NULL
;
275 assert_se(sd_netlink_open(&rtnl
) >= 0);
277 assert_se(sd_rtnl_message_new_link(rtnl
, &m1
, RTM_GETLINK
, ifindex
) >= 0);
278 assert_se(sd_rtnl_message_new_link(rtnl
, &m2
, RTM_GETLINK
, ifindex
) >= 0);
281 assert_se(sd_netlink_call_async(rtnl
, m1
, pipe_handler
, &counter
, 0, NULL
) >= 0);
284 assert_se(sd_netlink_call_async(rtnl
, m2
, pipe_handler
, &counter
, 0, NULL
) >= 0);
286 while (counter
> 0) {
287 assert_se(sd_netlink_wait(rtnl
, 0) >= 0);
288 assert_se(sd_netlink_process(rtnl
, NULL
) >= 0);
291 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
294 static void test_container(void) {
295 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
298 const char *string_data
;
300 assert_se(sd_rtnl_message_new_link(NULL
, &m
, RTM_NEWLINK
, 0) >= 0);
302 assert_se(sd_netlink_message_open_container(m
, IFLA_LINKINFO
) >= 0);
303 assert_se(sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "vlan") >= 0);
304 assert_se(sd_netlink_message_append_u16(m
, IFLA_VLAN_ID
, 100) >= 0);
305 assert_se(sd_netlink_message_close_container(m
) >= 0);
306 assert_se(sd_netlink_message_append_string(m
, IFLA_INFO_KIND
, "vlan") >= 0);
307 assert_se(sd_netlink_message_close_container(m
) >= 0);
308 assert_se(sd_netlink_message_close_container(m
) == -EINVAL
);
310 assert_se(sd_netlink_message_rewind(m
) >= 0);
312 assert_se(sd_netlink_message_enter_container(m
, IFLA_LINKINFO
) >= 0);
313 assert_se(sd_netlink_message_read_string(m
, IFLA_INFO_KIND
, &string_data
) >= 0);
314 assert_se(streq("vlan", string_data
));
316 assert_se(sd_netlink_message_enter_container(m
, IFLA_INFO_DATA
) >= 0);
317 assert_se(sd_netlink_message_read_u16(m
, IFLA_VLAN_ID
, &u16_data
) >= 0);
318 assert_se(sd_netlink_message_exit_container(m
) >= 0);
320 assert_se(sd_netlink_message_read_string(m
, IFLA_INFO_KIND
, &string_data
) >= 0);
321 assert_se(streq("vlan", string_data
));
322 assert_se(sd_netlink_message_exit_container(m
) >= 0);
324 assert_se(sd_netlink_message_read_u32(m
, IFLA_LINKINFO
, &u32_data
) < 0);
326 assert_se(sd_netlink_message_exit_container(m
) == -EINVAL
);
329 static void test_match(void) {
330 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
332 assert_se(sd_netlink_open(&rtnl
) >= 0);
334 assert_se(sd_netlink_add_match(rtnl
, RTM_NEWLINK
, link_handler
, NULL
) >= 0);
335 assert_se(sd_netlink_add_match(rtnl
, RTM_NEWLINK
, link_handler
, NULL
) >= 0);
337 assert_se(sd_netlink_remove_match(rtnl
, RTM_NEWLINK
, link_handler
, NULL
) == 1);
338 assert_se(sd_netlink_remove_match(rtnl
, RTM_NEWLINK
, link_handler
, NULL
) == 1);
339 assert_se(sd_netlink_remove_match(rtnl
, RTM_NEWLINK
, link_handler
, NULL
) == 0);
341 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);
344 static void test_get_addresses(sd_netlink
*rtnl
) {
345 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
346 sd_netlink_message
*m
;
348 assert_se(sd_rtnl_message_new_addr(rtnl
, &req
, RTM_GETADDR
, 0, AF_UNSPEC
) >= 0);
350 assert_se(sd_netlink_call(rtnl
, req
, 0, &reply
) >= 0);
352 for (m
= reply
; m
; m
= sd_netlink_message_next(m
)) {
354 unsigned char scope
, flags
;
357 assert_se(sd_netlink_message_get_type(m
, &type
) >= 0);
358 assert_se(type
== RTM_NEWADDR
);
360 assert_se(sd_rtnl_message_addr_get_ifindex(m
, &ifindex
) >= 0);
361 assert_se(sd_rtnl_message_addr_get_family(m
, &family
) >= 0);
362 assert_se(sd_rtnl_message_addr_get_scope(m
, &scope
) >= 0);
363 assert_se(sd_rtnl_message_addr_get_flags(m
, &flags
) >= 0);
365 assert_se(ifindex
> 0);
366 assert_se(IN_SET(family
, AF_INET
, AF_INET6
));
368 log_info("got IPv%u address on ifindex %i", family
== AF_INET
? 4: 6, ifindex
);
372 static void test_message(void) {
373 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
375 assert_se(rtnl_message_new_synthetic_error(-ETIMEDOUT
, 1, &m
) >= 0);
376 assert_se(sd_netlink_message_get_errno(m
) == -ETIMEDOUT
);
381 sd_netlink_message
*m
;
382 sd_netlink_message
*r
;
383 const char *string_data
;
397 assert_se(sd_netlink_open(&rtnl
) >= 0);
400 if_loopback
= (int) if_nametoindex("lo");
401 assert_se(if_loopback
> 0);
403 test_async(if_loopback
);
405 test_pipe(if_loopback
);
407 test_event_loop(if_loopback
);
409 test_link_configure(rtnl
, if_loopback
);
411 test_get_addresses(rtnl
);
413 test_message_link_bridge(rtnl
);
415 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, if_loopback
) >= 0);
418 assert_se(sd_netlink_message_get_type(m
, &type
) >= 0);
419 assert_se(type
== RTM_GETLINK
);
421 assert_se(sd_netlink_message_read_string(m
, IFLA_IFNAME
, &string_data
) == -EPERM
);
423 assert_se(sd_netlink_call(rtnl
, m
, 0, &r
) == 1);
424 assert_se(sd_netlink_message_get_type(r
, &type
) >= 0);
425 assert_se(type
== RTM_NEWLINK
);
427 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
429 assert_se(sd_netlink_call(rtnl
, m
, -1, &r
) == -EPERM
);
430 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
431 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
433 test_link_get(rtnl
, if_loopback
);
434 test_address_get(rtnl
, if_loopback
);
436 assert_se((m
= sd_netlink_message_unref(m
)) == NULL
);
437 assert_se((r
= sd_netlink_message_unref(r
)) == NULL
);
438 assert_se((rtnl
= sd_netlink_unref(rtnl
)) == NULL
);