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