chiark / gitweb /
47cce64816aa438e1880a7937ca61843d3fd0685
[elogind.git] / src / libelogind / 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 #include <net/if.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 #include "missing.h"
32
33 static void test_message_link_bridge(sd_rtnl *rtnl) {
34         _cleanup_rtnl_message_unref_ sd_rtnl_message *message = NULL;
35         uint32_t cost;
36
37         assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0);
38         assert_se(sd_rtnl_message_link_set_family(message, PF_BRIDGE) >= 0);
39         assert_se(sd_rtnl_message_open_container(message, IFLA_PROTINFO) >= 0);
40         assert_se(sd_rtnl_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0);
41         assert_se(sd_rtnl_message_close_container(message) >= 0);
42
43         assert_se(sd_rtnl_message_rewind(message) >= 0);
44
45         assert_se(sd_rtnl_message_enter_container(message, IFLA_PROTINFO) >= 0);
46         assert_se(sd_rtnl_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0);
47         assert_se(cost == 10);
48         assert_se(sd_rtnl_message_exit_container(message) >= 0);
49 }
50
51 static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
52         _cleanup_rtnl_message_unref_ sd_rtnl_message *message = NULL;
53         const char *mac = "98:fe:94:3f:c6:18", *name = "test";
54         char buffer[ETHER_ADDR_TO_STRING_MAX];
55         unsigned int mtu = 1450, mtu_out;
56         const char *name_out;
57         struct ether_addr mac_out;
58
59         /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
60         assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
61         assert_se(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0);
62         assert_se(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
63         assert_se(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0);
64
65         assert_se(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
66         assert_se(sd_rtnl_message_rewind(message) >= 0);
67
68         assert_se(sd_rtnl_message_read_string(message, IFLA_IFNAME, &name_out) >= 0);
69         assert_se(streq(name, name_out));
70
71         assert_se(sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0);
72         assert_se(streq(mac, ether_addr_to_string(&mac_out, buffer)));
73
74         assert_se(sd_rtnl_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0);
75         assert_se(mtu == mtu_out);
76 }
77
78 static void test_link_get(sd_rtnl *rtnl, int ifindex) {
79         sd_rtnl_message *m;
80         sd_rtnl_message *r;
81         unsigned int mtu = 1500;
82         const char *str_data;
83         uint8_t u8_data;
84         uint32_t u32_data;
85         struct ether_addr eth_data;
86
87         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
88         assert_se(m);
89
90         /* u8 test cases  */
91         assert_se(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0);
92         assert_se(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0);
93         assert_se(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0);
94
95         /* u32 test cases */
96         assert_se(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0);
97         assert_se(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0);
98         assert_se(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0);
99         assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0);
100         assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0);
101
102         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
103
104         assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
105
106         assert_se(sd_rtnl_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0);
107         assert_se(sd_rtnl_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0);
108         assert_se(sd_rtnl_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0);
109
110         assert_se(sd_rtnl_message_read_u32(r, IFLA_MTU, &u32_data) == 0);
111         assert_se(sd_rtnl_message_read_u32(r, IFLA_GROUP, &u32_data) == 0);
112         assert_se(sd_rtnl_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0);
113         assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0);
114         assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0);
115
116         assert_se(sd_rtnl_message_read_ether_addr(r, IFLA_ADDRESS, &eth_data) == 0);
117
118         assert_se(sd_rtnl_flush(rtnl) >= 0);
119         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
120         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
121 }
122
123
124 static void test_address_get(sd_rtnl *rtnl, int ifindex) {
125         sd_rtnl_message *m;
126         sd_rtnl_message *r;
127         struct in_addr in_data;
128         struct ifa_cacheinfo cache;
129         const char *label;
130
131         assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
132         assert_se(m);
133
134         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1);
135
136         assert_se(sd_rtnl_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0);
137         assert_se(sd_rtnl_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0);
138         assert_se(sd_rtnl_message_read_string(r, IFA_LABEL, &label) == 0);
139         assert_se(sd_rtnl_message_read_cache_info(r, IFA_CACHEINFO, &cache) == 0);
140
141         assert_se(sd_rtnl_flush(rtnl) >= 0);
142         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
143         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
144
145 }
146
147 static void test_route(void) {
148         _cleanup_rtnl_message_unref_ sd_rtnl_message *req;
149         struct in_addr addr, addr_data;
150         uint32_t index = 2, u32_data;
151         int r;
152
153         r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC);
154         if (r < 0) {
155                 log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");
156                 return;
157         }
158
159         addr.s_addr = htonl(INADDR_LOOPBACK);
160
161         r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr);
162         if (r < 0) {
163                 log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
164                 return;
165         }
166
167         r = sd_rtnl_message_append_u32(req, RTA_OIF, index);
168         if (r < 0) {
169                 log_error_errno(r, "Could not append RTA_OIF attribute: %m");
170                 return;
171         }
172
173         assert_se(sd_rtnl_message_rewind(req) >= 0);
174
175         assert_se(sd_rtnl_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
176         assert_se(addr_data.s_addr == addr.s_addr);
177
178         assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
179         assert_se(u32_data == index);
180
181         assert_se((req = sd_rtnl_message_unref(req)) == NULL);
182 }
183
184 static void test_multiple(void) {
185         sd_rtnl *rtnl1, *rtnl2;
186
187         assert_se(sd_rtnl_open(&rtnl1, 0) >= 0);
188         assert_se(sd_rtnl_open(&rtnl2, 0) >= 0);
189
190         rtnl1 = sd_rtnl_unref(rtnl1);
191         rtnl2 = sd_rtnl_unref(rtnl2);
192 }
193
194 static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
195         char *ifname = userdata;
196         const char *data;
197
198         assert_se(rtnl);
199         assert_se(m);
200
201         log_info("got link info about %s", ifname);
202         free(ifname);
203
204         assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &data) >= 0);
205         assert_se(streq(data, "lo"));
206
207         return 1;
208 }
209
210 static void test_event_loop(int ifindex) {
211         _cleanup_event_unref_ sd_event *event = NULL;
212         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
213         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
214         char *ifname;
215
216         ifname = strdup("lo2");
217         assert_se(ifname);
218
219         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
220         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
221
222         assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, NULL) >= 0);
223
224         assert_se(sd_event_default(&event) >= 0);
225
226         assert_se(sd_rtnl_attach_event(rtnl, event, 0) >= 0);
227
228         assert_se(sd_event_run(event, 0) >= 0);
229
230         assert_se(sd_rtnl_detach_event(rtnl) >= 0);
231
232         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
233 }
234
235 static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
236         int *counter = userdata;
237         int r;
238
239         (*counter) --;
240
241         r = sd_rtnl_message_get_errno(m);
242
243         log_info_errno(r, "%d left in pipe. got reply: %m", *counter);
244
245         assert_se(r >= 0);
246
247         return 1;
248 }
249
250 static void test_async(int ifindex) {
251         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
252         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
253         uint32_t serial;
254         char *ifname;
255
256         ifname = strdup("lo");
257         assert_se(ifname);
258
259         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
260
261         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
262
263         assert_se(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
264
265         assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
266         assert_se(sd_rtnl_process(rtnl, &r) >= 0);
267
268         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
269 }
270
271 static void test_pipe(int ifindex) {
272         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
273         _cleanup_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
274         int counter = 0;
275
276         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
277
278         assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
279         assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
280
281         counter ++;
282         assert_se(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
283
284         counter ++;
285         assert_se(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
286
287         while (counter > 0) {
288                 assert_se(sd_rtnl_wait(rtnl, 0) >= 0);
289                 assert_se(sd_rtnl_process(rtnl, NULL) >= 0);
290         }
291
292         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
293 }
294
295 static void test_container(void) {
296         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
297         uint16_t u16_data;
298         uint32_t u32_data;
299         const char *string_data;
300
301         assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0);
302
303         assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0);
304         assert_se(sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0);
305         assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
306         assert_se(sd_rtnl_message_close_container(m) >= 0);
307         assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
308         assert_se(sd_rtnl_message_close_container(m) >= 0);
309         assert_se(sd_rtnl_message_close_container(m) == -EINVAL);
310
311         assert_se(sd_rtnl_message_rewind(m) >= 0);
312
313         assert_se(sd_rtnl_message_enter_container(m, IFLA_LINKINFO) >= 0);
314         assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
315         assert_se(streq("vlan", string_data));
316
317         assert_se(sd_rtnl_message_enter_container(m, IFLA_INFO_DATA) >= 0);
318         assert_se(sd_rtnl_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0);
319         assert_se(sd_rtnl_message_exit_container(m) >= 0);
320
321         assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
322         assert_se(streq("vlan", string_data));
323         assert_se(sd_rtnl_message_exit_container(m) >= 0);
324
325         assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0);
326
327         assert_se(sd_rtnl_message_exit_container(m) == -EINVAL);
328 }
329
330 static void test_match(void) {
331         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
332
333         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
334
335         assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
336         assert_se(sd_rtnl_add_match(rtnl, RTM_NEWLINK, &link_handler, NULL) >= 0);
337
338         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
339         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 1);
340         assert_se(sd_rtnl_remove_match(rtnl, RTM_NEWLINK, &link_handler, NULL) == 0);
341
342         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
343 }
344
345 static void test_get_addresses(sd_rtnl *rtnl) {
346         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
347         sd_rtnl_message *m;
348
349         assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0);
350
351         assert_se(sd_rtnl_call(rtnl, req, 0, &reply) >= 0);
352
353         for (m = reply; m; m = sd_rtnl_message_next(m)) {
354                 uint16_t type;
355                 unsigned char scope, flags;
356                 int family, ifindex;
357
358                 assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
359                 assert_se(type == RTM_NEWADDR);
360
361                 assert_se(sd_rtnl_message_addr_get_ifindex(m, &ifindex) >= 0);
362                 assert_se(sd_rtnl_message_addr_get_family(m, &family) >= 0);
363                 assert_se(sd_rtnl_message_addr_get_scope(m, &scope) >= 0);
364                 assert_se(sd_rtnl_message_addr_get_flags(m, &flags) >= 0);
365
366                 assert_se(ifindex > 0);
367                 assert_se(family == AF_INET || family == AF_INET6);
368
369                 log_info("got IPv%u address on ifindex %i", family == AF_INET ? 4: 6, ifindex);
370         }
371 }
372
373 static void test_message(void) {
374         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
375
376         assert_se(rtnl_message_new_synthetic_error(-ETIMEDOUT, 1, &m) >= 0);
377         assert_se(sd_rtnl_message_get_errno(m) == -ETIMEDOUT);
378 }
379
380 int main(void) {
381         sd_rtnl *rtnl;
382         sd_rtnl_message *m;
383         sd_rtnl_message *r;
384         const char *string_data;
385         int if_loopback;
386         uint16_t type;
387
388         test_message();
389
390         test_match();
391
392         test_multiple();
393
394         test_route();
395
396         test_container();
397
398         assert_se(sd_rtnl_open(&rtnl, 0) >= 0);
399         assert_se(rtnl);
400
401         if_loopback = (int) if_nametoindex("lo");
402         assert_se(if_loopback > 0);
403
404         test_async(if_loopback);
405
406         test_pipe(if_loopback);
407
408         test_event_loop(if_loopback);
409
410         test_link_configure(rtnl, if_loopback);
411
412         test_get_addresses(rtnl);
413
414         test_message_link_bridge(rtnl);
415
416         assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
417         assert_se(m);
418
419         assert_se(sd_rtnl_message_get_type(m, &type) >= 0);
420         assert_se(type == RTM_GETLINK);
421
422         assert_se(sd_rtnl_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
423
424         assert_se(sd_rtnl_call(rtnl, m, 0, &r) == 1);
425         assert_se(sd_rtnl_message_get_type(r, &type) >= 0);
426         assert_se(type == RTM_NEWLINK);
427
428         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
429
430         assert_se(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
431         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
432         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
433
434         test_link_get(rtnl, if_loopback);
435         test_address_get(rtnl, if_loopback);
436
437         assert_se(sd_rtnl_flush(rtnl) >= 0);
438         assert_se((m = sd_rtnl_message_unref(m)) == NULL);
439         assert_se((r = sd_rtnl_message_unref(r)) == NULL);
440         assert_se((rtnl = sd_rtnl_unref(rtnl)) == NULL);
441
442         return EXIT_SUCCESS;
443 }