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 <linux/rtnetlink.h>
23 #include <netinet/ether.h>
28 #include "socket-util.h"
29 #include "rtnl-util.h"
30 #include "event-util.h"
32 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
33 _cleanup_sd_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_link_new(RTM_GETLINK, ifindex, 0, 0, &message) >= 0);
41 assert(sd_rtnl_message_append(message, IFLA_IFNAME, name) >= 0);
42 assert(sd_rtnl_message_append(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
43 assert(sd_rtnl_message_append(message, IFLA_MTU, &mtu) >= 0);
45 assert(sd_rtnl_message_read(message, &type, &data) >= 0);
46 assert(type == IFLA_IFNAME);
47 assert(streq(name, (char *) data));
49 assert(sd_rtnl_message_read(message, &type, &data) >= 0);
50 assert(type == IFLA_ADDRESS);
51 assert(streq(mac, ether_ntoa(data)));
53 assert(sd_rtnl_message_read(message, &type, &data) >= 0);
54 assert(type == IFLA_MTU);
55 assert(mtu == *(unsigned int *) data);
57 assert(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
60 static void test_route(void) {
61 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req;
62 uint32_t addr = htonl(INADDR_LOOPBACK);
68 r = sd_rtnl_message_route_new(RTM_NEWROUTE, AF_INET, 0, 0, 0,
69 RT_TABLE_MAIN, RT_SCOPE_UNIVERSE, RTPROT_BOOT,
70 RTN_UNICAST, 0, &req);
72 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
76 r = sd_rtnl_message_append(req, RTA_GATEWAY, &addr);
78 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
82 r = sd_rtnl_message_append(req, RTA_OIF, &index);
84 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
88 assert(sd_rtnl_message_read(req, &type, &data) > 0);
89 assert(type == RTA_GATEWAY);
90 assert(*(uint32_t *) data == addr);
92 assert(sd_rtnl_message_read(req, &type, &data) > 0);
93 assert(type == RTA_OIF);
94 assert(*(uint32_t *) data == index);
97 static void test_multiple(void) {
98 sd_rtnl *rtnl1, *rtnl2;
100 assert(sd_rtnl_open(0, &rtnl1) >= 0);
101 assert(sd_rtnl_open(0, &rtnl2) >= 0);
103 rtnl1 = sd_rtnl_unref(rtnl1);
104 rtnl2 = sd_rtnl_unref(rtnl2);
107 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
110 char *ifname = userdata;
115 log_info("got link info about %s", ifname);
118 while (sd_rtnl_message_read(m, &type, &data) > 0) {
121 // assert(*(unsigned int *) data == 65536);
124 // assert(streq((char *) data, "noqueue"));
127 assert(streq((char *) data, "lo"));
135 static void test_event_loop(int ifindex) {
136 _cleanup_event_unref_ sd_event *event = NULL;
137 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
138 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
141 ifname = strdup("lo2");
144 assert(sd_rtnl_open(0, &rtnl) >= 0);
145 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &m) >= 0);
147 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
149 assert(sd_event_default(&event) >= 0);
151 assert(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
153 assert(sd_event_run(event, 0) >= 0);
155 assert(sd_rtnl_detach_event(rtnl) >= 0);
158 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
159 int *counter = userdata;
163 log_info("got reply, %d left in pipe", *counter);
165 return sd_rtnl_message_get_errno(m);
168 static void test_async(int ifindex) {
169 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
170 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
174 ifname = strdup("lo");
177 assert(sd_rtnl_open(0, &rtnl) >= 0);
179 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &m) >= 0);
181 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
183 assert(sd_rtnl_wait(rtnl, 0) >= 0);
184 assert(sd_rtnl_process(rtnl, &r) >= 0);
187 static void test_pipe(int ifindex) {
188 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
189 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
192 assert(sd_rtnl_open(0, &rtnl) >= 0);
194 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &m1) >= 0);
195 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &m2) >= 0);
198 assert(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
201 assert(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
203 while (counter > 0) {
204 assert(sd_rtnl_wait(rtnl, 0) >= 0);
205 assert(sd_rtnl_process(rtnl, NULL) >= 0);
209 static void test_container(void) {
210 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
214 assert(sd_rtnl_message_link_new(RTM_NEWLINK, 0, 0, 0, &m) >= 0);
216 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
217 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -EINVAL);
218 assert(sd_rtnl_message_append(m, IFLA_INFO_KIND, "kind") >= 0);
219 assert(sd_rtnl_message_close_container(m) >= 0);
220 assert(sd_rtnl_message_close_container(m) == -EINVAL);
222 assert(sd_rtnl_message_read(m, &type, &data) == -EINVAL);
224 /* TODO: add support for entering containers
225 assert(sd_rtnl_message_read(m, &type, &data) > 0);
226 assert(type == IFLA_INFO_KIND);
227 assert(streq("kind", (char *) data));
229 assert(sd_rtnl_message_read(m, &type, &data) == 0);
233 static void test_match(void) {
234 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
236 assert(sd_rtnl_open(0, &rtnl) >= 0);
238 assert(sd_rtnl_add_match(rtnl, 0, &link_handler, NULL) == -EINVAL);
240 assert(sd_rtnl_add_match(rtnl, RTMGRP_LINK, &link_handler, NULL) >= 0);
241 assert(sd_rtnl_add_match(rtnl, RTMGRP_LINK, &link_handler, NULL) >= 0);
243 assert(sd_rtnl_remove_match(rtnl, RTMGRP_LINK, &link_handler, NULL) == 1);
244 assert(sd_rtnl_remove_match(rtnl, RTMGRP_LINK, &link_handler, NULL) == 1);
245 assert(sd_rtnl_remove_match(rtnl, RTMGRP_LINK, &link_handler, NULL) == 0);
255 unsigned int mtu = 0;
256 unsigned int *mtu_reply;
266 assert(sd_rtnl_open(0, &rtnl) >= 0);
269 if_loopback = (int) if_nametoindex("lo");
270 assert(if_loopback > 0);
272 test_async(if_loopback);
274 test_pipe(if_loopback);
276 test_event_loop(if_loopback);
278 test_link_configure(rtnl, if_loopback);
280 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m) >= 0);
283 assert(sd_rtnl_message_get_type(m, &type) >= 0);
284 assert(type == RTM_GETLINK);
286 assert(sd_rtnl_message_read(m, &type, &data) == 0);
288 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
289 assert(sd_rtnl_message_get_type(r, &type) >= 0);
290 assert(type == RTM_NEWLINK);
292 assert(sd_rtnl_message_read(m, &type, &data) == 0);
293 assert((r = sd_rtnl_message_unref(r)) == NULL);
295 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
296 assert((m = sd_rtnl_message_unref(m)) == NULL);
297 assert((r = sd_rtnl_message_unref(r)) == NULL);
299 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m) >= 0);
302 assert(sd_rtnl_message_append(m, IFLA_MTU, &mtu) >= 0);
303 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
305 assert(type == IFLA_MTU);
306 assert(*mtu_reply == 0);
308 assert(sd_rtnl_message_read(m, &type, &data) == 0);
310 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
311 while (sd_rtnl_message_read(r, &type, &data) > 0) {
314 // assert(*(unsigned int *) data == 65536);
317 // assert(streq((char *) data, "noqueue"));
320 assert(streq((char *) data, "lo"));
325 assert(sd_rtnl_flush(rtnl) >= 0);
327 assert((m = sd_rtnl_message_unref(m)) == NULL);
328 assert((r = sd_rtnl_message_unref(r)) == NULL);
329 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);