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>
28 #include "socket-util.h"
29 #include "rtnl-util.h"
30 #include "event-util.h"
32 #include "rtnl-internal.h"
34 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
35 _cleanup_rtnl_message_unref_ sd_rtnl_message *message;
36 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
37 unsigned int mtu = 1450, mtu_out;
39 struct ether_addr mac_out;
41 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
42 assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
43 assert_se(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
44 assert_se(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
45 assert_se(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
47 assert_se(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
48 assert_se(sd_rtnl_message_rewind(message) >= 0);
50 assert_se(sd_rtnl_message_read_string(message, IFLA_IFNAME, &name_out) >= 0);
51 assert_se(streq(name, name_out));
53 assert_se(sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0);
54 assert_se(streq(mac, ether_ntoa(&mac_out)));
56 assert_se(sd_rtnl_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0);
57 assert_se(mtu == mtu_out);
60 static void test_link_get(sd_rtnl *rtnl, int ifindex) {
63 unsigned int mtu = 1500;
67 struct ether_addr eth_data;
69 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
73 assert_se(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
74 assert_se(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
75 assert_se(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
78 assert_se(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
79 assert_se(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0);
80 assert_se(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
81 assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
82 assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
84 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
86 assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
88 assert_se(sd_rtnl_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0);
89 assert_se(sd_rtnl_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0);
90 assert_se(sd_rtnl_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0);
92 assert_se(sd_rtnl_message_read_u32(r, IFLA_MTU, &u32_data) == 0);
93 assert_se(sd_rtnl_message_read_u32(r, IFLA_GROUP, &u32_data) == 0);
94 assert_se(sd_rtnl_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0);
95 assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0);
96 assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0);
98 assert_se(sd_rtnl_message_read_ether_addr(r, IFLA_ADDRESS, ð_data) == 0);
100 assert_se(sd_rtnl_flush(rtnl) >= 0);
101 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
102 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
106 static void test_address_get(sd_rtnl *rtnl, int ifindex) {
109 struct in_addr in_data;
110 struct ifa_cacheinfo cache;
113 assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
116 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
118 assert_se(sd_rtnl_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0);
119 assert_se(sd_rtnl_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0);
120 assert_se(sd_rtnl_message_read_string(r, IFA_LABEL, &label) == 0);
121 assert_se(sd_rtnl_message_read_cache_info(r, IFA_CACHEINFO, &cache) == 0);
123 assert_se(sd_rtnl_flush(rtnl) >= 0);
124 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
125 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
129 static void test_route(void) {
130 _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
131 struct in_addr addr, addr_data;
132 uint32_t index = 2, u32_data;
135 r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC);
137 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
141 addr.s_addr = htonl(INADDR_LOOPBACK);
143 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
145 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
149 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
151 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
155 assert_se(sd_rtnl_message_rewind(req) >= 0);
157 assert_se(sd_rtnl_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
158 assert_se(addr_data.s_addr == addr.s_addr);
160 assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
161 assert_se(u32_data == index);
163 assert_se((req = sd_rtnl_message_unref(req)) == NULL);
166 static void test_multiple(void) {
167 sd_rtnl *rtnl1, *rtnl2;
169 assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
170 assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
172 rtnl1 = sd_rtnl_unref(rtnl1);
173 rtnl2 = sd_rtnl_unref(rtnl2);
176 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
177 char *ifname = userdata;
183 log_info("got link info about %s", ifname);
186 assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &data) >= 0);
187 assert_se(streq(data, "lo"));
192 static void test_event_loop(int ifindex) {
193 _cleanup_event_unref_ sd_event *event = NULL;
194 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
195 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
198 ifname = strdup("lo2");
201 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
202 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
204 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
206 assert_se(sd_event_default(&event) >= 0);
208 assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
210 assert_se(sd_event_run(event, 0) >= 0);
212 assert_se(sd_rtnl_detach_event(rtnl) >= 0);
214 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
217 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
218 int *counter = userdata;
223 r = sd_rtnl_message_get_errno(m);
225 log_info("%d left in pipe. got reply: %s", *counter, strerror(-r));
232 static void test_async(int ifindex) {
233 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
234 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
238 ifname = strdup("lo");
241 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
243 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
245 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
247 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
248 assert_se(sd_rtnl_process(rtnl, &r) >= 0);
250 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
253 static void test_pipe(int ifindex) {
254 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
255 _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
258 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
260 assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
261 assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
264 assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
267 assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
269 while (counter > 0) {
270 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
271 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
274 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
277 static void test_container(void) {
278 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
281 const char *string_data;
283 assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
285 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
286 assert_se(sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0);
287 assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
288 assert_se(sd_rtnl_message_close_container(m) >= 0);
289 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
290 assert_se(sd_rtnl_message_close_container(m) >= 0);
291 assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
293 assert_se(sd_rtnl_message_rewind(m) >= 0);
295 assert_se(sd_rtnl_message_enter_container(m, IFLA_LINKINFO) >= 0);
296 assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
297 assert_se(streq("vlan", string_data));
299 assert_se(sd_rtnl_message_enter_container(m, IFLA_INFO_DATA) >= 0);
300 assert_se(sd_rtnl_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0);
301 assert_se(sd_rtnl_message_exit_container(m) >= 0);
303 assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
304 assert_se(streq("vlan", string_data));
305 assert_se(sd_rtnl_message_exit_container(m) >= 0);
307 assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0);
309 assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
312 static void test_match(void) {
313 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
315 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
317 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
318 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
320 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
321 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
322 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
324 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
327 static void test_get_addresses(sd_rtnl *rtnl) {
328 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
331 assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0);
333 assert_se(sd_rtnl_call(rtnl, req, 0, &reply) >= 0);
335 for (m = reply; m; m = sd_rtnl_message_next(m)) {
337 unsigned char scope, flags;
340 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
341 assert_se(type == RTM_NEWADDR);
343 assert_se(sd_rtnl_message_addr_get_ifindex(m, &ifindex) >= 0);
344 assert_se(sd_rtnl_message_addr_get_family(m, &family) >= 0);
345 assert_se(sd_rtnl_message_addr_get_scope(m, &scope) >= 0);
346 assert_se(sd_rtnl_message_addr_get_flags(m, &flags) >= 0);
348 assert_se(ifindex > 0);
349 assert_se(family == AF_INET || family == AF_INET6);
351 log_info("got IPv%u address on ifindex %i", family == AF_INET ? 4: 6, ifindex);
359 const char *string_data;
371 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
374 if_loopback = (int) if_nametoindex("lo");
375 assert_se(if_loopback > 0);
377 test_async(if_loopback);
379 test_pipe(if_loopback);
381 test_event_loop(if_loopback);
383 test_link_configure(rtnl, if_loopback);
385 test_get_addresses(rtnl);
387 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
390 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
391 assert_se(type == RTM_GETLINK);
393 assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
395 assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
396 assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
397 assert_se(type == RTM_NEWLINK);
399 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
401 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
402 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
403 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
405 test_link_get(rtnl, if_loopback);
406 test_address_get(rtnl, if_loopback);
408 assert_se(sd_rtnl_flush(rtnl) >= 0);
409 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
410 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
411 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);