chiark / gitweb /
44369628f4d904b991325af6ccf0de0a92ede872
[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         char *label;
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);
118         assert_se(sd_rtnl_message_read_string(r, IFA_LABEL, &label) == 0);
119
120         assert_se(sd_rtnl_flush(rtnl) >= 0);
121         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
122         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
123
124 }
125
126 static void test_route(void) {
127         _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
128         struct in_addr addr, addr_data;
129         uint32_t index = 2, u32_data;
130         int r;
131
132         r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
133         if (r < 0) {
134                 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
135                 return;
136         }
137
138         addr.s_addr = htonl(INADDR_LOOPBACK);
139
140         r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
141         if (r < 0) {
142                 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
143                 return;
144         }
145
146         r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
147         if (r < 0) {
148                 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
149                 return;
150         }
151
152         assert_se(sd_rtnl_message_rewind(req) >= 0);
153
154         assert_se(sd_rtnl_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
155         assert_se(addr_data.s_addr == addr.s_addr);
156
157         assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
158         assert_se(u32_data == index);
159
160         assert_se((req = sd_rtnl_message_unref(req)) == NULL);
161 }
162
163 static void test_multiple(void) {
164         sd_rtnl *rtnl1, *rtnl2;
165
166         assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
167         assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
168
169         rtnl1 = sd_rtnl_unref(rtnl1);
170         rtnl2 = sd_rtnl_unref(rtnl2);
171 }
172
173 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
174         char *ifname = userdata, *data;
175
176         assert_se(rtnl);
177         assert_se(m);
178
179         log_info("got link info about %s", ifname);
180         free(ifname);
181
182         assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &data) >= 0);
183         assert_se(streq(data, "lo"));
184
185         return 1;
186 }
187
188 static void test_event_loop(int ifindex) {
189         _cleanup_event_unref_ sd_event *event = NULL;
190         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
191         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
192         char *ifname;
193
194         ifname = strdup("lo2");
195         assert_se(ifname);
196
197         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
198         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
199
200         assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
201
202         assert_se(sd_event_default(&event) >= 0);
203
204         assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
205
206         assert_se(sd_event_run(event, 0) >= 0);
207
208         assert_se(sd_rtnl_detach_event(rtnl) >= 0);
209
210         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
211 }
212
213 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
214         int *counter = userdata;
215         int r;
216
217         (*counter) --;
218
219         r = sd_rtnl_message_get_errno(m);
220
221         log_info("%d left in pipe. got reply: %s", *counter, strerror(-r));
222
223         assert_se(r >= 0);
224
225         return 1;
226 }
227
228 static void test_async(int ifindex) {
229         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
230         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
231         uint32_t serial;
232         char *ifname;
233
234         ifname = strdup("lo");
235         assert_se(ifname);
236
237         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
238
239         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
240
241         assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
242
243         assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
244         assert_se(sd_rtnl_process(rtnl, &r) >= 0);
245
246         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
247 }
248
249 static void test_pipe(int ifindex) {
250         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
251         _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
252         int counter = 0;
253
254         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
255
256         assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
257         assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
258
259         counter ++;
260         assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
261
262         counter ++;
263         assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
264
265         while (counter > 0) {
266                 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
267                 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
268         }
269
270         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
271 }
272
273 static void test_container(void) {
274         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
275         uint16_t u16_data;
276         uint32_t u32_data;
277         char *string_data;
278
279         assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
280
281         assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
282         assert_se(sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0);
283         assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
284         assert_se(sd_rtnl_message_close_container(m) >= 0);
285         assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
286         assert_se(sd_rtnl_message_close_container(m) >= 0);
287         assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
288
289         assert_se(sd_rtnl_message_rewind(m) >= 0);
290
291         assert_se(sd_rtnl_message_enter_container(m, IFLA_LINKINFO) >= 0);
292         assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
293         assert_se(streq("vlan", string_data));
294
295         assert_se(sd_rtnl_message_enter_container(m, IFLA_INFO_DATA) >= 0);
296         assert_se(sd_rtnl_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0);
297         assert_se(sd_rtnl_message_exit_container(m) >= 0);
298
299         assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
300         assert_se(streq("vlan", string_data));
301         assert_se(sd_rtnl_message_exit_container(m) >= 0);
302
303         assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0);
304
305         assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
306 }
307
308 static void test_match(void) {
309         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
310
311         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
312
313         assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
314         assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
315
316         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
317         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
318         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
319
320         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
321 }
322
323 int main(void) {
324         sd_rtnl *rtnl;
325         sd_rtnl_message *m;
326         sd_rtnl_message *r;
327         char *string_data;
328         int if_loopback;
329         uint16_t type;
330
331         test_match();
332
333         test_multiple();
334
335         test_route();
336
337         test_container();
338
339         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
340         assert_se(rtnl);
341
342         if_loopback = (int) if_nametoindex("lo");
343         assert_se(if_loopback > 0);
344
345         test_async(if_loopback);
346
347         test_pipe(if_loopback);
348
349         test_event_loop(if_loopback);
350
351         test_link_configure(rtnl, if_loopback);
352
353         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
354         assert_se(m);
355
356         assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
357         assert_se(type == RTM_GETLINK);
358
359         assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
360
361         assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
362         assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
363         assert_se(type == RTM_NEWLINK);
364
365         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
366
367         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
368         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
369         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
370
371         test_link_get(rtnl, if_loopback);
372         test_address_get(rtnl, if_loopback);
373
374         assert_se(sd_rtnl_flush(rtnl) >= 0);
375         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
376         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
377         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
378
379         return EXIT_SUCCESS;
380 }