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>
27 #include "socket-util.h"
28 #include "rtnl-util.h"
29 #include "event-util.h"
31 #include "rtnl-internal.h"
33 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
34 _cleanup_rtnl_message_unref_ sd_rtnl_message *message;
35 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
36 unsigned int mtu = 1450, mtu_out;
38 struct ether_addr mac_out;
40 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
41 assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
42 assert_se(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
43 assert_se(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
44 assert_se(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
46 assert_se(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
47 assert_se(sd_rtnl_message_rewind(message) >= 0);
49 assert_se(sd_rtnl_message_read_string(message, IFLA_IFNAME, &name_out) >= 0);
50 assert_se(streq(name, name_out));
52 assert_se(sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0);
53 assert_se(streq(mac, ether_ntoa(&mac_out)));
55 assert_se(sd_rtnl_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0);
56 assert_se(mtu == mtu_out);
59 static void test_link_get(sd_rtnl *rtnl, int ifindex) {
62 unsigned int mtu = 1500;
66 struct ether_addr eth_data;
68 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
72 assert_se(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
73 assert_se(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
74 assert_se(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
77 assert_se(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
78 assert_se(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0);
79 assert_se(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
80 assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
81 assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
83 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
85 assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
87 assert_se(sd_rtnl_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0);
88 assert_se(sd_rtnl_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0);
89 assert_se(sd_rtnl_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0);
91 assert_se(sd_rtnl_message_read_u32(r, IFLA_MTU, &u32_data) == 0);
92 assert_se(sd_rtnl_message_read_u32(r, IFLA_GROUP, &u32_data) == 0);
93 assert_se(sd_rtnl_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0);
94 assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0);
95 assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0);
97 assert_se(sd_rtnl_message_read_ether_addr(r, IFLA_ADDRESS, ð_data) == 0);
99 assert_se(sd_rtnl_flush(rtnl) >= 0);
100 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
101 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
105 static void test_address_get(sd_rtnl *rtnl, int ifindex) {
108 struct in_addr in_data;
111 assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
114 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
116 assert_se(sd_rtnl_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0);
117 assert_se(sd_rtnl_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0);
118 assert_se(sd_rtnl_message_read_string(r, IFA_LABEL, &label) == 0);
120 assert_se(sd_rtnl_flush(rtnl) >= 0);
121 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
122 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
126 static void test_route(void) {
127 _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
128 struct in_addr addr, addr_data;
129 uint32_t index = 2, u32_data;
132 r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
134 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
138 addr.s_addr = htonl(INADDR_LOOPBACK);
140 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
142 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
146 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
148 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
152 assert_se(sd_rtnl_message_rewind(req) >= 0);
154 assert_se(sd_rtnl_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
155 assert_se(addr_data.s_addr == addr.s_addr);
157 assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
158 assert_se(u32_data == index);
160 assert_se((req = sd_rtnl_message_unref(req)) == NULL);
163 static void test_multiple(void) {
164 sd_rtnl *rtnl1, *rtnl2;
166 assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
167 assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
169 rtnl1 = sd_rtnl_unref(rtnl1);
170 rtnl2 = sd_rtnl_unref(rtnl2);
173 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
174 char *ifname = userdata, *data;
179 log_info("got link info about %s", ifname);
182 assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &data) >= 0);
183 assert_se(streq(data, "lo"));
188 static void test_event_loop(int ifindex) {
189 _cleanup_event_unref_ sd_event *event = NULL;
190 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
191 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
194 ifname = strdup("lo2");
197 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
198 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
200 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
202 assert_se(sd_event_default(&event) >= 0);
204 assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
206 assert_se(sd_event_run(event, 0) >= 0);
208 assert_se(sd_rtnl_detach_event(rtnl) >= 0);
210 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
213 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
214 int *counter = userdata;
219 r = sd_rtnl_message_get_errno(m);
221 log_info("%d left in pipe. got reply: %s", *counter, strerror(-r));
228 static void test_async(int ifindex) {
229 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
230 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
234 ifname = strdup("lo");
237 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
239 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
241 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
243 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
244 assert_se(sd_rtnl_process(rtnl, &r) >= 0);
246 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
249 static void test_pipe(int ifindex) {
250 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
251 _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
254 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
256 assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
257 assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
260 assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
263 assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
265 while (counter > 0) {
266 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
267 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
270 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
273 static void test_container(void) {
274 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
279 assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
281 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
282 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
283 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
284 assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
285 assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
286 assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
287 assert_se(sd_rtnl_message_close_container(m) >= 0);
288 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
289 assert_se(sd_rtnl_message_close_container(m) >= 0);
290 assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
292 assert_se(sd_rtnl_message_rewind(m) >= 0);
294 assert_se(sd_rtnl_message_enter_container(m, IFLA_LINKINFO) >= 0);
295 assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
296 assert_se(streq("vlan", string_data));
298 assert_se(sd_rtnl_message_enter_container(m, IFLA_INFO_DATA) >= 0);
299 assert_se(sd_rtnl_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0);
300 assert_se(sd_rtnl_message_exit_container(m) >= 0);
302 assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
303 assert_se(streq("vlan", string_data));
304 assert_se(sd_rtnl_message_exit_container(m) >= 0);
306 assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) == 0);
308 assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
311 static void test_match(void) {
312 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
314 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
316 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
317 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
319 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
320 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
321 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
323 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
342 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
345 if_loopback = (int) if_nametoindex("lo");
346 assert_se(if_loopback > 0);
348 test_async(if_loopback);
350 test_pipe(if_loopback);
352 test_event_loop(if_loopback);
354 test_link_configure(rtnl, if_loopback);
356 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
359 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
360 assert_se(type == RTM_GETLINK);
362 assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
364 assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
365 assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
366 assert_se(type == RTM_NEWLINK);
368 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
370 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
371 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
372 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
374 test_link_get(rtnl, if_loopback);
375 test_address_get(rtnl, if_loopback);
377 assert_se(sd_rtnl_flush(rtnl) >= 0);
378 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
379 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
380 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);