chiark / gitweb /
remove unused variable
[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, &message) >= 0);
41         assert(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
42         assert(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
43         assert(sd_rtnl_message_append_u32(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         struct in_addr addr;
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, &req);
69         if (r < 0) {
70                 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
71                 return;
72         }
73
74         addr.s_addr = htonl(INADDR_LOOPBACK);
75
76         r = sd_rtnl_message_append_in_addr(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_u32(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(((struct in_addr *)data)->s_addr == addr.s_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, &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, &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, &m1) >= 0);
195         assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &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, &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_string(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 static void test_match(void) {
234         _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
235
236         assert(sd_rtnl_open(0, &rtnl) >= 0);
237
238         assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
239         assert(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
240
241         assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
242         assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
243         assert(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
244 }
245
246 int main(void) {
247         sd_rtnl *rtnl;
248         sd_rtnl_message *m;
249         sd_rtnl_message *r;
250         void *data;
251         int if_loopback;
252         uint16_t type;
253         unsigned int mtu = 0;
254         unsigned int *mtu_reply;
255
256         test_match();
257
258         test_multiple();
259
260         test_route();
261
262         test_container();
263
264         assert(sd_rtnl_open(0, &rtnl) >= 0);
265         assert(rtnl);
266
267         if_loopback = (int) if_nametoindex("lo");
268         assert(if_loopback > 0);
269
270         test_async(if_loopback);
271
272         test_pipe(if_loopback);
273
274         test_event_loop(if_loopback);
275
276         test_link_configure(rtnl, if_loopback);
277
278         assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
279         assert(m);
280
281         assert(sd_rtnl_message_get_type(m, &type) >= 0);
282         assert(type == RTM_GETLINK);
283
284         assert(sd_rtnl_message_read(m, &type, &data) == 0);
285
286         assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
287         assert(sd_rtnl_message_get_type(r, &type) >= 0);
288         assert(type == RTM_NEWLINK);
289
290         assert(sd_rtnl_message_read(m, &type, &data) == 0);
291         assert((r = sd_rtnl_message_unref(r)) == NULL);
292
293         assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
294         assert((m = sd_rtnl_message_unref(m)) == NULL);
295         assert((r = sd_rtnl_message_unref(r)) == NULL);
296
297         assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0);
298         assert(m);
299
300         assert(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
301         assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
302
303         assert(type == IFLA_MTU);
304         assert(*mtu_reply == 0);
305
306         assert(sd_rtnl_message_read(m, &type, &data) == 0);
307
308         assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
309         while (sd_rtnl_message_read(r, &type, &data) > 0) {
310                 switch (type) {
311 //                        case IFLA_MTU:
312 //                                assert(*(unsigned int *) data == 65536);
313 //                                break;
314 //                        case IFLA_QDISC:
315 //                                assert(streq((char *) data, "noqueue"));
316 //                                break;
317                         case IFLA_IFNAME:
318                                 assert(streq((char *) data, "lo"));
319                                 break;
320                 }
321         }
322
323         assert(sd_rtnl_flush(rtnl) >= 0);
324
325         assert((m = sd_rtnl_message_unref(m)) == NULL);
326         assert((r = sd_rtnl_message_unref(r)) == NULL);
327         assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);
328
329         return EXIT_SUCCESS;
330 }