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"
32 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
33 _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;
39 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
40 assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
41 assert_se(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
42 assert_se(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
43 assert_se(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
45 assert_se(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
47 assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
48 assert_se(type == IFLA_IFNAME);
49 assert_se(streq(name, (char *) data));
51 assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
52 assert_se(type == IFLA_ADDRESS);
53 assert_se(streq(mac, ether_ntoa(data)));
55 assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
56 assert_se(type == IFLA_MTU);
57 assert_se(mtu == *(unsigned int *) data);
60 static void test_link_get(sd_rtnl *rtnl, int ifindex) {
63 unsigned int mtu = 1500;
64 unsigned int *mtu_reply;
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);
86 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
87 assert_se(type == IFLA_CARRIER);
89 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
90 assert_se(type == IFLA_OPERSTATE);
92 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
93 assert_se(type == IFLA_LINKMODE);
96 assert_se(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
97 assert_se(type == IFLA_MTU);
98 assert_se(*mtu_reply == mtu);
100 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
101 assert_se(type == IFLA_GROUP);
103 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
104 assert_se(type == IFLA_TXQLEN);
106 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
107 assert_se(type == IFLA_NUM_TX_QUEUES);
109 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
110 assert_se(type == IFLA_NUM_RX_QUEUES);
112 while (sd_rtnl_message_read(r, &type, &data) > 0) {
115 // assert_se(*(unsigned int *) data == 65536);
118 // assert_se(streq((char *) data, "noqueue"));
121 assert_se(streq((char *) data, "lo"));
126 assert_se(sd_rtnl_flush(rtnl) >= 0);
127 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
131 static void test_route(void) {
132 _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
139 r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
141 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
145 addr.s_addr = htonl(INADDR_LOOPBACK);
147 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
149 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
153 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
155 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
159 assert_se(rtnl_message_seal(NULL, req) >= 0);
161 assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
162 assert_se(type == RTA_GATEWAY);
163 assert_se(((struct in_addr *)data)->s_addr == addr.s_addr);
165 assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
166 assert_se(type == RTA_OIF);
167 assert_se(*(uint32_t *) data == index);
170 static void test_multiple(void) {
171 sd_rtnl *rtnl1, *rtnl2;
173 assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
174 assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
176 rtnl1 = sd_rtnl_unref(rtnl1);
177 rtnl2 = sd_rtnl_unref(rtnl2);
180 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
183 char *ifname = userdata;
188 log_info("got link info about %s", ifname);
191 while (sd_rtnl_message_read(m, &type, &data) > 0) {
194 // assert_se(*(unsigned int *) data == 65536);
197 // assert_se(streq((char *) data, "noqueue"));
200 assert_se(streq((char *) data, "lo"));
208 static void test_event_loop(int ifindex) {
209 _cleanup_event_unref_ sd_event *event = NULL;
210 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
211 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
214 ifname = strdup("lo2");
217 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
218 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
220 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
222 assert_se(sd_event_default(&event) >= 0);
224 assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
226 assert_se(sd_event_run(event, 0) >= 0);
228 assert_se(sd_rtnl_detach_event(rtnl) >= 0);
231 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
232 int *counter = userdata;
236 log_info("got reply, %d left in pipe", *counter);
238 return sd_rtnl_message_get_errno(m);
241 static void test_async(int ifindex) {
242 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
243 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
247 ifname = strdup("lo");
250 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
252 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
254 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
256 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
257 assert_se(sd_rtnl_process(rtnl, &r) >= 0);
260 static void test_pipe(int ifindex) {
261 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
262 _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
265 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
267 assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
268 assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
271 assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
274 assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
276 while (counter > 0) {
277 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
278 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
282 static void test_container(void) {
283 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
287 assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
289 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
290 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
291 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
292 assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
293 assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
294 assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
295 assert_se(sd_rtnl_message_close_container(m) >= 0);
296 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
297 assert_se(sd_rtnl_message_close_container(m) >= 0);
298 assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
300 assert_se(rtnl_message_seal(NULL, m) >= 0);
302 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
303 assert_se(type == IFLA_LINKINFO);
304 assert_se(data == NULL);
305 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
306 assert_se(type == IFLA_INFO_KIND);
307 assert_se(streq("kind", (char *)data));
308 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
309 assert_se(type == IFLA_INFO_DATA);
310 assert_se(data == NULL);
311 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
312 assert_se(type == IFLA_VLAN_ID);
313 assert_se(*(uint16_t *)data == 100);
314 assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
315 assert_se(sd_rtnl_message_exit_container(m) >= 0);
316 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
317 assert_se(type == IFLA_INFO_KIND);
318 assert_se(streq("kind", (char *)data));
319 assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
320 assert_se(sd_rtnl_message_exit_container(m) >= 0);
321 assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
324 static void test_match(void) {
325 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
327 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
329 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
330 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
332 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
333 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
334 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
353 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
356 if_loopback = (int) if_nametoindex("lo");
357 assert_se(if_loopback > 0);
359 test_async(if_loopback);
361 test_pipe(if_loopback);
363 test_event_loop(if_loopback);
365 test_link_configure(rtnl, if_loopback);
367 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
370 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
371 assert_se(type == RTM_GETLINK);
373 assert_se(sd_rtnl_message_read(m, &type, &data) == -EPERM);
375 assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
376 assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
377 assert_se(type == RTM_NEWLINK);
379 assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
380 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
382 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
383 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
384 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
386 test_link_get(rtnl, if_loopback);
388 assert_se(sd_rtnl_flush(rtnl) >= 0);
389 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
390 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
391 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);