]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-rtnl/test-rtnl.c
rtnl: support interleaved reading and writing, and rewind
[thirdparty/systemd.git] / src / libsystemd-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
a33dece5 22#include <linux/rtnetlink.h>
65f568bb
TG
23#include <netinet/ether.h>
24
25#include "util.h"
26#include "macro.h"
27#include "sd-rtnl.h"
28#include "socket-util.h"
a33dece5 29#include "rtnl-util.h"
b4f2a5b1 30#include "event-util.h"
65f568bb
TG
31
32static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
33 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *message;
dabfa9d1 34 uint16_t type;
65f568bb
TG
35 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
36 unsigned int mtu = 1450;
37 void *data;
38
39 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
fc25d7f8 40 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &message) >= 0);
65f568bb
TG
41 assert(sd_rtnl_message_append(message, IFLA_IFNAME, name) >= 0);
42 assert(sd_rtnl_message_append(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
43 assert(sd_rtnl_message_append(message, IFLA_MTU, &mtu) >= 0);
44
0fc7531b 45 assert(sd_rtnl_message_read(message, &type, &data) > 0);
65f568bb
TG
46 assert(type == IFLA_IFNAME);
47 assert(streq(name, (char *) data));
48
0fc7531b 49 assert(sd_rtnl_message_read(message, &type, &data) > 0);
65f568bb
TG
50 assert(type == IFLA_ADDRESS);
51 assert(streq(mac, ether_ntoa(data)));
52
0fc7531b 53 assert(sd_rtnl_message_read(message, &type, &data) > 0);
65f568bb
TG
54 assert(type == IFLA_MTU);
55 assert(mtu == *(unsigned int *) data);
56
4555ec72 57 assert(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
d4bbdb77
TG
58}
59
03d7e632
TG
60static void test_route(void) {
61 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req;
62 uint32_t addr = htonl(INADDR_LOOPBACK);
63 uint32_t index = 2;
64 uint16_t type;
65 void *data;
66 int r;
67
1f01fb4f 68 r = sd_rtnl_message_route_new(RTM_NEWROUTE, AF_INET, &req);
03d7e632
TG
69 if (r < 0) {
70 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
71 return;
72 }
73
74 r = sd_rtnl_message_append(req, RTA_GATEWAY, &addr);
75 if (r < 0) {
76 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
77 return;
78 }
79
80 r = sd_rtnl_message_append(req, RTA_OIF, &index);
81 if (r < 0) {
82 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
83 return;
84 }
85
86 assert(sd_rtnl_message_read(req, &type, &data) > 0);
87 assert(type == RTA_GATEWAY);
88 assert(*(uint32_t *) data == addr);
89
90 assert(sd_rtnl_message_read(req, &type, &data) > 0);
91 assert(type == RTA_OIF);
92 assert(*(uint32_t *) data == index);
93}
94
d4bbdb77
TG
95static void test_multiple(void) {
96 sd_rtnl *rtnl1, *rtnl2;
97
98 assert(sd_rtnl_open(0, &rtnl1) >= 0);
99 assert(sd_rtnl_open(0, &rtnl2) >= 0);
100
101 rtnl1 = sd_rtnl_unref(rtnl1);
102 rtnl2 = sd_rtnl_unref(rtnl2);
65f568bb
TG
103}
104
e16bcf98
TG
105static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
106 void *data;
107 uint16_t type;
108 char *ifname = userdata;
109
110 assert(rtnl);
111 assert(m);
112
113 log_info("got link info about %s", ifname);
114 free(ifname);
115
116 while (sd_rtnl_message_read(m, &type, &data) > 0) {
117 switch (type) {
118// case IFLA_MTU:
119// assert(*(unsigned int *) data == 65536);
120// break;
121// case IFLA_QDISC:
122// assert(streq((char *) data, "noqueue"));
123// break;
124 case IFLA_IFNAME:
125 assert(streq((char *) data, "lo"));
126 break;
127 }
128 }
129
130 return 1;
131}
132
b4f2a5b1
TG
133static void test_event_loop(int ifindex) {
134 _cleanup_event_unref_ sd_event *event = NULL;
135 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
136 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
137 char *ifname;
138
139 ifname = strdup("lo2");
140 assert(ifname);
141
142 assert(sd_rtnl_open(0, &rtnl) >= 0);
fc25d7f8 143 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m) >= 0);
b4f2a5b1
TG
144
145 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
146
147 assert(sd_event_default(&event) >= 0);
148
149 assert(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
150
151 assert(sd_event_run(event, 0) >= 0);
152
153 assert(sd_rtnl_detach_event(rtnl) >= 0);
154}
155
e16bcf98
TG
156static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
157 int *counter = userdata;
158
159 (*counter) --;
160
161 log_info("got reply, %d left in pipe", *counter);
162
163 return sd_rtnl_message_get_errno(m);
164}
165
b4f2a5b1 166static void test_async(int ifindex) {
e16bcf98
TG
167 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
168 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
e16bcf98
TG
169 uint32_t serial;
170 char *ifname;
171
172 ifname = strdup("lo");
b4f2a5b1 173 assert(ifname);
e16bcf98
TG
174
175 assert(sd_rtnl_open(0, &rtnl) >= 0);
176
fc25d7f8 177 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m) >= 0);
e16bcf98
TG
178
179 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
180
181 assert(sd_rtnl_wait(rtnl, 0) >= 0);
182 assert(sd_rtnl_process(rtnl, &r) >= 0);
183}
184
b4f2a5b1 185static void test_pipe(int ifindex) {
e16bcf98
TG
186 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
187 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
188 int counter = 0;
e16bcf98
TG
189
190 assert(sd_rtnl_open(0, &rtnl) >= 0);
191
fc25d7f8
TG
192 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m1) >= 0);
193 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m2) >= 0);
e16bcf98
TG
194
195 counter ++;
196 assert(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
197
198 counter ++;
199 assert(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
200
201 while (counter > 0) {
202 assert(sd_rtnl_wait(rtnl, 0) >= 0);
203 assert(sd_rtnl_process(rtnl, NULL) >= 0);
204 }
205}
206
33125ac5
TG
207static void test_container(void) {
208 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
209 uint16_t type;
210 void *data;
211
fc25d7f8 212 assert(sd_rtnl_message_link_new(RTM_NEWLINK, 0, &m) >= 0);
33125ac5
TG
213
214 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
215 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -EINVAL);
216 assert(sd_rtnl_message_append(m, IFLA_INFO_KIND, "kind") >= 0);
217 assert(sd_rtnl_message_close_container(m) >= 0);
218 assert(sd_rtnl_message_close_container(m) == -EINVAL);
219
220 assert(sd_rtnl_message_read(m, &type, &data) == -EINVAL);
221
222/* TODO: add support for entering containers
223 assert(sd_rtnl_message_read(m, &type, &data) > 0);
224 assert(type == IFLA_INFO_KIND);
225 assert(streq("kind", (char *) data));
226
227 assert(sd_rtnl_message_read(m, &type, &data) == 0);
228*/
229}
230
8cec01b9
TG
231static void test_match(void) {
232 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
233
234 assert(sd_rtnl_open(0, &rtnl) >= 0);
235
23a7f0f7
TG
236 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
237 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
8cec01b9 238
23a7f0f7
TG
239 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
240 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
241 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
8cec01b9
TG
242}
243
65f568bb
TG
244int main(void) {
245 sd_rtnl *rtnl;
246 sd_rtnl_message *m;
247 sd_rtnl_message *r;
248 void *data;
249 int if_loopback;
dabfa9d1 250 uint16_t type;
65f568bb
TG
251 unsigned int mtu = 0;
252 unsigned int *mtu_reply;
253
8cec01b9
TG
254 test_match();
255
d4bbdb77
TG
256 test_multiple();
257
03d7e632
TG
258 test_route();
259
33125ac5
TG
260 test_container();
261
65f568bb
TG
262 assert(sd_rtnl_open(0, &rtnl) >= 0);
263 assert(rtnl);
264
265 if_loopback = (int) if_nametoindex("lo");
266 assert(if_loopback > 0);
267
b4f2a5b1
TG
268 test_async(if_loopback);
269
270 test_pipe(if_loopback);
271
272 test_event_loop(if_loopback);
273
65f568bb
TG
274 test_link_configure(rtnl, if_loopback);
275
fc25d7f8 276 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
65f568bb
TG
277 assert(m);
278
279 assert(sd_rtnl_message_get_type(m, &type) >= 0);
280 assert(type == RTM_GETLINK);
281
282 assert(sd_rtnl_message_read(m, &type, &data) == 0);
283
4555ec72 284 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
65f568bb
TG
285 assert(sd_rtnl_message_get_type(r, &type) >= 0);
286 assert(type == RTM_NEWLINK);
287
8e1519bd 288 assert(sd_rtnl_message_read(m, &type, &data) == 0);
65f568bb
TG
289 assert((r = sd_rtnl_message_unref(r)) == NULL);
290
fe4824e0 291 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
65f568bb
TG
292 assert((m = sd_rtnl_message_unref(m)) == NULL);
293 assert((r = sd_rtnl_message_unref(r)) == NULL);
294
fc25d7f8 295 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
65f568bb
TG
296 assert(m);
297
298 assert(sd_rtnl_message_append(m, IFLA_MTU, &mtu) >= 0);
299 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
300
301 assert(type == IFLA_MTU);
302 assert(*mtu_reply == 0);
303
8e1519bd 304 assert(sd_rtnl_message_read(m, &type, &data) == 0);
65f568bb 305
4555ec72 306 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
03d7e632 307 while (sd_rtnl_message_read(r, &type, &data) > 0) {
65f568bb 308 switch (type) {
eab97a46
TG
309// case IFLA_MTU:
310// assert(*(unsigned int *) data == 65536);
03d7e632 311// break;
eab97a46
TG
312// case IFLA_QDISC:
313// assert(streq((char *) data, "noqueue"));
03d7e632 314// break;
65f568bb
TG
315 case IFLA_IFNAME:
316 assert(streq((char *) data, "lo"));
03d7e632 317 break;
65f568bb
TG
318 }
319 }
320
b4f2a5b1
TG
321 assert(sd_rtnl_flush(rtnl) >= 0);
322
65f568bb
TG
323 assert((m = sd_rtnl_message_unref(m)) == NULL);
324 assert((r = sd_rtnl_message_unref(r)) == NULL);
325 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);
326
327 return EXIT_SUCCESS;
328}