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 "rtnl-internal.h"
31 #include "event-util.h"
33 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
34 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *message;
36 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
37 unsigned int mtu = 1450;
40 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
41 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &message) >= 0);
42 assert(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
43 assert(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
44 assert(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
46 assert(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
48 assert(sd_rtnl_message_read(message, &type, &data) > 0);
49 assert(type == IFLA_IFNAME);
50 assert(streq(name, (char *) data));
52 assert(sd_rtnl_message_read(message, &type, &data) > 0);
53 assert(type == IFLA_ADDRESS);
54 assert(streq(mac, ether_ntoa(data)));
56 assert(sd_rtnl_message_read(message, &type, &data) > 0);
57 assert(type == IFLA_MTU);
58 assert(mtu == *(unsigned int *) data);
61 static void test_route(void) {
62 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req;
69 r = sd_rtnl_message_route_new(RTM_NEWROUTE, AF_INET, &req);
71 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
75 addr.s_addr = htonl(INADDR_LOOPBACK);
77 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
79 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
83 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
85 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
89 assert(message_seal(NULL, req) >= 0);
91 assert(sd_rtnl_message_read(req, &type, &data) > 0);
92 assert(type == RTA_GATEWAY);
93 assert(((struct in_addr *)data)->s_addr == addr.s_addr);
95 assert(sd_rtnl_message_read(req, &type, &data) > 0);
96 assert(type == RTA_OIF);
97 assert(*(uint32_t *) data == index);
100 static void test_multiple(void) {
101 sd_rtnl *rtnl1, *rtnl2;
103 assert(sd_rtnl_open(0, &rtnl1) >= 0);
104 assert(sd_rtnl_open(0, &rtnl2) >= 0);
106 rtnl1 = sd_rtnl_unref(rtnl1);
107 rtnl2 = sd_rtnl_unref(rtnl2);
110 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
113 char *ifname = userdata;
118 log_info("got link info about %s", ifname);
121 while (sd_rtnl_message_read(m, &type, &data) > 0) {
124 // assert(*(unsigned int *) data == 65536);
127 // assert(streq((char *) data, "noqueue"));
130 assert(streq((char *) data, "lo"));
138 static void test_event_loop(int ifindex) {
139 _cleanup_event_unref_ sd_event *event = NULL;
140 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
141 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
144 ifname = strdup("lo2");
147 assert(sd_rtnl_open(0, &rtnl) >= 0);
148 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m) >= 0);
150 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
152 assert(sd_event_default(&event) >= 0);
154 assert(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
156 assert(sd_event_run(event, 0) >= 0);
158 assert(sd_rtnl_detach_event(rtnl) >= 0);
161 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
162 int *counter = userdata;
166 log_info("got reply, %d left in pipe", *counter);
168 return sd_rtnl_message_get_errno(m);
171 static void test_async(int ifindex) {
172 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
173 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
177 ifname = strdup("lo");
180 assert(sd_rtnl_open(0, &rtnl) >= 0);
182 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m) >= 0);
184 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
186 assert(sd_rtnl_wait(rtnl, 0) >= 0);
187 assert(sd_rtnl_process(rtnl, &r) >= 0);
190 static void test_pipe(int ifindex) {
191 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
192 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
195 assert(sd_rtnl_open(0, &rtnl) >= 0);
197 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m1) >= 0);
198 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m2) >= 0);
201 assert(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
204 assert(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
206 while (counter > 0) {
207 assert(sd_rtnl_wait(rtnl, 0) >= 0);
208 assert(sd_rtnl_process(rtnl, NULL) >= 0);
212 static void test_container(void) {
213 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
217 assert(sd_rtnl_message_link_new(RTM_NEWLINK, 0, &m) >= 0);
219 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
220 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
221 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
222 assert(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
223 assert(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
224 assert(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
225 assert(sd_rtnl_message_close_container(m) >= 0);
226 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
227 assert(sd_rtnl_message_close_container(m) >= 0);
228 assert(sd_rtnl_message_close_container(m) == -EINVAL);
230 assert(message_seal(NULL, m) >= 0);
232 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
233 assert(type == IFLA_LINKINFO);
234 assert(data == NULL);
235 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
236 assert(type == IFLA_INFO_KIND);
237 assert(streq("kind", (char *)data));
238 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
239 assert(type == IFLA_INFO_DATA);
240 assert(data == NULL);
241 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
242 assert(type == IFLA_VLAN_ID);
243 assert(*(uint16_t *)data == 100);
244 assert(sd_rtnl_message_exit_container(m) >= 0);
245 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
246 assert(type == IFLA_INFO_KIND);
247 assert(streq("kind", (char *)data));
248 assert(sd_rtnl_message_exit_container(m) >= 0);
249 assert(sd_rtnl_message_exit_container(m) == -EINVAL);
252 static void test_match(void) {
253 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
255 assert(sd_rtnl_open(0, &rtnl) >= 0);
257 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
258 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
260 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
261 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
262 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
272 unsigned int mtu = 0;
273 unsigned int *mtu_reply;
283 assert(sd_rtnl_open(0, &rtnl) >= 0);
286 if_loopback = (int) if_nametoindex("lo");
287 assert(if_loopback > 0);
289 test_async(if_loopback);
291 test_pipe(if_loopback);
293 test_event_loop(if_loopback);
295 test_link_configure(rtnl, if_loopback);
297 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
300 assert(sd_rtnl_message_get_type(m, &type) >= 0);
301 assert(type == RTM_GETLINK);
303 assert(sd_rtnl_message_read(m, &type, &data) == -EPERM);
305 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
306 assert(sd_rtnl_message_get_type(r, &type) >= 0);
307 assert(type == RTM_NEWLINK);
309 assert(sd_rtnl_message_read(m, &type, &data) == 0);
310 assert((r = sd_rtnl_message_unref(r)) == NULL);
312 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
313 assert((m = sd_rtnl_message_unref(m)) == NULL);
314 assert((r = sd_rtnl_message_unref(r)) == NULL);
316 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
319 assert(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
320 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == -EPERM);
321 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
322 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
324 assert(type == IFLA_MTU);
325 assert(*mtu_reply == 0);
327 assert(sd_rtnl_message_read(m, &type, &data) == 0);
329 while (sd_rtnl_message_read(r, &type, &data) > 0) {
332 // assert(*(unsigned int *) data == 65536);
335 // assert(streq((char *) data, "noqueue"));
338 assert(streq((char *) data, "lo"));
343 assert(sd_rtnl_flush(rtnl) >= 0);
345 assert((m = sd_rtnl_message_unref(m)) == NULL);
346 assert((r = sd_rtnl_message_unref(r)) == NULL);
347 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);