1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/ether.h>
28 #include "socket-util.h"
29 #include "rtnl-util.h"
30 #include "event-util.h"
32 #include "rtnl-internal.h"
34 static void test_link_configure(sd_rtnl
*rtnl
, int ifindex
) {
35 _cleanup_rtnl_message_unref_ sd_rtnl_message
*message
;
36 const char *mac
= "98:fe:94:3f:c6:18", *name
= "test";
37 char buffer
[ETHER_ADDR_TO_STRING_MAX
];
38 unsigned int mtu
= 1450, mtu_out
;
40 struct ether_addr mac_out
;
42 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
43 assert_se(sd_rtnl_message_new_link(rtnl
, &message
, RTM_GETLINK
, ifindex
) >= 0);
44 assert_se(sd_rtnl_message_append_string(message
, IFLA_IFNAME
, name
) >= 0);
45 assert_se(sd_rtnl_message_append_ether_addr(message
, IFLA_ADDRESS
, ether_aton(mac
)) >= 0);
46 assert_se(sd_rtnl_message_append_u32(message
, IFLA_MTU
, mtu
) >= 0);
48 assert_se(sd_rtnl_call(rtnl
, message
, 0, NULL
) == 1);
49 assert_se(sd_rtnl_message_rewind(message
) >= 0);
51 assert_se(sd_rtnl_message_read_string(message
, IFLA_IFNAME
, &name_out
) >= 0);
52 assert_se(streq(name
, name_out
));
54 assert_se(sd_rtnl_message_read_ether_addr(message
, IFLA_ADDRESS
, &mac_out
) >= 0);
55 assert_se(streq(mac
, ether_addr_to_string(&mac_out
, buffer
)));
57 assert_se(sd_rtnl_message_read_u32(message
, IFLA_MTU
, &mtu_out
) >= 0);
58 assert_se(mtu
== mtu_out
);
61 static void test_link_get(sd_rtnl
*rtnl
, int ifindex
) {
64 unsigned int mtu
= 1500;
68 struct ether_addr eth_data
;
70 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
74 assert_se(sd_rtnl_message_append_u8(m
, IFLA_CARRIER
, 0) >= 0);
75 assert_se(sd_rtnl_message_append_u8(m
, IFLA_OPERSTATE
, 0) >= 0);
76 assert_se(sd_rtnl_message_append_u8(m
, IFLA_LINKMODE
, 0) >= 0);
79 assert_se(sd_rtnl_message_append_u32(m
, IFLA_MTU
, mtu
) >= 0);
80 assert_se(sd_rtnl_message_append_u32(m
, IFLA_GROUP
, 0) >= 0);
81 assert_se(sd_rtnl_message_append_u32(m
, IFLA_TXQLEN
, 0) >= 0);
82 assert_se(sd_rtnl_message_append_u32(m
, IFLA_NUM_TX_QUEUES
, 0) >= 0);
83 assert_se(sd_rtnl_message_append_u32(m
, IFLA_NUM_RX_QUEUES
, 0) >= 0);
85 assert_se(sd_rtnl_call(rtnl
, m
, -1, &r
) == 1);
87 assert_se(sd_rtnl_message_read_string(r
, IFLA_IFNAME
, &str_data
) == 0);
89 assert_se(sd_rtnl_message_read_u8(r
, IFLA_CARRIER
, &u8_data
) == 0);
90 assert_se(sd_rtnl_message_read_u8(r
, IFLA_OPERSTATE
, &u8_data
) == 0);
91 assert_se(sd_rtnl_message_read_u8(r
, IFLA_LINKMODE
, &u8_data
) == 0);
93 assert_se(sd_rtnl_message_read_u32(r
, IFLA_MTU
, &u32_data
) == 0);
94 assert_se(sd_rtnl_message_read_u32(r
, IFLA_GROUP
, &u32_data
) == 0);
95 assert_se(sd_rtnl_message_read_u32(r
, IFLA_TXQLEN
, &u32_data
) == 0);
96 assert_se(sd_rtnl_message_read_u32(r
, IFLA_NUM_TX_QUEUES
, &u32_data
) == 0);
97 assert_se(sd_rtnl_message_read_u32(r
, IFLA_NUM_RX_QUEUES
, &u32_data
) == 0);
99 assert_se(sd_rtnl_message_read_ether_addr(r
, IFLA_ADDRESS
, ð_data
) == 0);
101 assert_se(sd_rtnl_flush(rtnl
) >= 0);
102 assert_se((m
= sd_rtnl_message_unref(m
)) == NULL
);
103 assert_se((r
= sd_rtnl_message_unref(r
)) == NULL
);
107 static void test_address_get(sd_rtnl
*rtnl
, int ifindex
) {
110 struct in_addr in_data
;
111 struct ifa_cacheinfo cache
;
114 assert_se(sd_rtnl_message_new_addr(rtnl
, &m
, RTM_GETADDR
, ifindex
, AF_INET
) >= 0);
117 assert_se(sd_rtnl_call(rtnl
, m
, -1, &r
) == 1);
119 assert_se(sd_rtnl_message_read_in_addr(r
, IFA_LOCAL
, &in_data
) == 0);
120 assert_se(sd_rtnl_message_read_in_addr(r
, IFA_ADDRESS
, &in_data
) == 0);
121 assert_se(sd_rtnl_message_read_string(r
, IFA_LABEL
, &label
) == 0);
122 assert_se(sd_rtnl_message_read_cache_info(r
, IFA_CACHEINFO
, &cache
) == 0);
124 assert_se(sd_rtnl_flush(rtnl
) >= 0);
125 assert_se((m
= sd_rtnl_message_unref(m
)) == NULL
);
126 assert_se((r
= sd_rtnl_message_unref(r
)) == NULL
);
130 static void test_route(void) {
131 _cleanup_rtnl_message_unref_ sd_rtnl_message
*req
;
132 struct in_addr addr
, addr_data
;
133 uint32_t index
= 2, u32_data
;
136 r
= sd_rtnl_message_new_route(NULL
, &req
, RTM_NEWROUTE
, AF_INET
, RTPROT_STATIC
);
138 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r
));
142 addr
.s_addr
= htonl(INADDR_LOOPBACK
);
144 r
= sd_rtnl_message_append_in_addr(req
, RTA_GATEWAY
, &addr
);
146 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r
));
150 r
= sd_rtnl_message_append_u32(req
, RTA_OIF
, index
);
152 log_error("Could not append RTA_OIF attribute: %s", strerror(-r
));
156 assert_se(sd_rtnl_message_rewind(req
) >= 0);
158 assert_se(sd_rtnl_message_read_in_addr(req
, RTA_GATEWAY
, &addr_data
) >= 0);
159 assert_se(addr_data
.s_addr
== addr
.s_addr
);
161 assert_se(sd_rtnl_message_read_u32(req
, RTA_OIF
, &u32_data
) >= 0);
162 assert_se(u32_data
== index
);
164 assert_se((req
= sd_rtnl_message_unref(req
)) == NULL
);
167 static void test_multiple(void) {
168 sd_rtnl
*rtnl1
, *rtnl2
;
170 assert_se(sd_rtnl_open(&rtnl1
, 0) >= 0);
171 assert_se(sd_rtnl_open(&rtnl2
, 0) >= 0);
173 rtnl1
= sd_rtnl_unref(rtnl1
);
174 rtnl2
= sd_rtnl_unref(rtnl2
);
177 static int link_handler(sd_rtnl
*rtnl
, sd_rtnl_message
*m
, void *userdata
) {
178 char *ifname
= userdata
;
184 log_info("got link info about %s", ifname
);
187 assert_se(sd_rtnl_message_read_string(m
, IFLA_IFNAME
, &data
) >= 0);
188 assert_se(streq(data
, "lo"));
193 static void test_event_loop(int ifindex
) {
194 _cleanup_event_unref_ sd_event
*event
= NULL
;
195 _cleanup_rtnl_unref_ sd_rtnl
*rtnl
= NULL
;
196 _cleanup_rtnl_message_unref_ sd_rtnl_message
*m
= NULL
;
199 ifname
= strdup("lo2");
202 assert_se(sd_rtnl_open(&rtnl
, 0) >= 0);
203 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
205 assert_se(sd_rtnl_call_async(rtnl
, m
, &link_handler
, ifname
, 0, NULL
) >= 0);
207 assert_se(sd_event_default(&event
) >= 0);
209 assert_se(sd_rtnl_attach_event(rtnl
, event
, 0) >= 0);
211 assert_se(sd_event_run(event
, 0) >= 0);
213 assert_se(sd_rtnl_detach_event(rtnl
) >= 0);
215 assert_se((rtnl
= sd_rtnl_unref(rtnl
)) == NULL
);
218 static int pipe_handler(sd_rtnl
*rtnl
, sd_rtnl_message
*m
, void *userdata
) {
219 int *counter
= userdata
;
224 r
= sd_rtnl_message_get_errno(m
);
226 log_info("%d left in pipe. got reply: %s", *counter
, strerror(-r
));
233 static void test_async(int ifindex
) {
234 _cleanup_rtnl_unref_ sd_rtnl
*rtnl
= NULL
;
235 _cleanup_rtnl_message_unref_ sd_rtnl_message
*m
= NULL
, *r
= NULL
;
239 ifname
= strdup("lo");
242 assert_se(sd_rtnl_open(&rtnl
, 0) >= 0);
244 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, ifindex
) >= 0);
246 assert_se(sd_rtnl_call_async(rtnl
, m
, &link_handler
, ifname
, 0, &serial
) >= 0);
248 assert_se(sd_rtnl_wait(rtnl
, 0) >= 0);
249 assert_se(sd_rtnl_process(rtnl
, &r
) >= 0);
251 assert_se((rtnl
= sd_rtnl_unref(rtnl
)) == NULL
);
254 static void test_pipe(int ifindex
) {
255 _cleanup_rtnl_unref_ sd_rtnl
*rtnl
= NULL
;
256 _cleanup_rtnl_message_unref_ sd_rtnl_message
*m1
= NULL
, *m2
= NULL
;
259 assert_se(sd_rtnl_open(&rtnl
, 0) >= 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_rtnl_call_async(rtnl
, m1
, &pipe_handler
, &counter
, 0, NULL
) >= 0);
268 assert_se(sd_rtnl_call_async(rtnl
, m2
, &pipe_handler
, &counter
, 0, NULL
) >= 0);
270 while (counter
> 0) {
271 assert_se(sd_rtnl_wait(rtnl
, 0) >= 0);
272 assert_se(sd_rtnl_process(rtnl
, NULL
) >= 0);
275 assert_se((rtnl
= sd_rtnl_unref(rtnl
)) == NULL
);
278 static void test_container(void) {
279 _cleanup_rtnl_message_unref_ sd_rtnl_message
*m
= NULL
;
282 const char *string_data
;
284 assert_se(sd_rtnl_message_new_link(NULL
, &m
, RTM_NEWLINK
, 0) >= 0);
286 assert_se(sd_rtnl_message_open_container(m
, IFLA_LINKINFO
) >= 0);
287 assert_se(sd_rtnl_message_open_container_union(m
, IFLA_INFO_DATA
, "vlan") >= 0);
288 assert_se(sd_rtnl_message_append_u16(m
, IFLA_VLAN_ID
, 100) >= 0);
289 assert_se(sd_rtnl_message_close_container(m
) >= 0);
290 assert_se(sd_rtnl_message_append_string(m
, IFLA_INFO_KIND
, "vlan") >= 0);
291 assert_se(sd_rtnl_message_close_container(m
) >= 0);
292 assert_se(sd_rtnl_message_close_container(m
) == -EINVAL
);
294 assert_se(sd_rtnl_message_rewind(m
) >= 0);
296 assert_se(sd_rtnl_message_enter_container(m
, IFLA_LINKINFO
) >= 0);
297 assert_se(sd_rtnl_message_read_string(m
, IFLA_INFO_KIND
, &string_data
) >= 0);
298 assert_se(streq("vlan", string_data
));
300 assert_se(sd_rtnl_message_enter_container(m
, IFLA_INFO_DATA
) >= 0);
301 assert_se(sd_rtnl_message_read_u16(m
, IFLA_VLAN_ID
, &u16_data
) >= 0);
302 assert_se(sd_rtnl_message_exit_container(m
) >= 0);
304 assert_se(sd_rtnl_message_read_string(m
, IFLA_INFO_KIND
, &string_data
) >= 0);
305 assert_se(streq("vlan", string_data
));
306 assert_se(sd_rtnl_message_exit_container(m
) >= 0);
308 assert_se(sd_rtnl_message_read_u32(m
, IFLA_LINKINFO
, &u32_data
) < 0);
310 assert_se(sd_rtnl_message_exit_container(m
) == -EINVAL
);
313 static void test_match(void) {
314 _cleanup_rtnl_unref_ sd_rtnl
*rtnl
= NULL
;
316 assert_se(sd_rtnl_open(&rtnl
, 0) >= 0);
318 assert_se(sd_rtnl_add_match(rtnl
, RTM_NEWLINK
, &link_handler
, NULL
) >= 0);
319 assert_se(sd_rtnl_add_match(rtnl
, RTM_NEWLINK
, &link_handler
, NULL
) >= 0);
321 assert_se(sd_rtnl_remove_match(rtnl
, RTM_NEWLINK
, &link_handler
, NULL
) == 1);
322 assert_se(sd_rtnl_remove_match(rtnl
, RTM_NEWLINK
, &link_handler
, NULL
) == 1);
323 assert_se(sd_rtnl_remove_match(rtnl
, RTM_NEWLINK
, &link_handler
, NULL
) == 0);
325 assert_se((rtnl
= sd_rtnl_unref(rtnl
)) == NULL
);
328 static void test_get_addresses(sd_rtnl
*rtnl
) {
329 _cleanup_rtnl_message_unref_ sd_rtnl_message
*req
= NULL
, *reply
= NULL
;
332 assert_se(sd_rtnl_message_new_addr(rtnl
, &req
, RTM_GETADDR
, 0, AF_UNSPEC
) >= 0);
334 assert_se(sd_rtnl_call(rtnl
, req
, 0, &reply
) >= 0);
336 for (m
= reply
; m
; m
= sd_rtnl_message_next(m
)) {
338 unsigned char scope
, flags
;
341 assert_se(sd_rtnl_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(family
== AF_INET
|| family
== AF_INET6
);
352 log_info("got IPv%u address on ifindex %i", family
== AF_INET
? 4: 6, ifindex
);
360 const char *string_data
;
372 assert_se(sd_rtnl_open(&rtnl
, 0) >= 0);
375 if_loopback
= (int) if_nametoindex("lo");
376 assert_se(if_loopback
> 0);
378 test_async(if_loopback
);
380 test_pipe(if_loopback
);
382 test_event_loop(if_loopback
);
384 test_link_configure(rtnl
, if_loopback
);
386 test_get_addresses(rtnl
);
388 assert_se(sd_rtnl_message_new_link(rtnl
, &m
, RTM_GETLINK
, if_loopback
) >= 0);
391 assert_se(sd_rtnl_message_get_type(m
, &type
) >= 0);
392 assert_se(type
== RTM_GETLINK
);
394 assert_se(sd_rtnl_message_read_string(m
, IFLA_IFNAME
, &string_data
) == -EPERM
);
396 assert_se(sd_rtnl_call(rtnl
, m
, 0, &r
) == 1);
397 assert_se(sd_rtnl_message_get_type(r
, &type
) >= 0);
398 assert_se(type
== RTM_NEWLINK
);
400 assert_se((r
= sd_rtnl_message_unref(r
)) == NULL
);
402 assert_se(sd_rtnl_call(rtnl
, m
, -1, &r
) == -EPERM
);
403 assert_se((m
= sd_rtnl_message_unref(m
)) == NULL
);
404 assert_se((r
= sd_rtnl_message_unref(r
)) == NULL
);
406 test_link_get(rtnl
, if_loopback
);
407 test_address_get(rtnl
, if_loopback
);
409 assert_se(sd_rtnl_flush(rtnl
) >= 0);
410 assert_se((m
= sd_rtnl_message_unref(m
)) == NULL
);
411 assert_se((r
= sd_rtnl_message_unref(r
)) == NULL
);
412 assert_se((rtnl
= sd_rtnl_unref(rtnl
)) == NULL
);