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