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 <netinet/ether.h>
27 #include "socket-util.h"
28 #include "rtnl-util.h"
29 #include "event-util.h"
31 #include "rtnl-internal.h"
33 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
34 _cleanup_rtnl_message_unref_ sd_rtnl_message *message;
35 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
36 unsigned int mtu = 1450, mtu_out;
38 struct ether_addr mac_out;
40 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
41 assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
42 assert_se(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
43 assert_se(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
44 assert_se(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
46 assert_se(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
47 assert_se(sd_rtnl_message_rewind(message) >= 0);
49 assert_se(sd_rtnl_message_read_string(message, IFLA_IFNAME, &name_out) >= 0);
50 assert_se(streq(name, name_out));
52 assert_se(sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0);
53 assert_se(streq(mac, ether_ntoa(&mac_out)));
55 assert_se(sd_rtnl_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0);
56 assert_se(mtu == mtu_out);
59 static void test_link_get(sd_rtnl *rtnl, int ifindex) {
62 unsigned int mtu = 1500;
66 struct ether_addr eth_data;
68 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
72 assert_se(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
73 assert_se(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
74 assert_se(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
77 assert_se(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
78 assert_se(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0);
79 assert_se(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
80 assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
81 assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
83 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
85 assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
87 assert_se(sd_rtnl_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0);
88 assert_se(sd_rtnl_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0);
89 assert_se(sd_rtnl_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0);
91 assert_se(sd_rtnl_message_read_u32(r, IFLA_MTU, &u32_data) == 0);
92 assert_se(sd_rtnl_message_read_u32(r, IFLA_GROUP, &u32_data) == 0);
93 assert_se(sd_rtnl_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0);
94 assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0);
95 assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0);
97 assert_se(sd_rtnl_message_read_ether_addr(r, IFLA_ADDRESS, ð_data) == 0);
99 assert_se(sd_rtnl_flush(rtnl) >= 0);
100 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
101 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
105 static void test_address_get(sd_rtnl *rtnl, int ifindex) {
108 struct in_addr in_data;
109 struct ifa_cacheinfo cache;
112 assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
115 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
117 assert_se(sd_rtnl_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0);
118 assert_se(sd_rtnl_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0);
119 assert_se(sd_rtnl_message_read_string(r, IFA_LABEL, &label) == 0);
120 assert_se(sd_rtnl_message_read_cache_info(r, IFA_CACHEINFO, &cache) == 0);
122 assert_se(sd_rtnl_flush(rtnl) >= 0);
123 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
124 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
128 static void test_route(void) {
129 _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
130 struct in_addr addr, addr_data;
131 uint32_t index = 2, u32_data;
134 r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
136 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
140 addr.s_addr = htonl(INADDR_LOOPBACK);
142 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
144 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
148 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
150 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
154 assert_se(sd_rtnl_message_rewind(req) >= 0);
156 assert_se(sd_rtnl_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
157 assert_se(addr_data.s_addr == addr.s_addr);
159 assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
160 assert_se(u32_data == index);
162 assert_se((req = sd_rtnl_message_unref(req)) == NULL);
165 static void test_multiple(void) {
166 sd_rtnl *rtnl1, *rtnl2;
168 assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
169 assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
171 rtnl1 = sd_rtnl_unref(rtnl1);
172 rtnl2 = sd_rtnl_unref(rtnl2);
175 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
176 char *ifname = userdata, *data;
181 log_info("got link info about %s", ifname);
184 assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &data) >= 0);
185 assert_se(streq(data, "lo"));
190 static void test_event_loop(int ifindex) {
191 _cleanup_event_unref_ sd_event *event = NULL;
192 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
193 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
196 ifname = strdup("lo2");
199 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
200 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
202 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
204 assert_se(sd_event_default(&event) >= 0);
206 assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
208 assert_se(sd_event_run(event, 0) >= 0);
210 assert_se(sd_rtnl_detach_event(rtnl) >= 0);
212 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
215 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
216 int *counter = userdata;
221 r = sd_rtnl_message_get_errno(m);
223 log_info("%d left in pipe. got reply: %s", *counter, strerror(-r));
230 static void test_async(int ifindex) {
231 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
232 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
236 ifname = strdup("lo");
239 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
241 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
243 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
245 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
246 assert_se(sd_rtnl_process(rtnl, &r) >= 0);
248 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
251 static void test_pipe(int ifindex) {
252 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
253 _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
256 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
258 assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
259 assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
262 assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
265 assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
267 while (counter > 0) {
268 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
269 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
272 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
275 static void test_container(void) {
276 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
281 assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
283 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
284 assert_se(sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0);
285 assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
286 assert_se(sd_rtnl_message_close_container(m) >= 0);
287 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
288 assert_se(sd_rtnl_message_close_container(m) >= 0);
289 assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
291 assert_se(sd_rtnl_message_rewind(m) >= 0);
293 assert_se(sd_rtnl_message_enter_container(m, IFLA_LINKINFO) >= 0);
294 assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
295 assert_se(streq("vlan", string_data));
297 assert_se(sd_rtnl_message_enter_container(m, IFLA_INFO_DATA) >= 0);
298 assert_se(sd_rtnl_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0);
299 assert_se(sd_rtnl_message_exit_container(m) >= 0);
301 assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
302 assert_se(streq("vlan", string_data));
303 assert_se(sd_rtnl_message_exit_container(m) >= 0);
305 assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0);
307 assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
310 static void test_match(void) {
311 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
313 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
315 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
316 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
318 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
319 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
320 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
322 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
325 static void test_get_addresses(sd_rtnl *rtnl) {
326 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
329 assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0);
331 assert_se(sd_rtnl_call(rtnl, req, 0, &reply) >= 0);
333 for (m = reply; m; m = sd_rtnl_message_next(m)) {
335 unsigned char family, scope, flags;
338 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
339 assert_se(type == RTM_NEWADDR);
341 assert_se(sd_rtnl_message_addr_get_ifindex(m, &ifindex) >= 0);
342 assert_se(sd_rtnl_message_addr_get_family(m, &family) >= 0);
343 assert_se(sd_rtnl_message_addr_get_scope(m, &scope) >= 0);
344 assert_se(sd_rtnl_message_addr_get_flags(m, &flags) >= 0);
346 assert_se(ifindex > 0);
347 assert_se(family == AF_INET || family == AF_INET6);
349 log_info("got IPv%u address on ifindex %i", family == AF_INET ? 4: 6, ifindex);
369 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
372 if_loopback = (int) if_nametoindex("lo");
373 assert_se(if_loopback > 0);
375 test_async(if_loopback);
377 test_pipe(if_loopback);
379 test_event_loop(if_loopback);
381 test_link_configure(rtnl, if_loopback);
383 test_get_addresses(rtnl);
385 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
388 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
389 assert_se(type == RTM_GETLINK);
391 assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
393 assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
394 assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
395 assert_se(type == RTM_NEWLINK);
397 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
399 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
400 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
401 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
403 test_link_get(rtnl, if_loopback);
404 test_address_get(rtnl, if_loopback);
406 assert_se(sd_rtnl_flush(rtnl) >= 0);
407 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
408 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
409 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);