chiark / gitweb /
1016bb6d4ea352c387d3b9e15c7b912768b2c6a2
[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
32 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
33         _cleanup_rtnl_message_unref_ sd_rtnl_message *message;
34         uint16_t type;
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 */
40         assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
41         assert_se(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
42         assert_se(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
43         assert_se(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
44
45         assert_se(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
46
47         assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
48         assert_se(type == IFLA_IFNAME);
49         assert_se(streq(name, (char *) data));
50
51         assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
52         assert_se(type == IFLA_ADDRESS);
53         assert_se(streq(mac, ether_ntoa(data)));
54
55         assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
56         assert_se(type == IFLA_MTU);
57         assert_se(mtu == *(unsigned int *) data);
58 }
59
60 static void test_link_get(sd_rtnl *rtnl, int ifindex) {
61         sd_rtnl_message *m;
62         sd_rtnl_message *r;
63         unsigned int mtu = 1500;
64         unsigned int *mtu_reply;
65         void *data;
66         uint16_t type;
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         /* u8 read back */
86         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
87         assert_se(type == IFLA_CARRIER);
88
89         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
90         assert_se(type == IFLA_OPERSTATE);
91
92         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
93         assert_se(type == IFLA_LINKMODE);
94
95         /* u32 read back */
96         assert_se(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
97         assert_se(type == IFLA_MTU);
98         assert_se(*mtu_reply == mtu);
99
100         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
101         assert_se(type == IFLA_GROUP);
102
103         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
104         assert_se(type == IFLA_TXQLEN);
105
106         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
107         assert_se(type == IFLA_NUM_TX_QUEUES);
108
109         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
110         assert_se(type == IFLA_NUM_RX_QUEUES);
111
112         while (sd_rtnl_message_read(r, &type, &data) > 0) {
113                 switch (type) {
114 //                        case IFLA_MTU:
115 //                                assert_se(*(unsigned int *) data == 65536);
116 //                                break;
117 //                        case IFLA_QDISC:
118 //                                assert_se(streq((char *) data, "noqueue"));
119 //                                break;
120                         case IFLA_IFNAME:
121                                 assert_se(streq((char *) data, "lo"));
122                                 break;
123                 }
124         }
125
126         assert_se(sd_rtnl_flush(rtnl) >= 0);
127         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
128
129 }
130
131 static void test_route(void) {
132         _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
133         struct in_addr addr;
134         uint32_t index = 2;
135         uint16_t type;
136         void *data;
137         int r;
138
139         r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
140         if (r < 0) {
141                 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
142                 return;
143         }
144
145         addr.s_addr = htonl(INADDR_LOOPBACK);
146
147         r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
148         if (r < 0) {
149                 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
150                 return;
151         }
152
153         r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
154         if (r < 0) {
155                 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
156                 return;
157         }
158
159         assert_se(rtnl_message_seal(NULL, req) >= 0);
160
161         assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
162         assert_se(type == RTA_GATEWAY);
163         assert_se(((struct in_addr *)data)->s_addr == addr.s_addr);
164
165         assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
166         assert_se(type == RTA_OIF);
167         assert_se(*(uint32_t *) data == index);
168 }
169
170 static void test_multiple(void) {
171         sd_rtnl *rtnl1, *rtnl2;
172
173         assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
174         assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
175
176         rtnl1 = sd_rtnl_unref(rtnl1);
177         rtnl2 = sd_rtnl_unref(rtnl2);
178 }
179
180 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
181         void *data;
182         uint16_t type;
183         char *ifname = userdata;
184
185         assert_se(rtnl);
186         assert_se(m);
187
188         log_info("got link info about %s", ifname);
189         free(ifname);
190
191         while (sd_rtnl_message_read(m, &type, &data) > 0) {
192                 switch (type) {
193 //                        case IFLA_MTU:
194 //                                assert_se(*(unsigned int *) data == 65536);
195 //                                break;
196 //                        case IFLA_QDISC:
197 //                                assert_se(streq((char *) data, "noqueue"));
198 //                                break;
199                         case IFLA_IFNAME:
200                                 assert_se(streq((char *) data, "lo"));
201                                 break;
202                 }
203         }
204
205         return 1;
206 }
207
208 static void test_event_loop(int ifindex) {
209         _cleanup_event_unref_ sd_event *event = NULL;
210         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
211         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
212         char *ifname;
213
214         ifname = strdup("lo2");
215         assert_se(ifname);
216
217         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
218         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
219
220         assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
221
222         assert_se(sd_event_default(&event) >= 0);
223
224         assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
225
226         assert_se(sd_event_run(event, 0) >= 0);
227
228         assert_se(sd_rtnl_detach_event(rtnl) >= 0);
229 }
230
231 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
232         int *counter = userdata;
233
234         (*counter) --;
235
236         log_info("got reply, %d left in pipe", *counter);
237
238         return sd_rtnl_message_get_errno(m);
239 }
240
241 static void test_async(int ifindex) {
242         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
243         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
244         uint32_t serial;
245         char *ifname;
246
247         ifname = strdup("lo");
248         assert_se(ifname);
249
250         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
251
252         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
253
254         assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
255
256         assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
257         assert_se(sd_rtnl_process(rtnl, &r) >= 0);
258 }
259
260 static void test_pipe(int ifindex) {
261         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
262         _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
263         int counter = 0;
264
265         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
266
267         assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
268         assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
269
270         counter ++;
271         assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
272
273         counter ++;
274         assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
275
276         while (counter > 0) {
277                 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
278                 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
279         }
280 }
281
282 static void test_container(void) {
283         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
284         uint16_t type;
285         void *data;
286
287         assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
288
289         assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
290         assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
291         assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
292         assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
293         assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
294         assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
295         assert_se(sd_rtnl_message_close_container(m) >= 0);
296         assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
297         assert_se(sd_rtnl_message_close_container(m) >= 0);
298         assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
299
300         assert_se(rtnl_message_seal(NULL, m) >= 0);
301
302         assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
303         assert_se(type == IFLA_LINKINFO);
304         assert_se(data == NULL);
305 /*
306         assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
307         assert_se(type == IFLA_INFO_KIND);
308         assert_se(streq("kind", (char *)data));
309         assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
310         assert_se(type == IFLA_INFO_DATA);
311         assert_se(data == NULL);
312         assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
313         assert_se(type == IFLA_VLAN_ID);
314         assert_se(*(uint16_t *)data == 100);
315         assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
316         assert_se(sd_rtnl_message_exit_container(m) >= 0);
317         assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
318         assert_se(type == IFLA_INFO_KIND);
319         assert_se(streq("kind", (char *)data));
320         assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
321         assert_se(sd_rtnl_message_exit_container(m) >= 0);
322 */
323         assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
324 }
325
326 static void test_match(void) {
327         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
328
329         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
330
331         assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
332         assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
333
334         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
335         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
336         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
337 }
338
339 int main(void) {
340         sd_rtnl *rtnl;
341         sd_rtnl_message *m;
342         sd_rtnl_message *r;
343         void *data;
344         int if_loopback;
345         uint16_t type;
346
347         test_match();
348
349         test_multiple();
350
351         test_route();
352
353         test_container();
354
355         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
356         assert_se(rtnl);
357
358         if_loopback = (int) if_nametoindex("lo");
359         assert_se(if_loopback > 0);
360
361         test_async(if_loopback);
362
363         test_pipe(if_loopback);
364
365         test_event_loop(if_loopback);
366
367         test_link_configure(rtnl, if_loopback);
368
369         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
370         assert_se(m);
371
372         assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
373         assert_se(type == RTM_GETLINK);
374
375         assert_se(sd_rtnl_message_read(m, &type, &data) == -EPERM);
376
377         assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
378         assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
379         assert_se(type == RTM_NEWLINK);
380
381         assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
382         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
383
384         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
385         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
386         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
387
388         test_link_get(rtnl, if_loopback);
389
390         assert_se(sd_rtnl_flush(rtnl) >= 0);
391         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
392         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
393         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
394
395         return EXIT_SUCCESS;
396 }