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;
111 assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
114 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
116 assert_se(sd_rtnl_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0);
117 assert_se(sd_rtnl_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0);
118 assert_se(sd_rtnl_message_read_string(r, IFA_LABEL, &label) == 0);
120 assert_se(sd_rtnl_flush(rtnl) >= 0);
121 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
122 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
126 static void test_route(void) {
127 _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
129 struct in_addr addr, addr_data;
130 uint32_t index = 2, u32_data;
133 r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
135 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
139 addr.s_addr = htonl(INADDR_LOOPBACK);
141 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
143 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
147 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
149 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
153 assert_se(sd_rtnl_message_rewind(req) >= 0);
155 assert_se(sd_rtnl_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
156 assert_se(addr_data.s_addr == addr.s_addr);
158 assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
159 assert_se(u32_data == index);
161 rtm = NLMSG_DATA(req->hdr);
162 r = rtnl_message_parse(req,
167 RTM_PAYLOAD(req->hdr));
169 assert_se(sd_rtnl_message_read_u32(req, RTA_GATEWAY, &u32_data) == 0);
170 assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) == 0);
172 assert_se((req = sd_rtnl_message_unref(req)) == NULL);
175 static void test_multiple(void) {
176 sd_rtnl *rtnl1, *rtnl2;
178 assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
179 assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
181 rtnl1 = sd_rtnl_unref(rtnl1);
182 rtnl2 = sd_rtnl_unref(rtnl2);
185 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
186 char *ifname = userdata, *data;
191 log_info("got link info about %s", ifname);
194 assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &data) >= 0);
195 assert_se(streq(data, "lo"));
200 static void test_event_loop(int ifindex) {
201 _cleanup_event_unref_ sd_event *event = NULL;
202 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
203 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
206 ifname = strdup("lo2");
209 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
210 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
212 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
214 assert_se(sd_event_default(&event) >= 0);
216 assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
218 assert_se(sd_event_run(event, 0) >= 0);
220 assert_se(sd_rtnl_detach_event(rtnl) >= 0);
222 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
225 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
226 int *counter = userdata;
231 r = sd_rtnl_message_get_errno(m);
233 log_info("%d left in pipe. got reply: %s", *counter, strerror(-r));
240 static void test_async(int ifindex) {
241 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
242 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
246 ifname = strdup("lo");
249 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
251 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
253 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
255 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
256 assert_se(sd_rtnl_process(rtnl, &r) >= 0);
258 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
261 static void test_pipe(int ifindex) {
262 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
263 _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
266 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
268 assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
269 assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
272 assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
275 assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
277 while (counter > 0) {
278 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
279 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
282 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
285 static void test_container(void) {
286 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
287 struct ifinfomsg *ifi;
293 assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
295 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
296 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
297 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
298 assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
299 assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
300 assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
301 assert_se(sd_rtnl_message_close_container(m) >= 0);
302 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
303 assert_se(sd_rtnl_message_close_container(m) >= 0);
304 assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
306 assert_se(sd_rtnl_message_rewind(m) >= 0);
308 assert_se(sd_rtnl_message_enter_container(m, IFLA_LINKINFO) >= 0);
309 assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
310 assert_se(streq("vlan", string_data));
312 assert_se(sd_rtnl_message_enter_container(m, IFLA_INFO_DATA) >= 0);
313 assert_se(sd_rtnl_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0);
314 assert_se(sd_rtnl_message_exit_container(m) >= 0);
316 assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
317 assert_se(streq("vlan", string_data));
318 assert_se(sd_rtnl_message_exit_container(m) >= 0);
320 ifi = NLMSG_DATA(m->hdr);
321 r = rtnl_message_parse(m,
326 IFLA_PAYLOAD(m->hdr));
330 assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) == 0);
332 assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
335 static void test_match(void) {
336 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
338 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
340 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
341 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
343 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
344 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
345 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
347 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
366 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
369 if_loopback = (int) if_nametoindex("lo");
370 assert_se(if_loopback > 0);
372 test_async(if_loopback);
374 test_pipe(if_loopback);
376 test_event_loop(if_loopback);
378 test_link_configure(rtnl, if_loopback);
380 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
383 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
384 assert_se(type == RTM_GETLINK);
386 assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
388 assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
389 assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
390 assert_se(type == RTM_NEWLINK);
392 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
394 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
395 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
396 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
398 test_link_get(rtnl, if_loopback);
399 test_address_get(rtnl, if_loopback);
401 assert_se(sd_rtnl_flush(rtnl) >= 0);
402 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
403 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
404 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);