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;
36 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
37 unsigned int mtu = 1450;
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);
48 assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
49 assert_se(type == IFLA_IFNAME);
50 assert_se(streq(name, (char *) data));
52 assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
53 assert_se(type == IFLA_ADDRESS);
54 assert_se(streq(mac, ether_ntoa(data)));
56 assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
57 assert_se(type == IFLA_MTU);
58 assert_se(mtu == *(unsigned int *) data);
61 static void test_link_get(sd_rtnl *rtnl, int ifindex) {
64 unsigned int mtu = 1500;
65 unsigned int *mtu_reply;
72 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
76 assert_se(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
77 assert_se(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
78 assert_se(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
81 assert_se(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
82 assert_se(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0);
83 assert_se(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
84 assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
85 assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
87 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
90 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
91 assert_se(type == IFLA_CARRIER);
93 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
94 assert_se(type == IFLA_OPERSTATE);
96 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
97 assert_se(type == IFLA_LINKMODE);
100 assert_se(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
101 assert_se(type == IFLA_MTU);
102 assert_se(*mtu_reply == mtu);
104 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
105 assert_se(type == IFLA_GROUP);
107 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
108 assert_se(type == IFLA_TXQLEN);
110 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
111 assert_se(type == IFLA_NUM_TX_QUEUES);
113 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
114 assert_se(type == IFLA_NUM_RX_QUEUES);
116 while (sd_rtnl_message_read(r, &type, &data) > 0) {
119 // assert_se(*(unsigned int *) data == 65536);
122 // assert_se(streq((char *) data, "noqueue"));
125 assert_se(streq((char *) data, "lo"));
130 assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
132 assert_se(sd_rtnl_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0);
133 assert_se(sd_rtnl_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0);
134 assert_se(sd_rtnl_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0);
136 assert_se(sd_rtnl_message_read_u32(r, IFLA_MTU, &u32_data) == 0);
137 assert_se(sd_rtnl_message_read_u32(r, IFLA_GROUP, &u32_data) == 0);
138 assert_se(sd_rtnl_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0);
139 assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0);
140 assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0);
142 assert_se(sd_rtnl_flush(rtnl) >= 0);
143 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
144 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
147 static void test_route(void) {
148 _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
157 r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
159 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
163 addr.s_addr = htonl(INADDR_LOOPBACK);
165 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
167 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
171 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
173 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
177 assert_se(rtnl_message_seal(NULL, req) >= 0);
179 assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
180 assert_se(type == RTA_GATEWAY);
181 assert_se(((struct in_addr *)data)->s_addr == addr.s_addr);
183 assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
184 assert_se(type == RTA_OIF);
185 assert_se(*(uint32_t *) data == index);
187 rtm = NLMSG_DATA(req->hdr);
188 r = rtnl_message_parse(req,
193 RTM_PAYLOAD(req->hdr));
195 assert_se(sd_rtnl_message_read_u32(req, RTA_GATEWAY, &u32_data) == 0);
196 assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) == 0);
198 assert_se((req = sd_rtnl_message_unref(req)) == NULL);
201 static void test_multiple(void) {
202 sd_rtnl *rtnl1, *rtnl2;
204 assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
205 assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
207 rtnl1 = sd_rtnl_unref(rtnl1);
208 rtnl2 = sd_rtnl_unref(rtnl2);
211 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
214 char *ifname = userdata;
219 log_info("got link info about %s", ifname);
222 while (sd_rtnl_message_read(m, &type, &data) > 0) {
225 // assert_se(*(unsigned int *) data == 65536);
228 // assert_se(streq((char *) data, "noqueue"));
231 assert_se(streq((char *) data, "lo"));
239 static void test_event_loop(int ifindex) {
240 _cleanup_event_unref_ sd_event *event = NULL;
241 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
242 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
245 ifname = strdup("lo2");
248 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
249 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
251 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
253 assert_se(sd_event_default(&event) >= 0);
255 assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
257 assert_se(sd_event_run(event, 0) >= 0);
259 assert_se(sd_rtnl_detach_event(rtnl) >= 0);
261 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
264 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
265 int *counter = userdata;
269 log_info("got reply, %d left in pipe", *counter);
271 return sd_rtnl_message_get_errno(m);
274 static void test_async(int ifindex) {
275 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
276 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
280 ifname = strdup("lo");
283 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
285 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
287 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
289 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
290 assert_se(sd_rtnl_process(rtnl, &r) >= 0);
292 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
295 static void test_pipe(int ifindex) {
296 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
297 _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
300 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
302 assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
303 assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
306 assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
309 assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
311 while (counter > 0) {
312 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
313 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
316 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
319 static void test_container(void) {
320 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
325 struct ifinfomsg *ifi;
327 assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
329 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
330 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
331 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
332 assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
333 assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
334 assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
335 assert_se(sd_rtnl_message_close_container(m) >= 0);
336 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
337 assert_se(sd_rtnl_message_close_container(m) >= 0);
338 assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
340 assert_se(rtnl_message_seal(NULL, m) >= 0);
342 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
343 assert_se(type == IFLA_LINKINFO);
344 assert_se(data == NULL);
346 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
347 assert_se(type == IFLA_INFO_KIND);
348 assert_se(streq("kind", (char *)data));
349 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
350 assert_se(type == IFLA_INFO_DATA);
351 assert_se(data == NULL);
352 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
353 assert_se(type == IFLA_VLAN_ID);
354 assert_se(*(uint16_t *)data == 100);
355 assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
356 assert_se(sd_rtnl_message_exit_container(m) >= 0);
357 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
358 assert_se(type == IFLA_INFO_KIND);
359 assert_se(streq("kind", (char *)data));
360 assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
361 assert_se(sd_rtnl_message_exit_container(m) >= 0);
364 ifi = NLMSG_DATA(m->hdr);
365 r = rtnl_message_parse(m,
370 IFLA_PAYLOAD(m->hdr));
374 assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) == 0);
376 assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
379 static void test_match(void) {
380 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
382 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
384 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
385 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
387 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
388 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
389 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
391 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
410 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
413 if_loopback = (int) if_nametoindex("lo");
414 assert_se(if_loopback > 0);
416 test_async(if_loopback);
418 test_pipe(if_loopback);
420 test_event_loop(if_loopback);
422 test_link_configure(rtnl, if_loopback);
424 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
427 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
428 assert_se(type == RTM_GETLINK);
430 assert_se(sd_rtnl_message_read(m, &type, &data) == -EPERM);
432 assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
433 assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
434 assert_se(type == RTM_NEWLINK);
436 assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
437 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
439 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
440 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
441 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
443 test_link_get(rtnl, if_loopback);
445 assert_se(sd_rtnl_flush(rtnl) >= 0);
446 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
447 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
448 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);