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, &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, &req);
70 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
74 r = sd_rtnl_message_append(req, RTA_GATEWAY, &addr);
76 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
80 r = sd_rtnl_message_append(req, RTA_OIF, &index);
82 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
86 assert(sd_rtnl_message_read(req, &type, &data) > 0);
87 assert(type == RTA_GATEWAY);
88 assert(*(uint32_t *) data == addr);
90 assert(sd_rtnl_message_read(req, &type, &data) > 0);
91 assert(type == RTA_OIF);
92 assert(*(uint32_t *) data == index);
95 static void test_multiple(void) {
96 sd_rtnl *rtnl1, *rtnl2;
98 assert(sd_rtnl_open(0, &rtnl1) >= 0);
99 assert(sd_rtnl_open(0, &rtnl2) >= 0);
101 rtnl1 = sd_rtnl_unref(rtnl1);
102 rtnl2 = sd_rtnl_unref(rtnl2);
105 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
108 char *ifname = userdata;
113 log_info("got link info about %s", ifname);
116 while (sd_rtnl_message_read(m, &type, &data) > 0) {
119 // assert(*(unsigned int *) data == 65536);
122 // assert(streq((char *) data, "noqueue"));
125 assert(streq((char *) data, "lo"));
133 static void test_event_loop(int ifindex) {
134 _cleanup_event_unref_ sd_event *event = NULL;
135 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
136 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
139 ifname = strdup("lo2");
142 assert(sd_rtnl_open(0, &rtnl) >= 0);
143 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m) >= 0);
145 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
147 assert(sd_event_default(&event) >= 0);
149 assert(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
151 assert(sd_event_run(event, 0) >= 0);
153 assert(sd_rtnl_detach_event(rtnl) >= 0);
156 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
157 int *counter = userdata;
161 log_info("got reply, %d left in pipe", *counter);
163 return sd_rtnl_message_get_errno(m);
166 static void test_async(int ifindex) {
167 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
168 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
172 ifname = strdup("lo");
175 assert(sd_rtnl_open(0, &rtnl) >= 0);
177 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m) >= 0);
179 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
181 assert(sd_rtnl_wait(rtnl, 0) >= 0);
182 assert(sd_rtnl_process(rtnl, &r) >= 0);
185 static void test_pipe(int ifindex) {
186 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
187 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
190 assert(sd_rtnl_open(0, &rtnl) >= 0);
192 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m1) >= 0);
193 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m2) >= 0);
196 assert(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
199 assert(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
201 while (counter > 0) {
202 assert(sd_rtnl_wait(rtnl, 0) >= 0);
203 assert(sd_rtnl_process(rtnl, NULL) >= 0);
207 static void test_container(void) {
208 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
212 assert(sd_rtnl_message_link_new(RTM_NEWLINK, 0, &m) >= 0);
214 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
215 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -EINVAL);
216 assert(sd_rtnl_message_append(m, IFLA_INFO_KIND, "kind") >= 0);
217 assert(sd_rtnl_message_close_container(m) >= 0);
218 assert(sd_rtnl_message_close_container(m) == -EINVAL);
220 assert(sd_rtnl_message_read(m, &type, &data) == -EINVAL);
222 /* TODO: add support for entering containers
223 assert(sd_rtnl_message_read(m, &type, &data) > 0);
224 assert(type == IFLA_INFO_KIND);
225 assert(streq("kind", (char *) data));
227 assert(sd_rtnl_message_read(m, &type, &data) == 0);
231 static void test_match(void) {
232 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
234 assert(sd_rtnl_open(0, &rtnl) >= 0);
236 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
237 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
239 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
240 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
241 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
251 unsigned int mtu = 0;
252 unsigned int *mtu_reply;
262 assert(sd_rtnl_open(0, &rtnl) >= 0);
265 if_loopback = (int) if_nametoindex("lo");
266 assert(if_loopback > 0);
268 test_async(if_loopback);
270 test_pipe(if_loopback);
272 test_event_loop(if_loopback);
274 test_link_configure(rtnl, if_loopback);
276 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
279 assert(sd_rtnl_message_get_type(m, &type) >= 0);
280 assert(type == RTM_GETLINK);
282 assert(sd_rtnl_message_read(m, &type, &data) == 0);
284 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
285 assert(sd_rtnl_message_get_type(r, &type) >= 0);
286 assert(type == RTM_NEWLINK);
288 assert(sd_rtnl_message_read(m, &type, &data) == 0);
289 assert((r = sd_rtnl_message_unref(r)) == NULL);
291 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
292 assert((m = sd_rtnl_message_unref(m)) == NULL);
293 assert((r = sd_rtnl_message_unref(r)) == NULL);
295 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
298 assert(sd_rtnl_message_append(m, IFLA_MTU, &mtu) >= 0);
299 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
301 assert(type == IFLA_MTU);
302 assert(*mtu_reply == 0);
304 assert(sd_rtnl_message_read(m, &type, &data) == 0);
306 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
307 while (sd_rtnl_message_read(r, &type, &data) > 0) {
310 // assert(*(unsigned int *) data == 65536);
313 // assert(streq((char *) data, "noqueue"));
316 assert(streq((char *) data, "lo"));
321 assert(sd_rtnl_flush(rtnl) >= 0);
323 assert((m = sd_rtnl_message_unref(m)) == NULL);
324 assert((r = sd_rtnl_message_unref(r)) == NULL);
325 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);