]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-rtnl/test-rtnl.c
rtnl: add call_async and call_async_cancel
[thirdparty/systemd.git] / src / libsystemd-rtnl / test-rtnl.c
CommitLineData
65f568bb
TG
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
a33dece5 22#include <linux/rtnetlink.h>
65f568bb
TG
23#include <netinet/ether.h>
24
25#include "util.h"
26#include "macro.h"
27#include "sd-rtnl.h"
28#include "socket-util.h"
a33dece5 29#include "rtnl-util.h"
65f568bb
TG
30
31static void test_link_configure(sd_rtnl *rtnl, int ifindex) {
32 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *message;
dabfa9d1 33 uint16_t type;
65f568bb
TG
34 const char *mac = "98:fe:94:3f:c6:18", *name = "test";
35 unsigned int mtu = 1450;
36 void *data;
37
38 /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
39 assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, 0, 0, &message) >= 0);
40 assert(sd_rtnl_message_append(message, IFLA_IFNAME, name) >= 0);
41 assert(sd_rtnl_message_append(message, IFLA_ADDRESS, ether_aton(mac)) >= 0);
42 assert(sd_rtnl_message_append(message, IFLA_MTU, &mtu) >= 0);
43
44 assert(sd_rtnl_message_read(message, &type, &data) >= 0);
45 assert(type == IFLA_IFNAME);
46 assert(streq(name, (char *) data));
47
48 assert(sd_rtnl_message_read(message, &type, &data) >= 0);
49 assert(type == IFLA_ADDRESS);
50 assert(streq(mac, ether_ntoa(data)));
51
52 assert(sd_rtnl_message_read(message, &type, &data) >= 0);
53 assert(type == IFLA_MTU);
54 assert(mtu == *(unsigned int *) data);
55
4555ec72 56 assert(sd_rtnl_call(rtnl, message, 0, NULL) == 1);
d4bbdb77
TG
57}
58
03d7e632
TG
59static void test_route(void) {
60 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req;
61 uint32_t addr = htonl(INADDR_LOOPBACK);
62 uint32_t index = 2;
63 uint16_t type;
64 void *data;
65 int r;
66
67 r = sd_rtnl_message_route_new(RTM_NEWROUTE, AF_INET, 0, 0, 0,
68 RT_TABLE_MAIN, RT_SCOPE_UNIVERSE, RTPROT_BOOT,
69 RTN_UNICAST, 0, &req);
70 if (r < 0) {
71 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
72 return;
73 }
74
75 r = sd_rtnl_message_append(req, RTA_GATEWAY, &addr);
76 if (r < 0) {
77 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
78 return;
79 }
80
81 r = sd_rtnl_message_append(req, RTA_OIF, &index);
82 if (r < 0) {
83 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
84 return;
85 }
86
87 assert(sd_rtnl_message_read(req, &type, &data) > 0);
88 assert(type == RTA_GATEWAY);
89 assert(*(uint32_t *) data == addr);
90
91 assert(sd_rtnl_message_read(req, &type, &data) > 0);
92 assert(type == RTA_OIF);
93 assert(*(uint32_t *) data == index);
94}
95
d4bbdb77
TG
96static void test_multiple(void) {
97 sd_rtnl *rtnl1, *rtnl2;
98
99 assert(sd_rtnl_open(0, &rtnl1) >= 0);
100 assert(sd_rtnl_open(0, &rtnl2) >= 0);
101
102 rtnl1 = sd_rtnl_unref(rtnl1);
103 rtnl2 = sd_rtnl_unref(rtnl2);
65f568bb
TG
104}
105
e16bcf98
TG
106static int link_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
107 void *data;
108 uint16_t type;
109 char *ifname = userdata;
110
111 assert(rtnl);
112 assert(m);
113
114 log_info("got link info about %s", ifname);
115 free(ifname);
116
117 while (sd_rtnl_message_read(m, &type, &data) > 0) {
118 switch (type) {
119// case IFLA_MTU:
120// assert(*(unsigned int *) data == 65536);
121// break;
122// case IFLA_QDISC:
123// assert(streq((char *) data, "noqueue"));
124// break;
125 case IFLA_IFNAME:
126 assert(streq((char *) data, "lo"));
127 break;
128 }
129 }
130
131 return 1;
132}
133
134static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
135 int *counter = userdata;
136
137 (*counter) --;
138
139 log_info("got reply, %d left in pipe", *counter);
140
141 return sd_rtnl_message_get_errno(m);
142}
143
144static void test_async(void) {
145 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
146 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m = NULL, *r = NULL;
147 int if_loopback;
148 uint32_t serial;
149 char *ifname;
150
151 ifname = strdup("lo");
152
153 assert(sd_rtnl_open(0, &rtnl) >= 0);
154
155 if_loopback = (int) if_nametoindex("lo");
156 assert(if_loopback > 0);
157
158 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m) >= 0);
159
160 assert(sd_rtnl_call_async(rtnl, m, &link_handler, ifname, 0, &serial) >= 0);
161
162 assert(sd_rtnl_wait(rtnl, 0) >= 0);
163 assert(sd_rtnl_process(rtnl, &r) >= 0);
164}
165
166static void test_pipe(void) {
167 _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL;
168 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *m1 = NULL, *m2 = NULL;
169 int counter = 0;
170 int if_loopback;
171
172 assert(sd_rtnl_open(0, &rtnl) >= 0);
173
174 if_loopback = (int) if_nametoindex("lo");
175 assert(if_loopback > 0);
176
177 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m1) >= 0);
178 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m2) >= 0);
179
180 counter ++;
181 assert(sd_rtnl_call_async(rtnl, m1, &pipe_handler, &counter, 0, NULL) >= 0);
182
183 counter ++;
184 assert(sd_rtnl_call_async(rtnl, m2, &pipe_handler, &counter, 0, NULL) >= 0);
185
186 while (counter > 0) {
187 assert(sd_rtnl_wait(rtnl, 0) >= 0);
188 assert(sd_rtnl_process(rtnl, NULL) >= 0);
189 }
190}
191
65f568bb
TG
192int main(void) {
193 sd_rtnl *rtnl;
194 sd_rtnl_message *m;
195 sd_rtnl_message *r;
196 void *data;
197 int if_loopback;
dabfa9d1 198 uint16_t type;
65f568bb
TG
199 unsigned int mtu = 0;
200 unsigned int *mtu_reply;
201
d4bbdb77
TG
202 test_multiple();
203
03d7e632
TG
204 test_route();
205
e16bcf98
TG
206 test_async();
207
208 test_pipe();
209
65f568bb
TG
210 assert(sd_rtnl_open(0, &rtnl) >= 0);
211 assert(rtnl);
212
213 if_loopback = (int) if_nametoindex("lo");
214 assert(if_loopback > 0);
215
216 test_link_configure(rtnl, if_loopback);
217
218 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m) >= 0);
219 assert(m);
220
221 assert(sd_rtnl_message_get_type(m, &type) >= 0);
222 assert(type == RTM_GETLINK);
223
224 assert(sd_rtnl_message_read(m, &type, &data) == 0);
225
4555ec72 226 assert(sd_rtnl_call(rtnl, m, 0, &r) == 1);
65f568bb
TG
227 assert(sd_rtnl_message_get_type(r, &type) >= 0);
228 assert(type == RTM_NEWLINK);
229
8e1519bd 230 assert(sd_rtnl_message_read(m, &type, &data) == 0);
65f568bb
TG
231 assert((r = sd_rtnl_message_unref(r)) == NULL);
232
fe4824e0 233 assert(sd_rtnl_call(rtnl, m, -1, &r) == -EPERM);
65f568bb
TG
234 assert((m = sd_rtnl_message_unref(m)) == NULL);
235 assert((r = sd_rtnl_message_unref(r)) == NULL);
236
237 assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, 0, 0, &m) >= 0);
238 assert(m);
239
240 assert(sd_rtnl_message_append(m, IFLA_MTU, &mtu) >= 0);
241 assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1);
242
243 assert(type == IFLA_MTU);
244 assert(*mtu_reply == 0);
245
8e1519bd 246 assert(sd_rtnl_message_read(m, &type, &data) == 0);
65f568bb 247
4555ec72 248 assert(sd_rtnl_call(rtnl, m, -1, &r) == 1);
03d7e632 249 while (sd_rtnl_message_read(r, &type, &data) > 0) {
65f568bb 250 switch (type) {
eab97a46
TG
251// case IFLA_MTU:
252// assert(*(unsigned int *) data == 65536);
03d7e632 253// break;
eab97a46
TG
254// case IFLA_QDISC:
255// assert(streq((char *) data, "noqueue"));
03d7e632 256// break;
65f568bb
TG
257 case IFLA_IFNAME:
258 assert(streq((char *) data, "lo"));
03d7e632 259 break;
65f568bb
TG
260 }
261 }
262
263 assert((m = sd_rtnl_message_unref(m)) == NULL);
264 assert((r = sd_rtnl_message_unref(r)) == NULL);
265 assert((rtnl = sd_rtnl_unref(rtnl)) == NULL);
266
267 return EXIT_SUCCESS;
268}