chiark / gitweb /
sd-rtnl: fix self-reference leaks
[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         uint16_t type;
36         const char *mac = "98:fe:94:3f:c6:18", *name = "test";
37         unsigned int mtu = 1450;
38         void *data;
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
48         assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
49         assert_se(type == IFLA_IFNAME);
50         assert_se(streq(name, (char *) data));
51
52         assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
53         assert_se(type == IFLA_ADDRESS);
54         assert_se(streq(mac, ether_ntoa(data)));
55
56         assert_se(sd_rtnl_message_read(message, &type, &data) > 0);
57         assert_se(type == IFLA_MTU);
58         assert_se(mtu == *(unsigned int *) data);
59 }
60
61 static void test_link_get(sd_rtnl *rtnl, int ifindex) {
62         sd_rtnl_message *m;
63         sd_rtnl_message *r;
64         unsigned int mtu = 1500;
65         unsigned int *mtu_reply;
66         void *data;
67         char *str_data;
68         uint16_t type;
69         uint8_t u8_data;
70         uint32_t u32_data;
71         struct ether_addr eth_data;
72
73         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
74         assert_se(m);
75
76         /* u8 test cases  */
77         assert_se(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
78         assert_se(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
79         assert_se(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
80
81         /* u32 test cases */
82         assert_se(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
83         assert_se(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0);
84         assert_se(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
85         assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
86         assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
87
88         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
89
90         /* u8 read back */
91         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
92         assert_se(type == IFLA_CARRIER);
93
94         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
95         assert_se(type == IFLA_OPERSTATE);
96
97         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
98         assert_se(type == IFLA_LINKMODE);
99
100         /* u32 read back */
101         assert_se(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
102         assert_se(type == IFLA_MTU);
103         assert_se(*mtu_reply == mtu);
104
105         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
106         assert_se(type == IFLA_GROUP);
107
108         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
109         assert_se(type == IFLA_TXQLEN);
110
111         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
112         assert_se(type == IFLA_NUM_TX_QUEUES);
113
114         assert_se(sd_rtnl_message_read(m, &type, &data) == 1);
115         assert_se(type == IFLA_NUM_RX_QUEUES);
116
117         while (sd_rtnl_message_read(r, &type, &data) > 0) {
118                 switch (type) {
119 //                        case IFLA_MTU:
120 //                                assert_se(*(unsigned int *) data == 65536);
121 //                                break;
122 //                        case IFLA_QDISC:
123 //                                assert_se(streq((char *) data, "noqueue"));
124 //                                break;
125                         case IFLA_IFNAME:
126                                 assert_se(streq((char *) data, "lo"));
127                                 break;
128                 }
129         }
130
131         assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
132
133         assert_se(sd_rtnl_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0);
134         assert_se(sd_rtnl_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0);
135         assert_se(sd_rtnl_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0);
136
137         assert_se(sd_rtnl_message_read_u32(r, IFLA_MTU, &u32_data) == 0);
138         assert_se(sd_rtnl_message_read_u32(r, IFLA_GROUP, &u32_data) == 0);
139         assert_se(sd_rtnl_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0);
140         assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0);
141         assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0);
142
143         assert_se(sd_rtnl_message_read_ether_addr(r, IFLA_ADDRESS, &eth_data) == 0);
144
145         assert_se(sd_rtnl_flush(rtnl) >= 0);
146         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
147         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
148 }
149
150
151 static void test_address_get(sd_rtnl *rtnl, int ifindex) {
152         sd_rtnl_message *m;
153         sd_rtnl_message *r;
154         struct in_addr in_data;
155
156         assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
157         assert_se(m);
158
159         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
160
161         assert_se(sd_rtnl_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0);
162         assert_se(sd_rtnl_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0);
163         assert_se(sd_rtnl_message_read_in_addr(r, IFA_LABEL, &in_data) == 0);
164         assert_se(sd_rtnl_message_read_in_addr(r, IFA_CACHEINFO, &in_data) == 0);
165
166         assert_se(sd_rtnl_flush(rtnl) >= 0);
167         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
168         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
169
170 }
171
172 static void test_route(void) {
173         _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
174         struct in_addr addr;
175         uint32_t index = 2;
176         uint16_t type;
177         void *data;
178         uint32_t u32_data;
179         int r;
180         struct rtmsg *rtm;
181
182         r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET);
183         if (r < 0) {
184                 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
185                 return;
186         }
187
188         addr.s_addr = htonl(INADDR_LOOPBACK);
189
190         r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
191         if (r < 0) {
192                 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
193                 return;
194         }
195
196         r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
197         if (r < 0) {
198                 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
199                 return;
200         }
201
202         assert_se(rtnl_message_seal(NULL, req) >= 0);
203
204         assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
205         assert_se(type == RTA_GATEWAY);
206         assert_se(((struct in_addr *)data)->s_addr == addr.s_addr);
207
208         assert_se(sd_rtnl_message_read(req, &type, &data) > 0);
209         assert_se(type == RTA_OIF);
210         assert_se(*(uint32_t *) data == index);
211
212         rtm = NLMSG_DATA(req->hdr);
213         r = rtnl_message_parse(req,
214                                &req->rta_offset_tb,
215                                &req->rta_tb_size,
216                                RTA_MAX,
217                                RTM_RTA(rtm),
218                                RTM_PAYLOAD(req->hdr));
219
220         assert_se(sd_rtnl_message_read_u32(req, RTA_GATEWAY, &u32_data) == 0);
221         assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) == 0);
222
223         assert_se((req = sd_rtnl_message_unref(req)) == NULL);
224 }
225
226 static void test_multiple(void) {
227         sd_rtnl *rtnl1, *rtnl2;
228
229         assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
230         assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
231
232         rtnl1 = sd_rtnl_unref(rtnl1);
233         rtnl2 = sd_rtnl_unref(rtnl2);
234 }
235
236 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
237         void *data;
238         uint16_t type;
239         char *ifname = userdata;
240
241         assert_se(rtnl);
242         assert_se(m);
243
244         log_info("got link info about %s", ifname);
245         free(ifname);
246
247         while (sd_rtnl_message_read(m, &type, &data) > 0) {
248                 switch (type) {
249 //                        case IFLA_MTU:
250 //                                assert_se(*(unsigned int *) data == 65536);
251 //                                break;
252 //                        case IFLA_QDISC:
253 //                                assert_se(streq((char *) data, "noqueue"));
254 //                                break;
255                         case IFLA_IFNAME:
256                                 assert_se(streq((char *) data, "lo"));
257                                 break;
258                 }
259         }
260
261         return 1;
262 }
263
264 static void test_event_loop(int ifindex) {
265         _cleanup_event_unref_ sd_event *event = NULL;
266         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
267         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
268         char *ifname;
269
270         ifname = strdup("lo2");
271         assert_se(ifname);
272
273         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
274         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
275
276         assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
277
278         assert_se(sd_event_default(&event) >= 0);
279
280         assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
281
282         assert_se(sd_event_run(event, 0) >= 0);
283
284         assert_se(sd_rtnl_detach_event(rtnl) >= 0);
285
286         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
287 }
288
289 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
290         int *counter = userdata;
291
292         (*counter) --;
293
294         log_info("got reply, %d left in pipe", *counter);
295
296         return sd_rtnl_message_get_errno(m);
297 }
298
299 static void test_async(int ifindex) {
300         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
301         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
302         uint32_t serial;
303         char *ifname;
304
305         ifname = strdup("lo");
306         assert_se(ifname);
307
308         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
309
310         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
311
312         assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
313
314         assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
315         assert_se(sd_rtnl_process(rtnl, &r) >= 0);
316
317         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
318 }
319
320 static void test_pipe(int ifindex) {
321         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
322         _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
323         int counter = 0;
324
325         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
326
327         assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
328         assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
329
330         counter ++;
331         assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
332
333         counter ++;
334         assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
335
336         while (counter > 0) {
337                 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
338                 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
339         }
340
341         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
342 }
343
344 static void test_container(void) {
345         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
346         uint16_t type;
347         uint32_t u32_data;
348         void *data;
349         int r;
350         struct ifinfomsg *ifi;
351
352         assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
353
354         assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
355         assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP);
356         assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
357         assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0);
358         assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP);
359         assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
360         assert_se(sd_rtnl_message_close_container(m) >= 0);
361         assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0);
362         assert_se(sd_rtnl_message_close_container(m) >= 0);
363         assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
364
365         assert_se(rtnl_message_seal(NULL, m) >= 0);
366
367         assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
368         assert_se(type == IFLA_LINKINFO);
369         assert_se(data == NULL);
370 /*
371         assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
372         assert_se(type == IFLA_INFO_KIND);
373         assert_se(streq("kind", (char *)data));
374         assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
375         assert_se(type == IFLA_INFO_DATA);
376         assert_se(data == NULL);
377         assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
378         assert_se(type == IFLA_VLAN_ID);
379         assert_se(*(uint16_t *)data == 100);
380         assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
381         assert_se(sd_rtnl_message_exit_container(m) >= 0);
382         assert_se(sd_rtnl_message_read(m, &type, &data) >= 0);
383         assert_se(type == IFLA_INFO_KIND);
384         assert_se(streq("kind", (char *)data));
385         assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
386         assert_se(sd_rtnl_message_exit_container(m) >= 0);
387 */
388
389         ifi = NLMSG_DATA(m->hdr);
390         r = rtnl_message_parse(m,
391                                &m->rta_offset_tb,
392                                &m->rta_tb_size,
393                                IFLA_MAX,
394                                IFLA_RTA(ifi),
395                                IFLA_PAYLOAD(m->hdr));
396         if(r < 0)
397                 return;
398
399         assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) == 0);
400
401         assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
402 }
403
404 static void test_match(void) {
405         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
406
407         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
408
409         assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
410         assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
411
412         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
413         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
414         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
415
416         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
417 }
418
419 int main(void) {
420         sd_rtnl *rtnl;
421         sd_rtnl_message *m;
422         sd_rtnl_message *r;
423         void *data;
424         int if_loopback;
425         uint16_t type;
426
427         test_match();
428
429         test_multiple();
430
431         test_route();
432
433         test_container();
434
435         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
436         assert_se(rtnl);
437
438         if_loopback = (int) if_nametoindex("lo");
439         assert_se(if_loopback > 0);
440
441         test_async(if_loopback);
442
443         test_pipe(if_loopback);
444
445         test_event_loop(if_loopback);
446
447         test_link_configure(rtnl, if_loopback);
448
449         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
450         assert_se(m);
451
452         assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
453         assert_se(type == RTM_GETLINK);
454
455         assert_se(sd_rtnl_message_read(m, &type, &data) == -EPERM);
456
457         assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
458         assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
459         assert_se(type == RTM_NEWLINK);
460
461         assert_se(sd_rtnl_message_read(m, &type, &data) == 0);
462         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
463
464         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
465         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
466         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
467
468         test_link_get(rtnl, if_loopback);
469         test_address_get(rtnl, if_loopback);
470
471         assert_se(sd_rtnl_flush(rtnl) >= 0);
472         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
473         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
474         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
475
476         return EXIT_SUCCESS;
477 }