]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/plugins/kernel_netlink/suites/test_socket.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libcharon / plugins / kernel_netlink / suites / test_socket.c
CommitLineData
02794456
MW
1/*
2 * Copyright (C) 2014 Martin Willi
19ef2aec
TB
3 *
4 * Copyright (C) secunet Security Networks AG
02794456
MW
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17#include <test_suite.h>
18
aa762bed
MW
19#include <threading/thread.h>
20
02794456
MW
21#include "../kernel_netlink_shared.h"
22
adb930ed
MW
23/**
24 * Netlink message drop configuration
25 */
26static int drop_interval = 0;
27
28/**
29 * Netlink message drop hook
30 */
31bool netlink_msg_loss(struct nlmsghdr *hdr)
32{
33 static refcount_t i;
34
35 if (drop_interval)
36 {
37 return ref_get(&i) % drop_interval == drop_interval - 1;
38 }
39 return FALSE;
40}
41
02794456 42START_TEST(test_echo)
4b41ea95
MW
43{
44 netlink_socket_t *s;
45 struct nlmsghdr *out;
46 struct rtmsg *msg;
47 char dst[] = {
48 127,0,0,1
49 };
50 size_t len;
51 netlink_buf_t request = {
52 .hdr = {
53 .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)),
54 .nlmsg_flags = NLM_F_REQUEST,
55 .nlmsg_type = RTM_GETROUTE,
56 },
57 };
58
59 msg = NLMSG_DATA(&request.hdr);
60 msg->rtm_family = AF_INET;
61 netlink_add_attribute(&request.hdr, RTA_DST,
62 chunk_from_thing(dst), sizeof(request));
63
6c58fabe 64 s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0);
4b41ea95
MW
65
66 ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS);
67 ck_assert_int_eq(out->nlmsg_type, RTM_NEWROUTE);
68 free(out);
69 s->destroy(s);
70}
71END_TEST
72
73START_TEST(test_echo_dump)
02794456
MW
74{
75 netlink_socket_t *s;
76 struct nlmsghdr *out, *current;
77 struct rtgenmsg *msg;
78 size_t len;
79 netlink_buf_t request = {
80 .hdr = {
81 .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
82 .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT,
83 .nlmsg_type = RTM_GETLINK,
84 },
85 };
86
6c58fabe 87 s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0);
02794456
MW
88 msg = NLMSG_DATA(&request.hdr);
89 msg->rtgen_family = AF_UNSPEC;
90
91 ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS);
92 current = out;
93 while (TRUE)
94 {
95 ck_assert(NLMSG_OK(current, len));
96 if (current->nlmsg_type == NLMSG_DONE)
97 {
98 break;
99 }
100 ck_assert_int_eq(current->nlmsg_type, RTM_NEWLINK);
101 current = NLMSG_NEXT(current, len);
102 }
103 free(out);
104 s->destroy(s);
105}
106END_TEST
107
aa762bed
MW
108CALLBACK(stress, void*,
109 netlink_socket_t *s)
4b41ea95
MW
110{
111 struct nlmsghdr *out;
112 struct rtmsg *msg;
113 char dst[] = {
114 127,0,0,1
115 };
116 size_t len;
117 int i;
118 netlink_buf_t request = {
119 .hdr = {
120 .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)),
121 .nlmsg_flags = NLM_F_REQUEST,
122 .nlmsg_type = RTM_GETROUTE,
123 },
124 };
125
126 for (i = 0; i < 10; i++)
127 {
128 msg = NLMSG_DATA(&request.hdr);
129 msg->rtm_family = AF_INET;
130 netlink_add_attribute(&request.hdr, RTA_DST,
131 chunk_from_thing(dst), sizeof(request));
132
133 ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS);
134 ck_assert_int_eq(out->nlmsg_type, RTM_NEWROUTE);
135 free(out);
136 }
137 return NULL;
138}
139
140CALLBACK(stress_dump, void*,
141 netlink_socket_t *s)
aa762bed
MW
142{
143 struct nlmsghdr *out, *current;
144 struct rtgenmsg *msg;
145 size_t len;
146 int i;
147 netlink_buf_t request = {
148 .hdr = {
149 .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
150 .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT,
151 .nlmsg_type = RTM_GETLINK,
152 },
153 };
154
155 msg = NLMSG_DATA(&request.hdr);
156 msg->rtgen_family = AF_UNSPEC;
157
158 for (i = 0; i < 10; i++)
159 {
160 ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS);
161 current = out;
162 while (TRUE)
163 {
164 ck_assert(NLMSG_OK(current, len));
165 if (current->nlmsg_type == NLMSG_DONE)
166 {
167 break;
168 }
169 ck_assert_int_eq(current->nlmsg_type, RTM_NEWLINK);
170 current = NLMSG_NEXT(current, len);
171 }
172 free(out);
173 }
174 return NULL;
175}
176
177START_TEST(test_stress)
178{
179 thread_t *threads[10];
180 netlink_socket_t *s;
181 int i;
182
6c58fabe 183 s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0);
aa762bed
MW
184 for (i = 0; i < countof(threads); i++)
185 {
186 threads[i] = thread_create(stress, s);
187 }
188 for (i = 0; i < countof(threads); i++)
189 {
190 threads[i]->join(threads[i]);
191 }
192 s->destroy(s);
193}
194END_TEST
195
4b41ea95
MW
196START_TEST(test_stress_dump)
197{
198 thread_t *threads[10];
199 netlink_socket_t *s;
200 int i;
201
6c58fabe 202 s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0);
4b41ea95
MW
203 for (i = 0; i < countof(threads); i++)
204 {
205 threads[i] = thread_create(stress_dump, s);
206 }
207 for (i = 0; i < countof(threads); i++)
208 {
209 threads[i]->join(threads[i]);
210 }
211 s->destroy(s);
212}
213END_TEST
214
adb930ed
MW
215START_TEST(test_retransmit_success)
216{
217 netlink_socket_t *s;
218 struct nlmsghdr *out;
219 struct rtgenmsg *msg;
220 size_t len;
221 netlink_buf_t request = {
222 .hdr = {
223 .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
224 .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT,
225 .nlmsg_type = RTM_GETLINK,
226 },
227 };
228
229 drop_interval = 2;
230
231 lib->settings->set_int(lib->settings,
232 "%s.plugins.kernel-netlink.timeout", 100, lib->ns);
233 lib->settings->set_int(lib->settings,
234 "%s.plugins.kernel-netlink.retries", 1, lib->ns);
235
6c58fabe 236 s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0);
adb930ed
MW
237 msg = NLMSG_DATA(&request.hdr);
238 msg->rtgen_family = AF_UNSPEC;
239
240 ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS);
241 free(out);
242 s->destroy(s);
243
244 drop_interval = 0;
245}
246END_TEST
247
248START_TEST(test_retransmit_fail)
249{
250 netlink_socket_t *s;
251 struct nlmsghdr *out;
252 struct rtgenmsg *msg;
253 size_t len;
254 netlink_buf_t request = {
255 .hdr = {
256 .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
257 .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT,
258 .nlmsg_type = RTM_GETLINK,
259 },
260 };
261
262 drop_interval = 1;
263
264 lib->settings->set_int(lib->settings,
265 "%s.plugins.kernel-netlink.timeout", 50, lib->ns);
266 lib->settings->set_int(lib->settings,
267 "%s.plugins.kernel-netlink.retries", 3, lib->ns);
268
6c58fabe 269 s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0);
adb930ed
MW
270 msg = NLMSG_DATA(&request.hdr);
271 msg->rtgen_family = AF_UNSPEC;
272
273 ck_assert(s->send(s, &request.hdr, &out, &len) == OUT_OF_RES);
274 s->destroy(s);
275
276 drop_interval = 0;
277}
278END_TEST
279
02794456
MW
280Suite *socket_suite_create()
281{
282 Suite *s;
283 TCase *tc;
284
285 s = suite_create("netlink socket");
286
287 tc = tcase_create("echo");
6c58fabe
MW
288 tcase_add_loop_test(tc, test_echo, 0, 2);
289 tcase_add_loop_test(tc, test_echo_dump, 0, 2);
02794456
MW
290 suite_add_tcase(s, tc);
291
aa762bed 292 tc = tcase_create("stress");
6c58fabe
MW
293 tcase_add_loop_test(tc, test_stress, 0, 2);
294 tcase_add_loop_test(tc, test_stress_dump, 0, 2);
aa762bed
MW
295 suite_add_tcase(s, tc);
296
adb930ed 297 tc = tcase_create("retransmit");
6c58fabe
MW
298 tcase_add_loop_test(tc, test_retransmit_success, 0, 2);
299 tcase_add_loop_test(tc, test_retransmit_fail, 0, 2);
adb930ed
MW
300 suite_add_tcase(s, tc);
301
02794456
MW
302 return s;
303}