chiark / gitweb /
sd-rtnl: fix broken test cases and add support for tunnel
[elogind.git] / src / libsystemd / sd-rtnl / test-rtnl.c
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"
28 #include "rtnl-util.h"
29 #include "event-util.h"
30 #include "missing.h"
31 #include "rtnl-internal.h"
32
33 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
34         _cleanup_rtnl_message_unref_ sd_rtnl_message *message;
35         const char *mac = "98:fe:94:3f:c6:18", *name = "test";
36         unsigned int mtu = 1450, mtu_out;
37         char *name_out;
38         struct ether_addr mac_out;
39
40         /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
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);
45
46         assert_se(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
47         assert_se(sd_rtnl_message_rewind(message) >= 0);
48
49         assert_se(sd_rtnl_message_read_string(message, IFLA_IFNAME, &name_out) >= 0);
50         assert_se(streq(name, name_out));
51
52         assert_se(sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0);
53         assert_se(streq(mac, ether_ntoa(&mac_out)));
54
55         assert_se(sd_rtnl_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0);
56         assert_se(mtu == mtu_out);
57 }
58
59 static void test_link_get(sd_rtnl *rtnl, int ifindex) {
60         sd_rtnl_message *m;
61         sd_rtnl_message *r;
62         unsigned int mtu = 1500;
63         char *str_data;
64         uint8_t u8_data;
65         uint32_t u32_data;
66         struct ether_addr eth_data;
67
68         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
69         assert_se(m);
70
71         /* u8 test cases  */
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);
75
76         /* u32 test cases */
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);
82
83         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
84
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
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
105 static 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;
109         struct ifa_cacheinfo cache;
110         char *label;
111
112         assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
113         assert_se(m);
114
115         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
116
117         assert_se(sd_rtnl_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0);
118         assert_se(sd_rtnl_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0);
119         assert_se(sd_rtnl_message_read_string(r, IFA_LABEL, &label) == 0);
120         assert_se(sd_rtnl_message_read_cache_info(r, IFA_CACHEINFO, &cache) == 0);
121
122         assert_se(sd_rtnl_flush(rtnl) >= 0);
123         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
124         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
125
126 }
127
128 static void test_route(void) {
129         _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
130         struct in_addr addr, addr_data;
131         uint32_t index = 2, u32_data;
132         int r;
133
134         r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
135         if (r < 0) {
136                 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
137                 return;
138         }
139
140         addr.s_addr = htonl(INADDR_LOOPBACK);
141
142         r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
143         if (r < 0) {
144                 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
145                 return;
146         }
147
148         r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
149         if (r < 0) {
150                 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
151                 return;
152         }
153
154         assert_se(sd_rtnl_message_rewind(req) >= 0);
155
156         assert_se(sd_rtnl_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
157         assert_se(addr_data.s_addr == addr.s_addr);
158
159         assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
160         assert_se(u32_data == index);
161
162         assert_se((req = sd_rtnl_message_unref(req)) == NULL);
163 }
164
165 static void test_multiple(void) {
166         sd_rtnl *rtnl1, *rtnl2;
167
168         assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
169         assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
170
171         rtnl1 = sd_rtnl_unref(rtnl1);
172         rtnl2 = sd_rtnl_unref(rtnl2);
173 }
174
175 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
176         char *ifname = userdata, *data;
177
178         assert_se(rtnl);
179         assert_se(m);
180
181         log_info("got link info about %s", ifname);
182         free(ifname);
183
184         assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &data) >= 0);
185         assert_se(streq(data, "lo"));
186
187         return 1;
188 }
189
190 static void test_event_loop(int ifindex) {
191         _cleanup_event_unref_ sd_event *event = NULL;
192         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
193         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
194         char *ifname;
195
196         ifname = strdup("lo2");
197         assert_se(ifname);
198
199         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
200         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
201
202         assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
203
204         assert_se(sd_event_default(&event) >= 0);
205
206         assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
207
208         assert_se(sd_event_run(event, 0) >= 0);
209
210         assert_se(sd_rtnl_detach_event(rtnl) >= 0);
211
212         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
213 }
214
215 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
216         int *counter = userdata;
217         int r;
218
219         (*counter) --;
220
221         r = sd_rtnl_message_get_errno(m);
222
223         log_info("%d left in pipe. got reply: %s", *counter, strerror(-r));
224
225         assert_se(r >= 0);
226
227         return 1;
228 }
229
230 static void test_async(int ifindex) {
231         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
232         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
233         uint32_t serial;
234         char *ifname;
235
236         ifname = strdup("lo");
237         assert_se(ifname);
238
239         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
240
241         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
242
243         assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
244
245         assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
246         assert_se(sd_rtnl_process(rtnl, &r) >= 0);
247
248         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
249 }
250
251 static void test_pipe(int ifindex) {
252         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
253         _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
254         int counter = 0;
255
256         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
257
258         assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
259         assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
260
261         counter ++;
262         assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
263
264         counter ++;
265         assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
266
267         while (counter > 0) {
268                 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
269                 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
270         }
271
272         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
273 }
274
275 static void test_container(void) {
276         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
277         uint16_t u16_data;
278         uint32_t u32_data;
279         char *string_data;
280
281         assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
282
283         assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
284         assert_se(sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0);
285         assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
286         assert_se(sd_rtnl_message_close_container(m) >= 0);
287         assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
288         assert_se(sd_rtnl_message_close_container(m) >= 0);
289         assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
290
291         assert_se(sd_rtnl_message_rewind(m) >= 0);
292
293         assert_se(sd_rtnl_message_enter_container(m, IFLA_LINKINFO) >= 0);
294         assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
295         assert_se(streq("vlan", string_data));
296
297         assert_se(sd_rtnl_message_enter_container(m, IFLA_INFO_DATA) >= 0);
298         assert_se(sd_rtnl_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0);
299         assert_se(sd_rtnl_message_exit_container(m) >= 0);
300
301         assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
302         assert_se(streq("vlan", string_data));
303         assert_se(sd_rtnl_message_exit_container(m) >= 0);
304
305         assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0);
306
307         assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
308 }
309
310 static void test_match(void) {
311         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
312
313         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
314
315         assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
316         assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
317
318         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
319         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
320         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
321
322         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
323 }
324
325 int main(void) {
326         sd_rtnl *rtnl;
327         sd_rtnl_message *m;
328         sd_rtnl_message *r;
329         char *string_data;
330         int if_loopback;
331         uint16_t type;
332
333         test_match();
334
335         test_multiple();
336
337         test_route();
338
339         test_container();
340
341         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
342         assert_se(rtnl);
343
344         if_loopback = (int) if_nametoindex("lo");
345         assert_se(if_loopback > 0);
346
347         test_async(if_loopback);
348
349         test_pipe(if_loopback);
350
351         test_event_loop(if_loopback);
352
353         test_link_configure(rtnl, if_loopback);
354
355         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
356         assert_se(m);
357
358         assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
359         assert_se(type == RTM_GETLINK);
360
361         assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
362
363         assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
364         assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
365         assert_se(type == RTM_NEWLINK);
366
367         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
368
369         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
370         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
371         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
372
373         test_link_get(rtnl, if_loopback);
374         test_address_get(rtnl, if_loopback);
375
376         assert_se(sd_rtnl_flush(rtnl) >= 0);
377         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
378         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
379         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
380
381         return EXIT_SUCCESS;
382 }