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_read(m, &type, &data) == 0);
245 assert(sd_rtnl_message_exit_container(m) >= 0);
246 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
247 assert(type == IFLA_INFO_KIND);
248 assert(streq("kind", (char *)data));
249 assert(sd_rtnl_message_read(m, &type, &data) == 0);
250 assert(sd_rtnl_message_exit_container(m) >= 0);
251 assert(sd_rtnl_message_exit_container(m) == -EINVAL);
254 static void test_match(void) {
255 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
257 assert(sd_rtnl_open(0, &rtnl) >= 0);
259 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
260 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
262 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
263 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
264 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
274 unsigned int mtu = 0;
275 unsigned int *mtu_reply;
285 assert(sd_rtnl_open(0, &rtnl) >= 0);
288 if_loopback = (int) if_nametoindex("lo");
289 assert(if_loopback > 0);
291 test_async(if_loopback);
293 test_pipe(if_loopback);
295 test_event_loop(if_loopback);
297 test_link_configure(rtnl, if_loopback);
299 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
302 assert(sd_rtnl_message_get_type(m, &type) >= 0);
303 assert(type == RTM_GETLINK);
305 assert(sd_rtnl_message_read(m, &type, &data) == -EPERM);
307 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
308 assert(sd_rtnl_message_get_type(r, &type) >= 0);
309 assert(type == RTM_NEWLINK);
311 assert(sd_rtnl_message_read(m, &type, &data) == 0);
312 assert((r = sd_rtnl_message_unref(r)) == NULL);
314 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
315 assert((m = sd_rtnl_message_unref(m)) == NULL);
316 assert((r = sd_rtnl_message_unref(r)) == NULL);
318 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
321 assert(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
322 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == -EPERM);
323 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
324 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
326 assert(type == IFLA_MTU);
327 assert(*mtu_reply == 0);
329 assert(sd_rtnl_message_read(m, &type, &data) == 0);
331 while (sd_rtnl_message_read(r, &type, &data) > 0) {
334 // assert(*(unsigned int *) data == 65536);
337 // assert(streq((char *) data, "noqueue"));
340 assert(streq((char *) data, "lo"));
345 assert(sd_rtnl_flush(rtnl) >= 0);
347 assert((m = sd_rtnl_message_unref(m)) == NULL);
348 assert((r = sd_rtnl_message_unref(r)) == NULL);
349 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);