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 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
32 _cleanup_rtnl_message_unref_ sd_rtnl_message *message;
34 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
35 unsigned int mtu = 1450;
38 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
39 assert(sd_rtnl_message_new_link(RTM_GETLINK, ifindex, &message) >= 0);
40 assert(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
41 assert(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
42 assert(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
44 assert(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
46 assert(sd_rtnl_message_read(message, &type, &data) > 0);
47 assert(type == IFLA_IFNAME);
48 assert(streq(name, (char *) data));
50 assert(sd_rtnl_message_read(message, &type, &data) > 0);
51 assert(type == IFLA_ADDRESS);
52 assert(streq(mac, ether_ntoa(data)));
54 assert(sd_rtnl_message_read(message, &type, &data) > 0);
55 assert(type == IFLA_MTU);
56 assert(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(sd_rtnl_message_new_link(RTM_GETLINK, ifindex, &m) >= 0);
72 assert(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
73 assert(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
74 assert(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
77 assert(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
78 assert(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0);
79 assert(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
80 assert(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
81 assert(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
83 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
86 assert(sd_rtnl_message_read(m, &type, &data) == 1);
87 assert(type == IFLA_CARRIER);
89 assert(sd_rtnl_message_read(m, &type, &data) == 1);
90 assert(type == IFLA_OPERSTATE);
92 assert(sd_rtnl_message_read(m, &type, &data) == 1);
93 assert(type == IFLA_LINKMODE);
96 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
97 assert(type == IFLA_MTU);
98 assert(*mtu_reply == mtu);
100 assert(sd_rtnl_message_read(m, &type, &data) == 1);
101 assert(type == IFLA_GROUP);
103 assert(sd_rtnl_message_read(m, &type, &data) == 1);
104 assert(type == IFLA_TXQLEN);
106 assert(sd_rtnl_message_read(m, &type, &data) == 1);
107 assert(type == IFLA_NUM_TX_QUEUES);
109 assert(sd_rtnl_message_read(m, &type, &data) == 1);
110 assert(type == IFLA_NUM_RX_QUEUES);
112 while (sd_rtnl_message_read(r, &type, &data) > 0) {
115 // assert(*(unsigned int *) data == 65536);
118 // assert(streq((char *) data, "noqueue"));
121 assert(streq((char *) data, "lo"));
126 assert(sd_rtnl_flush(rtnl) >= 0);
127 assert((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(RTM_NEWROUTE, AF_INET, &req);
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(rtnl_message_seal(NULL, req) >= 0);
161 assert(sd_rtnl_message_read(req, &type, &data) > 0);
162 assert(type == RTA_GATEWAY);
163 assert(((struct in_addr *)data)->s_addr == addr.s_addr);
165 assert(sd_rtnl_message_read(req, &type, &data) > 0);
166 assert(type == RTA_OIF);
167 assert(*(uint32_t *) data == index);
170 static void test_multiple(void) {
171 sd_rtnl *rtnl1, *rtnl2;
173 assert(sd_rtnl_open(0, &rtnl1) >= 0);
174 assert(sd_rtnl_open(0, &rtnl2) >= 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(*(unsigned int *) data == 65536);
197 // assert(streq((char *) data, "noqueue"));
200 assert(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(sd_rtnl_open(0, &rtnl) >= 0);
218 assert(sd_rtnl_message_new_link(RTM_GETLINK, ifindex, &m) >= 0);
220 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
222 assert(sd_event_default(&event) >= 0);
224 assert(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
226 assert(sd_event_run(event, 0) >= 0);
228 assert(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(sd_rtnl_open(0, &rtnl) >= 0);
252 assert(sd_rtnl_message_new_link(RTM_GETLINK, ifindex, &m) >= 0);
254 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
256 assert(sd_rtnl_wait(rtnl, 0) >= 0);
257 assert(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(sd_rtnl_open(0, &rtnl) >= 0);
267 assert(sd_rtnl_message_new_link(RTM_GETLINK, ifindex, &m1) >= 0);
268 assert(sd_rtnl_message_new_link(RTM_GETLINK, ifindex, &m2) >= 0);
271 assert(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
274 assert(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
276 while (counter > 0) {
277 assert(sd_rtnl_wait(rtnl, 0) >= 0);
278 assert(sd_rtnl_process(rtnl, NULL) >= 0);
282 static void test_container(void) {
283 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
287 assert(sd_rtnl_message_new_link(RTM_NEWLINK, 0, &m) >= 0);
289 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
290 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
291 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
292 assert(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
293 assert(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
294 assert(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
295 assert(sd_rtnl_message_close_container(m) >= 0);
296 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
297 assert(sd_rtnl_message_close_container(m) >= 0);
298 assert(sd_rtnl_message_close_container(m) == -EINVAL);
300 assert(rtnl_message_seal(NULL, m) >= 0);
302 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
303 assert(type == IFLA_LINKINFO);
304 assert(data == NULL);
305 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
306 assert(type == IFLA_INFO_KIND);
307 assert(streq("kind", (char *)data));
308 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
309 assert(type == IFLA_INFO_DATA);
310 assert(data == NULL);
311 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
312 assert(type == IFLA_VLAN_ID);
313 assert(*(uint16_t *)data == 100);
314 assert(sd_rtnl_message_read(m, &type, &data) == 0);
315 assert(sd_rtnl_message_exit_container(m) >= 0);
316 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
317 assert(type == IFLA_INFO_KIND);
318 assert(streq("kind", (char *)data));
319 assert(sd_rtnl_message_read(m, &type, &data) == 0);
320 assert(sd_rtnl_message_exit_container(m) >= 0);
321 assert(sd_rtnl_message_exit_container(m) == -EINVAL);
324 static void test_match(void) {
325 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
327 assert(sd_rtnl_open(0, &rtnl) >= 0);
329 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
330 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
332 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
333 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
334 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
353 assert(sd_rtnl_open(0, &rtnl) >= 0);
356 if_loopback = (int) if_nametoindex("lo");
357 assert(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(sd_rtnl_message_new_link(RTM_GETLINK, if_loopback, &m) >= 0);
370 assert(sd_rtnl_message_get_type(m, &type) >= 0);
371 assert(type == RTM_GETLINK);
373 assert(sd_rtnl_message_read(m, &type, &data) == -EPERM);
375 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
376 assert(sd_rtnl_message_get_type(r, &type) >= 0);
377 assert(type == RTM_NEWLINK);
379 assert(sd_rtnl_message_read(m, &type, &data) == 0);
380 assert((r = sd_rtnl_message_unref(r)) == NULL);
382 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
383 assert((m = sd_rtnl_message_unref(m)) == NULL);
384 assert((r = sd_rtnl_message_unref(r)) == NULL);
386 test_link_get(rtnl, if_loopback);
388 assert(sd_rtnl_flush(rtnl) >= 0);
389 assert((m = sd_rtnl_message_unref(m)) == NULL);
390 assert((r = sd_rtnl_message_unref(r)) == NULL);
391 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);