]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-rtnl/test-rtnl.c
sd-rtnl:introduce table-based lookup and typesafe read() functions
[thirdparty/systemd.git] / src / libsystemd / sd-rtnl / test-rtnl.c
CommitLineData
65f568bb
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
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.
12
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.
17
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/>.
20***/
21
22#include <netinet/ether.h>
23
24#include "util.h"
25#include "macro.h"
26#include "sd-rtnl.h"
27#include "socket-util.h"
a33dece5 28#include "rtnl-util.h"
b4f2a5b1 29#include "event-util.h"
5723e176 30#include "missing.h"
44caa5e7 31#include "rtnl-internal.h"
65f568bb
TG
32
33static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
cf6a8911 34 _cleanup_rtnl_message_unref_ sd_rtnl_message *message;
dabfa9d1 35 uint16_t type;
65f568bb
TG
36 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
37 unsigned int mtu = 1450;
38 void *data;
39
40 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
12e0f830
TG
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);
65f568bb 45
12e0f830 46 assert_se(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
e5c4350b 47
12e0f830
TG
48 assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
49 assert_se(type == IFLA_IFNAME);
50 assert_se(streq(name, (char *) data));
65f568bb 51
12e0f830
TG
52 assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
53 assert_se(type == IFLA_ADDRESS);
54 assert_se(streq(mac, ether_ntoa(data)));
65f568bb 55
12e0f830
TG
56 assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
57 assert_se(type == IFLA_MTU);
58 assert_se(mtu == *(unsigned int *) data);
d4bbdb77
TG
59}
60
eedee645
SS
61static void test_link_get(sd_rtnl *rtnl, int ifindex) {
62 sd_rtnl_message *m;
63 sd_rtnl_message *r;
11fc2e83 64 unsigned int mtu = 1500;
eedee645
SS
65 unsigned int *mtu_reply;
66 void *data;
44caa5e7 67 char *str_data;
eedee645 68 uint16_t type;
44caa5e7
SS
69 uint8_t u8_data;
70 uint32_t u32_data;
eedee645 71
12e0f830
TG
72 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
73 assert_se(m);
eedee645
SS
74
75 /* u8 test cases */
12e0f830
TG
76 assert_se(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
77 assert_se(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
78 assert_se(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
eedee645
SS
79
80 /* u32 test cases */
12e0f830
TG
81 assert_se(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
82 assert_se(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0);
83 assert_se(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
84 assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
85 assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
eedee645 86
12e0f830 87 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
eedee645
SS
88
89 /* u8 read back */
12e0f830
TG
90 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
91 assert_se(type == IFLA_CARRIER);
eedee645 92
12e0f830
TG
93 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
94 assert_se(type == IFLA_OPERSTATE);
eedee645 95
12e0f830
TG
96 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
97 assert_se(type == IFLA_LINKMODE);
eedee645
SS
98
99 /* u32 read back */
12e0f830
TG
100 assert_se(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
101 assert_se(type == IFLA_MTU);
102 assert_se(*mtu_reply == mtu);
eedee645 103
12e0f830
TG
104 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
105 assert_se(type == IFLA_GROUP);
eedee645 106
12e0f830
TG
107 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
108 assert_se(type == IFLA_TXQLEN);
eedee645 109
12e0f830
TG
110 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
111 assert_se(type == IFLA_NUM_TX_QUEUES);
eedee645 112
12e0f830
TG
113 assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
114 assert_se(type == IFLA_NUM_RX_QUEUES);
eedee645
SS
115
116 while (sd_rtnl_message_read(r, &type, &data) > 0) {
117 switch (type) {
118// case IFLA_MTU:
12e0f830 119// assert_se(*(unsigned int *) data == 65536);
eedee645
SS
120// break;
121// case IFLA_QDISC:
12e0f830 122// assert_se(streq((char *) data, "noqueue"));
eedee645
SS
123// break;
124 case IFLA_IFNAME:
12e0f830 125 assert_se(streq((char *) data, "lo"));
eedee645
SS
126 break;
127 }
128 }
129
44caa5e7
SS
130 assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
131
132 assert_se(sd_rtnl_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0);
133 assert_se(sd_rtnl_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0);
134 assert_se(sd_rtnl_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0);
135
136 assert_se(sd_rtnl_message_read_u32(r, IFLA_MTU, &u32_data) == 0);
137 assert_se(sd_rtnl_message_read_u32(r, IFLA_GROUP, &u32_data) == 0);
138 assert_se(sd_rtnl_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0);
139 assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0);
140 assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0);
141
12e0f830
TG
142 assert_se(sd_rtnl_flush(rtnl) >= 0);
143 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
44caa5e7 144 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
eedee645
SS
145}
146
03d7e632 147static void test_route(void) {
cf6a8911 148 _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
0a0dc69b 149 struct in_addr addr;
03d7e632
TG
150 uint32_t index = 2;
151 uint16_t type;
152 void *data;
44caa5e7 153 uint32_t u32_data;
03d7e632 154 int r;
44caa5e7 155 struct rtmsg *rtm;
03d7e632 156
151b9b96 157 r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
03d7e632
TG
158 if (r < 0) {
159 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
160 return;
161 }
162
0a0dc69b
TG
163 addr.s_addr = htonl(INADDR_LOOPBACK);
164
165 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
03d7e632
TG
166 if (r < 0) {
167 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
168 return;
169 }
170
0a0dc69b 171 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
03d7e632
TG
172 if (r < 0) {
173 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
174 return;
175 }
176
12e0f830 177 assert_se(rtnl_message_seal(NULL, req) >= 0);
e5c4350b 178
12e0f830
TG
179 assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
180 assert_se(type == RTA_GATEWAY);
181 assert_se(((struct in_addr *)data)->s_addr == addr.s_addr);
03d7e632 182
12e0f830
TG
183 assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
184 assert_se(type == RTA_OIF);
185 assert_se(*(uint32_t *) data == index);
44caa5e7
SS
186
187 rtm = NLMSG_DATA(req->hdr);
188 r = rtnl_message_parse(req,
189 &req->rta_offset_tb,
190 &req->rta_tb_size,
191 RTA_MAX,
192 RTM_RTA(rtm),
193 RTM_PAYLOAD(req->hdr));
194
195 assert_se(sd_rtnl_message_read_u32(req, RTA_GATEWAY, &u32_data) == 0);
196 assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) == 0);
197
198 assert_se((req = sd_rtnl_message_unref(req)) == NULL);
03d7e632
TG
199}
200
d4bbdb77
TG
201static void test_multiple(void) {
202 sd_rtnl *rtnl1, *rtnl2;
203
12e0f830
TG
204 assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
205 assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
d4bbdb77
TG
206
207 rtnl1 = sd_rtnl_unref(rtnl1);
208 rtnl2 = sd_rtnl_unref(rtnl2);
65f568bb
TG
209}
210
e16bcf98
TG
211static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
212 void *data;
213 uint16_t type;
214 char *ifname = userdata;
215
12e0f830
TG
216 assert_se(rtnl);
217 assert_se(m);
e16bcf98
TG
218
219 log_info("got link info about %s", ifname);
220 free(ifname);
221
222 while (sd_rtnl_message_read(m, &type, &data) > 0) {
223 switch (type) {
224// case IFLA_MTU:
12e0f830 225// assert_se(*(unsigned int *) data == 65536);
e16bcf98
TG
226// break;
227// case IFLA_QDISC:
12e0f830 228// assert_se(streq((char *) data, "noqueue"));
e16bcf98
TG
229// break;
230 case IFLA_IFNAME:
12e0f830 231 assert_se(streq((char *) data, "lo"));
e16bcf98
TG
232 break;
233 }
234 }
235
236 return 1;
237}
238
b4f2a5b1
TG
239static void test_event_loop(int ifindex) {
240 _cleanup_event_unref_ sd_event *event = NULL;
cf6a8911
LP
241 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
242 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
b4f2a5b1
TG
243 char *ifname;
244
245 ifname = strdup("lo2");
12e0f830 246 assert_se(ifname);
b4f2a5b1 247
12e0f830
TG
248 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
249 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
b4f2a5b1 250
12e0f830 251 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
b4f2a5b1 252
12e0f830 253 assert_se(sd_event_default(&event) >= 0);
b4f2a5b1 254
12e0f830 255 assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
b4f2a5b1 256
12e0f830 257 assert_se(sd_event_run(event, 0) >= 0);
b4f2a5b1 258
12e0f830 259 assert_se(sd_rtnl_detach_event(rtnl) >= 0);
44caa5e7
SS
260
261 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
b4f2a5b1
TG
262}
263
e16bcf98
TG
264static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
265 int *counter = userdata;
266
267 (*counter) --;
268
269 log_info("got reply, %d left in pipe", *counter);
270
271 return sd_rtnl_message_get_errno(m);
272}
273
b4f2a5b1 274static void test_async(int ifindex) {
cf6a8911
LP
275 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
276 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
e16bcf98
TG
277 uint32_t serial;
278 char *ifname;
279
280 ifname = strdup("lo");
12e0f830 281 assert_se(ifname);
e16bcf98 282
12e0f830 283 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
e16bcf98 284
12e0f830 285 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
e16bcf98 286
12e0f830 287 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
e16bcf98 288
12e0f830
TG
289 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
290 assert_se(sd_rtnl_process(rtnl, &r) >= 0);
44caa5e7
SS
291
292 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
e16bcf98
TG
293}
294
b4f2a5b1 295static void test_pipe(int ifindex) {
cf6a8911
LP
296 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
297 _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
e16bcf98 298 int counter = 0;
e16bcf98 299
12e0f830 300 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
e16bcf98 301
12e0f830
TG
302 assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
303 assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
e16bcf98
TG
304
305 counter ++;
12e0f830 306 assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
e16bcf98
TG
307
308 counter ++;
12e0f830 309 assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
e16bcf98
TG
310
311 while (counter > 0) {
12e0f830
TG
312 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
313 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
e16bcf98 314 }
44caa5e7
SS
315
316 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
e16bcf98
TG
317}
318
33125ac5 319static void test_container(void) {
cf6a8911 320 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
33125ac5 321 uint16_t type;
44caa5e7 322 uint32_t u32_data;
33125ac5 323 void *data;
44caa5e7
SS
324 int r;
325 struct ifinfomsg *ifi;
33125ac5 326
12e0f830
TG
327 assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
328
329 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
330 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
331 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
332 assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
333 assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
334 assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
335 assert_se(sd_rtnl_message_close_container(m) >= 0);
336 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
337 assert_se(sd_rtnl_message_close_container(m) >= 0);
338 assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
339
340 assert_se(rtnl_message_seal(NULL, m) >= 0);
341
342 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
343 assert_se(type == IFLA_LINKINFO);
344 assert_se(data == NULL);
3b35ade3 345/*
12e0f830
TG
346 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
347 assert_se(type == IFLA_INFO_KIND);
348 assert_se(streq("kind", (char *)data));
349 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
350 assert_se(type == IFLA_INFO_DATA);
351 assert_se(data == NULL);
352 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
353 assert_se(type == IFLA_VLAN_ID);
354 assert_se(*(uint16_t *)data == 100);
355 assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
356 assert_se(sd_rtnl_message_exit_container(m) >= 0);
357 assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
358 assert_se(type == IFLA_INFO_KIND);
359 assert_se(streq("kind", (char *)data));
360 assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
361 assert_se(sd_rtnl_message_exit_container(m) >= 0);
3b35ade3 362*/
44caa5e7
SS
363
364 ifi = NLMSG_DATA(m->hdr);
365 r = rtnl_message_parse(m,
366 &m->rta_offset_tb,
367 &m->rta_tb_size,
368 IFLA_MAX,
369 IFLA_RTA(ifi),
370 IFLA_PAYLOAD(m->hdr));
371 if(r < 0)
372 return;
373
374 assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) == 0);
375
12e0f830 376 assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
33125ac5
TG
377}
378
8cec01b9 379static void test_match(void) {
cf6a8911 380 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
8cec01b9 381
12e0f830 382 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
8cec01b9 383
12e0f830
TG
384 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
385 assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
8cec01b9 386
12e0f830
TG
387 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
388 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
389 assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
44caa5e7
SS
390
391 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
8cec01b9
TG
392}
393
65f568bb
TG
394int main(void) {
395 sd_rtnl *rtnl;
396 sd_rtnl_message *m;
397 sd_rtnl_message *r;
398 void *data;
399 int if_loopback;
dabfa9d1 400 uint16_t type;
65f568bb 401
8cec01b9
TG
402 test_match();
403
d4bbdb77
TG
404 test_multiple();
405
03d7e632
TG
406 test_route();
407
33125ac5
TG
408 test_container();
409
12e0f830
TG
410 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
411 assert_se(rtnl);
65f568bb
TG
412
413 if_loopback = (int) if_nametoindex("lo");
12e0f830 414 assert_se(if_loopback > 0);
65f568bb 415
b4f2a5b1
TG
416 test_async(if_loopback);
417
418 test_pipe(if_loopback);
419
420 test_event_loop(if_loopback);
421
65f568bb
TG
422 test_link_configure(rtnl, if_loopback);
423
12e0f830
TG
424 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
425 assert_se(m);
65f568bb 426
12e0f830
TG
427 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
428 assert_se(type == RTM_GETLINK);
65f568bb 429
12e0f830 430 assert_se(sd_rtnl_message_read(m, &type, &data) == -EPERM);
65f568bb 431
12e0f830
TG
432 assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
433 assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
434 assert_se(type == RTM_NEWLINK);
65f568bb 435
12e0f830
TG
436 assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
437 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
65f568bb 438
12e0f830
TG
439 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
440 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
441 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
65f568bb 442
eedee645 443 test_link_get(rtnl, if_loopback);
65f568bb 444
12e0f830
TG
445 assert_se(sd_rtnl_flush(rtnl) >= 0);
446 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
447 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
448 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
65f568bb
TG
449
450 return EXIT_SUCCESS;
451}