]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-rtnl/test-rtnl.c
rtnl: replace message_append by typesafe versions
[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);
0a0dc69b
TG
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);
65f568bb 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;
0a0dc69b 62 struct in_addr addr;
03d7e632
TG
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
0a0dc69b
TG
74 addr.s_addr = htonl(INADDR_LOOPBACK);
75
76 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
03d7e632
TG
77 if (r < 0) {
78 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
79 return;
80 }
81
0a0dc69b 82 r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
03d7e632
TG
83 if (r < 0) {
84 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
85 return;
86 }
87
88 assert(sd_rtnl_message_read(req, &type, &data) > 0);
89 assert(type == RTA_GATEWAY);
0a0dc69b 90 assert(((struct in_addr *)data)->s_addr == addr.s_addr);
03d7e632
TG
91
92 assert(sd_rtnl_message_read(req, &type, &data) > 0);
93 assert(type == RTA_OIF);
94 assert(*(uint32_t *) data == index);
95}
96
d4bbdb77
TG
97static void test_multiple(void) {
98 sd_rtnl *rtnl1, *rtnl2;
99
100 assert(sd_rtnl_open(0, &rtnl1) >= 0);
101 assert(sd_rtnl_open(0, &rtnl2) >= 0);
102
103 rtnl1 = sd_rtnl_unref(rtnl1);
104 rtnl2 = sd_rtnl_unref(rtnl2);
65f568bb
TG
105}
106
e16bcf98
TG
107static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
108 void *data;
109 uint16_t type;
110 char *ifname = userdata;
111
112 assert(rtnl);
113 assert(m);
114
115 log_info("got link info about %s", ifname);
116 free(ifname);
117
118 while (sd_rtnl_message_read(m, &type, &data) > 0) {
119 switch (type) {
120// case IFLA_MTU:
121// assert(*(unsigned int *) data == 65536);
122// break;
123// case IFLA_QDISC:
124// assert(streq((char *) data, "noqueue"));
125// break;
126 case IFLA_IFNAME:
127 assert(streq((char *) data, "lo"));
128 break;
129 }
130 }
131
132 return 1;
133}
134
b4f2a5b1
TG
135static void test_event_loop(int ifindex) {
136 _cleanup_event_unref_ sd_event *event = NULL;
137 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
138 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
139 char *ifname;
140
141 ifname = strdup("lo2");
142 assert(ifname);
143
144 assert(sd_rtnl_open(0, &rtnl) >= 0);
fc25d7f8 145 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m) >= 0);
b4f2a5b1
TG
146
147 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
148
149 assert(sd_event_default(&event) >= 0);
150
151 assert(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
152
153 assert(sd_event_run(event, 0) >= 0);
154
155 assert(sd_rtnl_detach_event(rtnl) >= 0);
156}
157
e16bcf98
TG
158static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
159 int *counter = userdata;
160
161 (*counter) --;
162
163 log_info("got reply, %d left in pipe", *counter);
164
165 return sd_rtnl_message_get_errno(m);
166}
167
b4f2a5b1 168static void test_async(int ifindex) {
e16bcf98
TG
169 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
170 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
e16bcf98
TG
171 uint32_t serial;
172 char *ifname;
173
174 ifname = strdup("lo");
b4f2a5b1 175 assert(ifname);
e16bcf98
TG
176
177 assert(sd_rtnl_open(0, &rtnl) >= 0);
178
fc25d7f8 179 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m) >= 0);
e16bcf98
TG
180
181 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
182
183 assert(sd_rtnl_wait(rtnl, 0) >= 0);
184 assert(sd_rtnl_process(rtnl, &r) >= 0);
185}
186
b4f2a5b1 187static void test_pipe(int ifindex) {
e16bcf98
TG
188 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
189 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
190 int counter = 0;
e16bcf98
TG
191
192 assert(sd_rtnl_open(0, &rtnl) >= 0);
193
fc25d7f8
TG
194 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m1) >= 0);
195 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &m2) >= 0);
e16bcf98
TG
196
197 counter ++;
198 assert(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
199
200 counter ++;
201 assert(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
202
203 while (counter > 0) {
204 assert(sd_rtnl_wait(rtnl, 0) >= 0);
205 assert(sd_rtnl_process(rtnl, NULL) >= 0);
206 }
207}
208
33125ac5
TG
209static void test_container(void) {
210 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
211 uint16_t type;
212 void *data;
213
fc25d7f8 214 assert(sd_rtnl_message_link_new(RTM_NEWLINK, 0, &m) >= 0);
33125ac5
TG
215
216 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
217 assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -EINVAL);
0a0dc69b 218 assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
33125ac5
TG
219 assert(sd_rtnl_message_close_container(m) >= 0);
220 assert(sd_rtnl_message_close_container(m) == -EINVAL);
221
222 assert(sd_rtnl_message_read(m, &type, &data) == -EINVAL);
223
224/* TODO: add support for entering containers
225 assert(sd_rtnl_message_read(m, &type, &data) > 0);
226 assert(type == IFLA_INFO_KIND);
227 assert(streq("kind", (char *) data));
228
229 assert(sd_rtnl_message_read(m, &type, &data) == 0);
230*/
231}
232
8cec01b9
TG
233static void test_match(void) {
234 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
235
236 assert(sd_rtnl_open(0, &rtnl) >= 0);
237
23a7f0f7
TG
238 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
239 assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
8cec01b9 240
23a7f0f7
TG
241 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
242 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
243 assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
8cec01b9
TG
244}
245
65f568bb
TG
246int main(void) {
247 sd_rtnl *rtnl;
248 sd_rtnl_message *m;
249 sd_rtnl_message *r;
250 void *data;
251 int if_loopback;
dabfa9d1 252 uint16_t type;
65f568bb
TG
253 unsigned int mtu = 0;
254 unsigned int *mtu_reply;
255
8cec01b9
TG
256 test_match();
257
d4bbdb77
TG
258 test_multiple();
259
03d7e632
TG
260 test_route();
261
33125ac5
TG
262 test_container();
263
65f568bb
TG
264 assert(sd_rtnl_open(0, &rtnl) >= 0);
265 assert(rtnl);
266
267 if_loopback = (int) if_nametoindex("lo");
268 assert(if_loopback > 0);
269
b4f2a5b1
TG
270 test_async(if_loopback);
271
272 test_pipe(if_loopback);
273
274 test_event_loop(if_loopback);
275
65f568bb
TG
276 test_link_configure(rtnl, if_loopback);
277
fc25d7f8 278 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
65f568bb
TG
279 assert(m);
280
281 assert(sd_rtnl_message_get_type(m, &type) >= 0);
282 assert(type == RTM_GETLINK);
283
284 assert(sd_rtnl_message_read(m, &type, &data) == 0);
285
4555ec72 286 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
65f568bb
TG
287 assert(sd_rtnl_message_get_type(r, &type) >= 0);
288 assert(type == RTM_NEWLINK);
289
8e1519bd 290 assert(sd_rtnl_message_read(m, &type, &data) == 0);
65f568bb
TG
291 assert((r = sd_rtnl_message_unref(r)) == NULL);
292
fe4824e0 293 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
65f568bb
TG
294 assert((m = sd_rtnl_message_unref(m)) == NULL);
295 assert((r = sd_rtnl_message_unref(r)) == NULL);
296
fc25d7f8 297 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
65f568bb
TG
298 assert(m);
299
0a0dc69b 300 assert(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
65f568bb
TG
301 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
302
303 assert(type == IFLA_MTU);
304 assert(*mtu_reply == 0);
305
8e1519bd 306 assert(sd_rtnl_message_read(m, &type, &data) == 0);
65f568bb 307
4555ec72 308 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
03d7e632 309 while (sd_rtnl_message_read(r, &type, &data) > 0) {
65f568bb 310 switch (type) {
eab97a46
TG
311// case IFLA_MTU:
312// assert(*(unsigned int *) data == 65536);
03d7e632 313// break;
eab97a46
TG
314// case IFLA_QDISC:
315// assert(streq((char *) data, "noqueue"));
03d7e632 316// break;
65f568bb
TG
317 case IFLA_IFNAME:
318 assert(streq((char *) data, "lo"));
03d7e632 319 break;
65f568bb
TG
320 }
321 }
322
b4f2a5b1
TG
323 assert(sd_rtnl_flush(rtnl) >= 0);
324
65f568bb
TG
325 assert((m = sd_rtnl_message_unref(m)) == NULL);
326 assert((r = sd_rtnl_message_unref(r)) == NULL);
327 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);
328
329 return EXIT_SUCCESS;
330}