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(sd_rtnl_message_new_link(rtnl, RTM_GETLINK, ifindex, &message) >= 0);
41 assert(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
42 assert(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
43 assert(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
45 assert(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
47 assert(sd_rtnl_message_read(message, &type, &data) > 0);
48 assert(type == IFLA_IFNAME);
49 assert(streq(name, (char *) data));
51 assert(sd_rtnl_message_read(message, &type, &data) > 0);
52 assert(type == IFLA_ADDRESS);
53 assert(streq(mac, ether_ntoa(data)));
55 assert(sd_rtnl_message_read(message, &type, &data) > 0);
56 assert(type == IFLA_MTU);
57 assert(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;
69 assert(sd_rtnl_message_new_link(rtnl, RTM_GETLINK, ifindex, &m) >= 0);
73 assert(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
74 assert(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
75 assert(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
78 assert(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
79 assert(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0);
80 assert(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
81 assert(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
82 assert(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
84 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
87 assert(sd_rtnl_message_read(m, &type, &data) == 1);
88 assert(type == IFLA_CARRIER);
90 assert(sd_rtnl_message_read(m, &type, &data) == 1);
91 assert(type == IFLA_OPERSTATE);
93 assert(sd_rtnl_message_read(m, &type, &data) == 1);
94 assert(type == IFLA_LINKMODE);
97 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
98 assert(type == IFLA_MTU);
99 assert(*mtu_reply == mtu);
101 assert(sd_rtnl_message_read(m, &type, &data) == 1);
102 assert(type == IFLA_GROUP);
104 assert(sd_rtnl_message_read(m, &type, &data) == 1);
105 assert(type == IFLA_TXQLEN);
107 assert(sd_rtnl_message_read(m, &type, &data) == 1);
108 assert(type == IFLA_NUM_TX_QUEUES);
110 assert(sd_rtnl_message_read(m, &type, &data) == 1);
111 assert(type == IFLA_NUM_RX_QUEUES);
113 while (sd_rtnl_message_read(r, &type, &data) > 0) {
116 // assert(*(unsigned int *) data == 65536);
119 // assert(streq((char *) data, "noqueue"));
122 assert(streq((char *) data, "lo"));
127 assert(sd_rtnl_flush(rtnl) >= 0);
128 assert((m = sd_rtnl_message_unref(m)) == NULL);
132 static void test_route(void) {
133 _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
140 r = sd_rtnl_message_new_route(NULL, RTM_NEWROUTE, AF_INET, &req);
142 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
146 addr.s_addr = htonl(INADDR_LOOPBACK);
148 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
150 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
154 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
156 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
160 assert(rtnl_message_seal(NULL, req) >= 0);
162 assert(sd_rtnl_message_read(req, &type, &data) > 0);
163 assert(type == RTA_GATEWAY);
164 assert(((struct in_addr *)data)->s_addr == addr.s_addr);
166 assert(sd_rtnl_message_read(req, &type, &data) > 0);
167 assert(type == RTA_OIF);
168 assert(*(uint32_t *) data == index);
171 static void test_multiple(void) {
172 sd_rtnl *rtnl1, *rtnl2;
174 assert(sd_rtnl_open(0, &rtnl1) >= 0);
175 assert(sd_rtnl_open(0, &rtnl2) >= 0);
177 rtnl1 = sd_rtnl_unref(rtnl1);
178 rtnl2 = sd_rtnl_unref(rtnl2);
181 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
184 char *ifname = userdata;
189 log_info("got link info about %s", ifname);
192 while (sd_rtnl_message_read(m, &type, &data) > 0) {
195 // assert(*(unsigned int *) data == 65536);
198 // assert(streq((char *) data, "noqueue"));
201 assert(streq((char *) data, "lo"));
209 static void test_event_loop(int ifindex) {
210 _cleanup_event_unref_ sd_event *event = NULL;
211 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
212 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
215 ifname = strdup("lo2");
218 assert(sd_rtnl_open(0, &rtnl) >= 0);
219 assert(sd_rtnl_message_new_link(rtnl, RTM_GETLINK, ifindex, &m) >= 0);
221 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
223 assert(sd_event_default(&event) >= 0);
225 assert(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
227 assert(sd_event_run(event, 0) >= 0);
229 assert(sd_rtnl_detach_event(rtnl) >= 0);
232 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
233 int *counter = userdata;
237 log_info("got reply, %d left in pipe", *counter);
239 return sd_rtnl_message_get_errno(m);
242 static void test_async(int ifindex) {
243 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
244 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
248 ifname = strdup("lo");
251 assert(sd_rtnl_open(0, &rtnl) >= 0);
253 assert(sd_rtnl_message_new_link(rtnl, RTM_GETLINK, ifindex, &m) >= 0);
255 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
257 assert(sd_rtnl_wait(rtnl, 0) >= 0);
258 assert(sd_rtnl_process(rtnl, &r) >= 0);
261 static void test_pipe(int ifindex) {
262 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
263 _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
266 assert(sd_rtnl_open(0, &rtnl) >= 0);
268 assert(sd_rtnl_message_new_link(rtnl, RTM_GETLINK, ifindex, &m1) >= 0);
269 assert(sd_rtnl_message_new_link(rtnl, RTM_GETLINK, ifindex, &m2) >= 0);
272 assert(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
275 assert(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
277 while (counter > 0) {
278 assert(sd_rtnl_wait(rtnl, 0) >= 0);
279 assert(sd_rtnl_process(rtnl, NULL) >= 0);
283 static void test_container(void) {
284 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
288 assert(sd_rtnl_message_new_link(NULL, RTM_NEWLINK, 0, &m) >= 0);
290 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
291 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
292 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
293 assert(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
294 assert(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
295 assert(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
296 assert(sd_rtnl_message_close_container(m) >= 0);
297 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
298 assert(sd_rtnl_message_close_container(m) >= 0);
299 assert(sd_rtnl_message_close_container(m) == -EINVAL);
301 assert(rtnl_message_seal(NULL, m) >= 0);
303 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
304 assert(type == IFLA_LINKINFO);
305 assert(data == NULL);
306 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
307 assert(type == IFLA_INFO_KIND);
308 assert(streq("kind", (char *)data));
309 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
310 assert(type == IFLA_INFO_DATA);
311 assert(data == NULL);
312 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
313 assert(type == IFLA_VLAN_ID);
314 assert(*(uint16_t *)data == 100);
315 assert(sd_rtnl_message_read(m, &type, &data) == 0);
316 assert(sd_rtnl_message_exit_container(m) >= 0);
317 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
318 assert(type == IFLA_INFO_KIND);
319 assert(streq("kind", (char *)data));
320 assert(sd_rtnl_message_read(m, &type, &data) == 0);
321 assert(sd_rtnl_message_exit_container(m) >= 0);
322 assert(sd_rtnl_message_exit_container(m) == -EINVAL);
325 static void test_match(void) {
326 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
328 assert(sd_rtnl_open(0, &rtnl) >= 0);
330 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
331 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
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) == 1);
335 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
354 assert(sd_rtnl_open(0, &rtnl) >= 0);
357 if_loopback = (int) if_nametoindex("lo");
358 assert(if_loopback > 0);
360 test_async(if_loopback);
362 test_pipe(if_loopback);
364 test_event_loop(if_loopback);
366 test_link_configure(rtnl, if_loopback);
368 assert(sd_rtnl_message_new_link(rtnl, RTM_GETLINK, if_loopback, &m) >= 0);
371 assert(sd_rtnl_message_get_type(m, &type) >= 0);
372 assert(type == RTM_GETLINK);
374 assert(sd_rtnl_message_read(m, &type, &data) == -EPERM);
376 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
377 assert(sd_rtnl_message_get_type(r, &type) >= 0);
378 assert(type == RTM_NEWLINK);
380 assert(sd_rtnl_message_read(m, &type, &data) == 0);
381 assert((r = sd_rtnl_message_unref(r)) == NULL);
383 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
384 assert((m = sd_rtnl_message_unref(m)) == NULL);
385 assert((r = sd_rtnl_message_unref(r)) == NULL);
387 test_link_get(rtnl, if_loopback);
389 assert(sd_rtnl_flush(rtnl) >= 0);
390 assert((m = sd_rtnl_message_unref(m)) == NULL);
391 assert((r = sd_rtnl_message_unref(r)) == NULL);
392 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);