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_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_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;
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 addr.s_addr = htonl(INADDR_LOOPBACK);
76 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
78 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
82 r = sd_rtnl_message_append_u32(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(((struct in_addr *)data)->s_addr == addr.s_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, &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, &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, &m1) >= 0);
195 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &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, &m) >= 0);
216 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
217 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
218 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
219 assert(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
220 assert(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
221 assert(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
222 assert(sd_rtnl_message_close_container(m) >= 0);
223 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
224 assert(sd_rtnl_message_close_container(m) >= 0);
225 assert(sd_rtnl_message_close_container(m) == -EINVAL);
227 assert(sd_rtnl_message_read(m, &type, &data) == -EINVAL);
229 /* TODO: add support for entering containers
230 assert(sd_rtnl_message_read(m, &type, &data) > 0);
231 assert(type == IFLA_INFO_KIND);
232 assert(streq("kind", (char *) data));
234 assert(sd_rtnl_message_read(m, &type, &data) == 0);
238 static void test_match(void) {
239 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
241 assert(sd_rtnl_open(0, &rtnl) >= 0);
243 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
244 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
246 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
247 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
248 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
258 unsigned int mtu = 0;
259 unsigned int *mtu_reply;
269 assert(sd_rtnl_open(0, &rtnl) >= 0);
272 if_loopback = (int) if_nametoindex("lo");
273 assert(if_loopback > 0);
275 test_async(if_loopback);
277 test_pipe(if_loopback);
279 test_event_loop(if_loopback);
281 test_link_configure(rtnl, if_loopback);
283 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
286 assert(sd_rtnl_message_get_type(m, &type) >= 0);
287 assert(type == RTM_GETLINK);
289 assert(sd_rtnl_message_read(m, &type, &data) == 0);
291 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
292 assert(sd_rtnl_message_get_type(r, &type) >= 0);
293 assert(type == RTM_NEWLINK);
295 assert(sd_rtnl_message_read(m, &type, &data) == 0);
296 assert((r = sd_rtnl_message_unref(r)) == NULL);
298 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
299 assert((m = sd_rtnl_message_unref(m)) == NULL);
300 assert((r = sd_rtnl_message_unref(r)) == NULL);
302 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
305 assert(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
306 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
308 assert(type == IFLA_MTU);
309 assert(*mtu_reply == 0);
311 assert(sd_rtnl_message_read(m, &type, &data) == 0);
313 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
314 while (sd_rtnl_message_read(r, &type, &data) > 0) {
317 // assert(*(unsigned int *) data == 65536);
320 // assert(streq((char *) data, "noqueue"));
323 assert(streq((char *) data, "lo"));
328 assert(sd_rtnl_flush(rtnl) >= 0);
330 assert((m = sd_rtnl_message_unref(m)) == NULL);
331 assert((r = sd_rtnl_message_unref(r)) == NULL);
332 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);