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 "event-util.h"
32 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
33 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *message;
35 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
36 unsigned int mtu = 1450;
39 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
40 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &message) >= 0);
41 assert(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
42 assert(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
43 assert(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
45 assert(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
47 assert(sd_rtnl_message_read(message, &type, &data) > 0);
48 assert(type == IFLA_IFNAME);
49 assert(streq(name, (char *) data));
51 assert(sd_rtnl_message_read(message, &type, &data) > 0);
52 assert(type == IFLA_ADDRESS);
53 assert(streq(mac, ether_ntoa(data)));
55 assert(sd_rtnl_message_read(message, &type, &data) > 0);
56 assert(type == IFLA_MTU);
57 assert(mtu == *(unsigned int *) data);
60 static void test_route(void) {
61 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req;
68 r = sd_rtnl_message_route_new(RTM_NEWROUTE, AF_INET, &req);
70 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
74 addr.s_addr = htonl(INADDR_LOOPBACK);
76 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
78 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
82 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
84 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
88 assert(rtnl_message_seal(NULL, req) >= 0);
90 assert(sd_rtnl_message_read(req, &type, &data) > 0);
91 assert(type == RTA_GATEWAY);
92 assert(((struct in_addr *)data)->s_addr == addr.s_addr);
94 assert(sd_rtnl_message_read(req, &type, &data) > 0);
95 assert(type == RTA_OIF);
96 assert(*(uint32_t *) data == index);
99 static void test_multiple(void) {
100 sd_rtnl *rtnl1, *rtnl2;
102 assert(sd_rtnl_open(0, &rtnl1) >= 0);
103 assert(sd_rtnl_open(0, &rtnl2) >= 0);
105 rtnl1 = sd_rtnl_unref(rtnl1);
106 rtnl2 = sd_rtnl_unref(rtnl2);
109 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
112 char *ifname = userdata;
117 log_info("got link info about %s", ifname);
120 while (sd_rtnl_message_read(m, &type, &data) > 0) {
123 // assert(*(unsigned int *) data == 65536);
126 // assert(streq((char *) data, "noqueue"));
129 assert(streq((char *) data, "lo"));
137 static void test_event_loop(int ifindex) {
138 _cleanup_event_unref_ sd_event *event = NULL;
139 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
140 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
143 ifname = strdup("lo2");
146 assert(sd_rtnl_open(0, &rtnl) >= 0);
147 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m) >= 0);
149 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
151 assert(sd_event_default(&event) >= 0);
153 assert(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
155 assert(sd_event_run(event, 0) >= 0);
157 assert(sd_rtnl_detach_event(rtnl) >= 0);
160 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
161 int *counter = userdata;
165 log_info("got reply, %d left in pipe", *counter);
167 return sd_rtnl_message_get_errno(m);
170 static void test_async(int ifindex) {
171 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
172 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
176 ifname = strdup("lo");
179 assert(sd_rtnl_open(0, &rtnl) >= 0);
181 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m) >= 0);
183 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
185 assert(sd_rtnl_wait(rtnl, 0) >= 0);
186 assert(sd_rtnl_process(rtnl, &r) >= 0);
189 static void test_pipe(int ifindex) {
190 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
191 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
194 assert(sd_rtnl_open(0, &rtnl) >= 0);
196 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m1) >= 0);
197 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m2) >= 0);
200 assert(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
203 assert(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
205 while (counter > 0) {
206 assert(sd_rtnl_wait(rtnl, 0) >= 0);
207 assert(sd_rtnl_process(rtnl, NULL) >= 0);
211 static void test_container(void) {
212 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
216 assert(sd_rtnl_message_link_new(RTM_NEWLINK, 0, &m) >= 0);
218 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
219 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
220 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
221 assert(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
222 assert(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
223 assert(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
224 assert(sd_rtnl_message_close_container(m) >= 0);
225 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
226 assert(sd_rtnl_message_close_container(m) >= 0);
227 assert(sd_rtnl_message_close_container(m) == -EINVAL);
229 assert(rtnl_message_seal(NULL, m) >= 0);
231 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
232 assert(type == IFLA_LINKINFO);
233 assert(data == NULL);
234 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
235 assert(type == IFLA_INFO_KIND);
236 assert(streq("kind", (char *)data));
237 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
238 assert(type == IFLA_INFO_DATA);
239 assert(data == NULL);
240 assert(sd_rtnl_message_read(m, &type, &data) >= 0);
241 assert(type == IFLA_VLAN_ID);
242 assert(*(uint16_t *)data == 100);
243 assert(sd_rtnl_message_read(m, &type, &data) == 0);
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_read(m, &type, &data) == 0);
249 assert(sd_rtnl_message_exit_container(m) >= 0);
250 assert(sd_rtnl_message_exit_container(m) == -EINVAL);
253 static void test_match(void) {
254 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
256 assert(sd_rtnl_open(0, &rtnl) >= 0);
258 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
259 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
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) == 1);
263 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
273 unsigned int mtu = 0;
274 unsigned int *mtu_reply;
284 assert(sd_rtnl_open(0, &rtnl) >= 0);
287 if_loopback = (int) if_nametoindex("lo");
288 assert(if_loopback > 0);
290 test_async(if_loopback);
292 test_pipe(if_loopback);
294 test_event_loop(if_loopback);
296 test_link_configure(rtnl, if_loopback);
298 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
301 assert(sd_rtnl_message_get_type(m, &type) >= 0);
302 assert(type == RTM_GETLINK);
304 assert(sd_rtnl_message_read(m, &type, &data) == -EPERM);
306 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
307 assert(sd_rtnl_message_get_type(r, &type) >= 0);
308 assert(type == RTM_NEWLINK);
310 assert(sd_rtnl_message_read(m, &type, &data) == 0);
311 assert((r = sd_rtnl_message_unref(r)) == NULL);
313 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
314 assert((m = sd_rtnl_message_unref(m)) == NULL);
315 assert((r = sd_rtnl_message_unref(r)) == NULL);
317 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
320 assert(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
321 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == -EPERM);
322 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
323 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
325 assert(type == IFLA_MTU);
326 assert(*mtu_reply == 0);
328 assert(sd_rtnl_message_read(m, &type, &data) == 0);
330 while (sd_rtnl_message_read(r, &type, &data) > 0) {
333 // assert(*(unsigned int *) data == 65536);
336 // assert(streq((char *) data, "noqueue"));
339 assert(streq((char *) data, "lo"));
344 assert(sd_rtnl_flush(rtnl) >= 0);
346 assert((m = sd_rtnl_message_unref(m)) == NULL);
347 assert((r = sd_rtnl_message_unref(r)) == NULL);
348 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);