chiark / gitweb /
bus: update kdbus.h and always subscribe to KDBUS_HELLO_ATTACH_NAMES
[elogind.git] / src / libsystemd-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 <linux/rtnetlink.h>
23 #include <netinet/ether.h>
24
25 #include "util.h"
26 #include "macro.h"
27 #include "sd-rtnl.h"
28 #include "socket-util.h"
29 #include "rtnl-util.h"
30 #include "event-util.h"
31
32 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
33         _cleanup_sd_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(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &message) >= 0);
41         assert(sd_rtnl_message_append(message, IFLA_IFNAME, name) >= 0);
42         assert(sd_rtnl_message_append(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
43         assert(sd_rtnl_message_append(message, IFLA_MTU, &mtu) >= 0);
44
45         assert(sd_rtnl_message_read(message, &type, &data) >= 0);
46         assert(type == IFLA_IFNAME);
47         assert(streq(name, (char *) data));
48
49         assert(sd_rtnl_message_read(message, &type, &data) >= 0);
50         assert(type == IFLA_ADDRESS);
51         assert(streq(mac, ether_ntoa(data)));
52
53         assert(sd_rtnl_message_read(message, &type, &data) >= 0);
54         assert(type == IFLA_MTU);
55         assert(mtu == *(unsigned int *) data);
56
57         assert(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
58 }
59
60 static void test_route(void) {
61         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req;
62         uint32_t addr = htonl(INADDR_LOOPBACK);
63         uint32_t index = 2;
64         uint16_t type;
65         void *data;
66         int r;
67
68         r = sd_rtnl_message_route_new(RTM_NEWROUTE, AF_INET, 0, 0, 0,
69                                       RT_TABLE_MAIN, RT_SCOPE_UNIVERSE, RTPROT_BOOT,
70                                       RTN_UNICAST, 0, &req);
71         if (r < 0) {
72                 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
73                 return;
74         }
75
76         r = sd_rtnl_message_append(req, RTA_GATEWAY, &addr);
77         if (r < 0) {
78                 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
79                 return;
80         }
81
82         r = sd_rtnl_message_append(req, RTA_OIF, &index);
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);
90         assert(*(uint32_t *) data == addr);
91
92         assert(sd_rtnl_message_read(req, &type, &data) > 0);
93         assert(type == RTA_OIF);
94         assert(*(uint32_t *) data == index);
95 }
96
97 static 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);
105 }
106
107 static 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
135 static 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);
145         assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &m) >= 0);
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
158 static 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
168 static void test_async(int ifindex) {
169         _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
170         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
171         uint32_t serial;
172         char *ifname;
173
174         ifname = strdup("lo");
175         assert(ifname);
176
177         assert(sd_rtnl_open(0, &rtnl) >= 0);
178
179         assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &m) >= 0);
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
187 static void test_pipe(int ifindex) {
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;
191
192         assert(sd_rtnl_open(0, &rtnl) >= 0);
193
194         assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &m1) >= 0);
195         assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &m2) >= 0);
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
209 static void test_container(void) {
210         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL;
211         uint16_t type;
212         void *data;
213
214         assert(sd_rtnl_message_link_new(RTM_NEWLINK, 0, 0, 0, &m) >= 0);
215
216         assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
217         assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -EINVAL);
218         assert(sd_rtnl_message_append(m, IFLA_INFO_KIND, "kind") >= 0);
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
233 int main(void) {
234         sd_rtnl *rtnl;
235         sd_rtnl_message *m;
236         sd_rtnl_message *r;
237         void *data;
238         int if_loopback;
239         uint16_t type;
240         unsigned int mtu = 0;
241         unsigned int *mtu_reply;
242
243         test_multiple();
244
245         test_route();
246
247         test_container();
248
249         assert(sd_rtnl_open(0, &rtnl) >= 0);
250         assert(rtnl);
251
252         if_loopback = (int) if_nametoindex("lo");
253         assert(if_loopback > 0);
254
255         test_async(if_loopback);
256
257         test_pipe(if_loopback);
258
259         test_event_loop(if_loopback);
260
261         test_link_configure(rtnl, if_loopback);
262
263         assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m) >= 0);
264         assert(m);
265
266         assert(sd_rtnl_message_get_type(m, &type) >= 0);
267         assert(type == RTM_GETLINK);
268
269         assert(sd_rtnl_message_read(m, &type, &data) == 0);
270
271         assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
272         assert(sd_rtnl_message_get_type(r, &type) >= 0);
273         assert(type == RTM_NEWLINK);
274
275         assert(sd_rtnl_message_read(m, &type, &data) == 0);
276         assert((r = sd_rtnl_message_unref(r)) == NULL);
277
278         assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
279         assert((m = sd_rtnl_message_unref(m)) == NULL);
280         assert((r = sd_rtnl_message_unref(r)) == NULL);
281
282         assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m) >= 0);
283         assert(m);
284
285         assert(sd_rtnl_message_append(m, IFLA_MTU, &mtu) >= 0);
286         assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
287
288         assert(type == IFLA_MTU);
289         assert(*mtu_reply == 0);
290
291         assert(sd_rtnl_message_read(m, &type, &data) == 0);
292
293         assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
294         while (sd_rtnl_message_read(r, &type, &data) > 0) {
295                 switch (type) {
296 //                        case IFLA_MTU:
297 //                                assert(*(unsigned int *) data == 65536);
298 //                                break;
299 //                        case IFLA_QDISC:
300 //                                assert(streq((char *) data, "noqueue"));
301 //                                break;
302                         case IFLA_IFNAME:
303                                 assert(streq((char *) data, "lo"));
304                                 break;
305                 }
306         }
307
308         assert(sd_rtnl_flush(rtnl) >= 0);
309
310         assert((m = sd_rtnl_message_unref(m)) == NULL);
311         assert((r = sd_rtnl_message_unref(r)) == NULL);
312         assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);
313
314         return EXIT_SUCCESS;
315 }