]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-rtnl/test-rtnl.c
sd-rtnl: add sd_rtnl_message_enter_container()
[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;
65f568bb 35 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
3dd215e0
TG
36 unsigned int mtu = 1450, mtu_out;
37 char *name_out;
38 struct ether_addr mac_out;
65f568bb
TG
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);
3dd215e0 47 assert_se(sd_rtnl_message_rewind(message) >= 0);
e5c4350b 48
3dd215e0
TG
49 assert_se(sd_rtnl_message_read_string(message, IFLA_IFNAME, &name_out) >= 0);
50 assert_se(streq(name, name_out));
65f568bb 51
3dd215e0
TG
52 assert_se(sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0);
53 assert_se(streq(mac, ether_ntoa(&mac_out)));
65f568bb 54
3dd215e0
TG
55 assert_se(sd_rtnl_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0);
56 assert_se(mtu == mtu_out);
d4bbdb77
TG
57}
58
eedee645
SS
59static void test_link_get(sd_rtnl *rtnl, int ifindex) {
60 sd_rtnl_message *m;
61 sd_rtnl_message *r;
11fc2e83 62 unsigned int mtu = 1500;
44caa5e7 63 char *str_data;
44caa5e7
SS
64 uint8_t u8_data;
65 uint32_t u32_data;
4e9e7f18 66 struct ether_addr eth_data;
eedee645 67
12e0f830
TG
68 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
69 assert_se(m);
eedee645
SS
70
71 /* u8 test cases */
12e0f830
TG
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);
eedee645
SS
75
76 /* u32 test cases */
12e0f830
TG
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);
eedee645 82
12e0f830 83 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
eedee645 84
44caa5e7
SS
85 assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
86
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);
90
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);
96
4e9e7f18
SS
97 assert_se(sd_rtnl_message_read_ether_addr(r, IFLA_ADDRESS, &eth_data) == 0);
98
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);
102}
103
104
105static void test_address_get(sd_rtnl *rtnl, int ifindex) {
106 sd_rtnl_message *m;
107 sd_rtnl_message *r;
108 struct in_addr in_data;
f66eeb6b 109 char *label;
4e9e7f18
SS
110
111 assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
112 assert_se(m);
113
114 assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
115
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);
f66eeb6b 118 assert_se(sd_rtnl_message_read_string(r, IFA_LABEL, &label) == 0);
4e9e7f18 119
12e0f830
TG
120 assert_se(sd_rtnl_flush(rtnl) >= 0);
121 assert_se((m = sd_rtnl_message_unref(m)) == NULL);
44caa5e7 122 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
4e9e7f18 123
eedee645
SS
124}
125
03d7e632 126static void test_route(void) {
cf6a8911 127 _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
44caa5e7 128 struct rtmsg *rtm;
3dd215e0
TG
129 struct in_addr addr, addr_data;
130 uint32_t index = 2, u32_data;
131 int r;
03d7e632 132
151b9b96 133 r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
03d7e632
TG
134 if (r < 0) {
135 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
136 return;
137 }
138
0a0dc69b
TG
139 addr.s_addr = htonl(INADDR_LOOPBACK);
140
141 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
03d7e632
TG
142 if (r < 0) {
143 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
144 return;
145 }
146
0a0dc69b 147 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
03d7e632
TG
148 if (r < 0) {
149 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
150 return;
151 }
152
3dd215e0 153 assert_se(sd_rtnl_message_rewind(req) >= 0);
e5c4350b 154
3dd215e0
TG
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);
03d7e632 157
3dd215e0
TG
158 assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
159 assert_se(u32_data == index);
44caa5e7
SS
160
161 rtm = NLMSG_DATA(req->hdr);
162 r = rtnl_message_parse(req,
163 &req->rta_offset_tb,
164 &req->rta_tb_size,
165 RTA_MAX,
166 RTM_RTA(rtm),
167 RTM_PAYLOAD(req->hdr));
168
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);
171
172 assert_se((req = sd_rtnl_message_unref(req)) == NULL);
03d7e632
TG
173}
174
d4bbdb77
TG
175static void test_multiple(void) {
176 sd_rtnl *rtnl1, *rtnl2;
177
12e0f830
TG
178 assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
179 assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
d4bbdb77
TG
180
181 rtnl1 = sd_rtnl_unref(rtnl1);
182 rtnl2 = sd_rtnl_unref(rtnl2);
65f568bb
TG
183}
184
e16bcf98 185static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
3dd215e0 186 char *ifname = userdata, *data;
e16bcf98 187
12e0f830
TG
188 assert_se(rtnl);
189 assert_se(m);
e16bcf98
TG
190
191 log_info("got link info about %s", ifname);
192 free(ifname);
193
3dd215e0
TG
194 assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &data) >= 0);
195 assert_se(streq(data, "lo"));
e16bcf98
TG
196
197 return 1;
198}
199
b4f2a5b1
TG
200static void test_event_loop(int ifindex) {
201 _cleanup_event_unref_ sd_event *event = NULL;
cf6a8911
LP
202 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
203 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
b4f2a5b1
TG
204 char *ifname;
205
206 ifname = strdup("lo2");
12e0f830 207 assert_se(ifname);
b4f2a5b1 208
12e0f830
TG
209 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
210 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
b4f2a5b1 211
12e0f830 212 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
b4f2a5b1 213
12e0f830 214 assert_se(sd_event_default(&event) >= 0);
b4f2a5b1 215
12e0f830 216 assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
b4f2a5b1 217
12e0f830 218 assert_se(sd_event_run(event, 0) >= 0);
b4f2a5b1 219
12e0f830 220 assert_se(sd_rtnl_detach_event(rtnl) >= 0);
44caa5e7
SS
221
222 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
b4f2a5b1
TG
223}
224
e16bcf98
TG
225static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
226 int *counter = userdata;
3dd215e0 227 int r;
e16bcf98
TG
228
229 (*counter) --;
230
3dd215e0
TG
231 r = sd_rtnl_message_get_errno(m);
232
233 log_info("%d left in pipe. got reply: %s", *counter, strerror(-r));
234
235 assert_se(r >= 0);
e16bcf98 236
3dd215e0 237 return 1;
e16bcf98
TG
238}
239
b4f2a5b1 240static void test_async(int ifindex) {
cf6a8911
LP
241 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
242 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
e16bcf98
TG
243 uint32_t serial;
244 char *ifname;
245
246 ifname = strdup("lo");
12e0f830 247 assert_se(ifname);
e16bcf98 248
12e0f830 249 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
e16bcf98 250
12e0f830 251 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
e16bcf98 252
12e0f830 253 assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
e16bcf98 254
12e0f830
TG
255 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
256 assert_se(sd_rtnl_process(rtnl, &r) >= 0);
44caa5e7
SS
257
258 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
e16bcf98
TG
259}
260
b4f2a5b1 261static void test_pipe(int ifindex) {
cf6a8911
LP
262 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
263 _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
e16bcf98 264 int counter = 0;
e16bcf98 265
12e0f830 266 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
e16bcf98 267
12e0f830
TG
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);
e16bcf98
TG
270
271 counter ++;
12e0f830 272 assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
e16bcf98
TG
273
274 counter ++;
12e0f830 275 assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
e16bcf98
TG
276
277 while (counter > 0) {
12e0f830
TG
278 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
279 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
e16bcf98 280 }
44caa5e7
SS
281
282 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
e16bcf98
TG
283}
284
33125ac5 285static void test_container(void) {
cf6a8911 286 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
3dd215e0
TG
287 struct ifinfomsg *ifi;
288 uint16_t u16_data;
44caa5e7 289 uint32_t u32_data;
3dd215e0 290 char *string_data;
44caa5e7 291 int r;
33125ac5 292
12e0f830
TG
293 assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
294
295 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
296 assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
3dd215e0 297 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
12e0f830
TG
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);
3dd215e0 302 assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
12e0f830
TG
303 assert_se(sd_rtnl_message_close_container(m) >= 0);
304 assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
305
3dd215e0
TG
306 assert_se(sd_rtnl_message_rewind(m) >= 0);
307
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));
311
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);
12e0f830 314 assert_se(sd_rtnl_message_exit_container(m) >= 0);
3dd215e0
TG
315
316 assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
317 assert_se(streq("vlan", string_data));
12e0f830 318 assert_se(sd_rtnl_message_exit_container(m) >= 0);
44caa5e7
SS
319
320 ifi = NLMSG_DATA(m->hdr);
321 r = rtnl_message_parse(m,
322 &m->rta_offset_tb,
323 &m->rta_tb_size,
324 IFLA_MAX,
325 IFLA_RTA(ifi),
326 IFLA_PAYLOAD(m->hdr));
327 if(r < 0)
328 return;
329
330 assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) == 0);
331
12e0f830 332 assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
33125ac5
TG
333}
334
8cec01b9 335static void test_match(void) {
cf6a8911 336 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
8cec01b9 337
12e0f830 338 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
8cec01b9 339
12e0f830
TG
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);
8cec01b9 342
12e0f830
TG
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);
44caa5e7
SS
346
347 assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
8cec01b9
TG
348}
349
65f568bb
TG
350int main(void) {
351 sd_rtnl *rtnl;
352 sd_rtnl_message *m;
353 sd_rtnl_message *r;
3dd215e0 354 char *string_data;
65f568bb 355 int if_loopback;
dabfa9d1 356 uint16_t type;
65f568bb 357
8cec01b9
TG
358 test_match();
359
d4bbdb77
TG
360 test_multiple();
361
03d7e632
TG
362 test_route();
363
33125ac5
TG
364 test_container();
365
12e0f830
TG
366 assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
367 assert_se(rtnl);
65f568bb
TG
368
369 if_loopback = (int) if_nametoindex("lo");
12e0f830 370 assert_se(if_loopback > 0);
65f568bb 371
b4f2a5b1
TG
372 test_async(if_loopback);
373
374 test_pipe(if_loopback);
375
376 test_event_loop(if_loopback);
377
65f568bb
TG
378 test_link_configure(rtnl, if_loopback);
379
12e0f830
TG
380 assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
381 assert_se(m);
65f568bb 382
12e0f830
TG
383 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
384 assert_se(type == RTM_GETLINK);
65f568bb 385
3dd215e0 386 assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
65f568bb 387
12e0f830
TG
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);
65f568bb 391
12e0f830 392 assert_se((r = sd_rtnl_message_unref(r)) == NULL);
65f568bb 393
12e0f830
TG
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);
65f568bb 397
eedee645 398 test_link_get(rtnl, if_loopback);
4e9e7f18 399 test_address_get(rtnl, if_loopback);
65f568bb 400
12e0f830
TG
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);
65f568bb
TG
405
406 return EXIT_SUCCESS;
407}