Line data Source code
1 : /*
2 : * Copyright (c) 2021 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : #include <hs_apps/vcl/vcl_test.h>
17 :
18 : static int
19 11 : vt_tcp_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
20 : {
21 : uint32_t flags, flen;
22 : int rv;
23 :
24 11 : ts->fd = vppcom_session_create (VPPCOM_PROTO_TCP, ts->noblk_connect);
25 11 : if (ts->fd < 0)
26 : {
27 0 : vterr ("vppcom_session_create()", ts->fd);
28 0 : return ts->fd;
29 : }
30 :
31 11 : rv = vppcom_session_connect (ts->fd, endpt);
32 11 : if (rv < 0 && rv != VPPCOM_EINPROGRESS)
33 : {
34 0 : vterr ("vppcom_session_connect()", rv);
35 0 : return rv;
36 : }
37 :
38 11 : ts->read = vcl_test_read;
39 11 : ts->write = vcl_test_write;
40 :
41 11 : if (!ts->noblk_connect)
42 : {
43 11 : flags = O_NONBLOCK;
44 11 : flen = sizeof (flags);
45 11 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
46 11 : vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
47 : }
48 :
49 11 : return 0;
50 : }
51 :
52 : static int
53 9 : vt_tcp_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
54 : {
55 : int rv;
56 :
57 9 : ts->fd = vppcom_session_create (VPPCOM_PROTO_TCP, 1 /* is_nonblocking */);
58 9 : if (ts->fd < 0)
59 : {
60 0 : vterr ("vppcom_session_create()", ts->fd);
61 0 : return ts->fd;
62 : }
63 :
64 9 : rv = vppcom_session_bind (ts->fd, endpt);
65 9 : if (rv < 0)
66 : {
67 0 : vterr ("vppcom_session_bind()", rv);
68 0 : return rv;
69 : }
70 :
71 9 : rv = vppcom_session_listen (ts->fd, 10);
72 9 : if (rv < 0)
73 : {
74 0 : vterr ("vppcom_session_listen()", rv);
75 0 : return rv;
76 : }
77 :
78 9 : return 0;
79 : }
80 :
81 : static int
82 23 : vt_tcp_accept (int listen_fd, vcl_test_session_t *ts)
83 : {
84 : int client_fd;
85 :
86 23 : client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
87 23 : if (client_fd < 0)
88 : {
89 0 : vterr ("vppcom_session_accept()", client_fd);
90 0 : return client_fd;
91 : }
92 23 : ts->fd = client_fd;
93 23 : ts->is_open = 1;
94 23 : ts->read = vcl_test_read;
95 23 : ts->write = vcl_test_write;
96 :
97 23 : return 0;
98 : }
99 :
100 : static const vcl_test_proto_vft_t vcl_test_tcp = {
101 : .open = vt_tcp_connect,
102 : .listen = vt_tcp_listen,
103 : .accept = vt_tcp_accept,
104 : };
105 :
106 24 : VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_TCP, vcl_test_tcp);
107 :
108 : static int
109 0 : vt_udp_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
110 : {
111 : uint32_t flags, flen;
112 : int rv;
113 :
114 0 : ts->fd = vppcom_session_create (VPPCOM_PROTO_UDP, ts->noblk_connect);
115 0 : if (ts->fd < 0)
116 : {
117 0 : vterr ("vppcom_session_create()", ts->fd);
118 0 : return ts->fd;
119 : }
120 :
121 0 : rv = vppcom_session_connect (ts->fd, endpt);
122 0 : if (rv < 0 && rv != VPPCOM_EINPROGRESS)
123 : {
124 0 : vterr ("vppcom_session_connect()", rv);
125 0 : return rv;
126 : }
127 :
128 0 : ts->read = vcl_test_read;
129 0 : ts->write = vcl_test_write;
130 :
131 0 : if (!ts->noblk_connect)
132 : {
133 0 : flags = O_NONBLOCK;
134 0 : flen = sizeof (flags);
135 0 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
136 0 : vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
137 : }
138 :
139 0 : return 0;
140 : }
141 :
142 : static int
143 0 : vt_udp_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
144 : {
145 : int rv;
146 :
147 0 : ts->fd = vppcom_session_create (VPPCOM_PROTO_UDP, 1 /* is_nonblocking */);
148 0 : if (ts->fd < 0)
149 : {
150 0 : vterr ("vppcom_session_create()", ts->fd);
151 0 : return ts->fd;
152 : }
153 :
154 0 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CONNECTED, 0, 0);
155 :
156 : /* Listen is implicit */
157 0 : rv = vppcom_session_bind (ts->fd, endpt);
158 0 : if (rv < 0)
159 : {
160 0 : vterr ("vppcom_session_bind()", rv);
161 0 : return rv;
162 : }
163 :
164 0 : return 0;
165 : }
166 :
167 : static int
168 0 : vt_udp_accept (int listen_fd, vcl_test_session_t *ts)
169 : {
170 : int client_fd;
171 :
172 0 : client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
173 0 : if (client_fd < 0)
174 : {
175 0 : vterr ("vppcom_session_accept()", client_fd);
176 0 : return client_fd;
177 : }
178 0 : ts->fd = client_fd;
179 0 : ts->is_open = 1;
180 0 : ts->read = vcl_test_read;
181 0 : ts->write = vcl_test_write;
182 :
183 0 : return 0;
184 : }
185 :
186 : static const vcl_test_proto_vft_t vcl_test_udp = {
187 : .open = vt_udp_connect,
188 : .listen = vt_udp_listen,
189 : .accept = vt_udp_accept,
190 : };
191 :
192 24 : VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_UDP, vcl_test_udp);
193 :
194 : /*
195 : * TLS server cert and keys to be used for testing only
196 : */
197 : static char vcl_test_crt_rsa[] =
198 : "-----BEGIN CERTIFICATE-----\r\n"
199 : "MIID5zCCAs+gAwIBAgIJALeMYCEHrTtJMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD\r\n"
200 : "VQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMQ4wDAYDVQQK\r\n"
201 : "DAVDaXNjbzEOMAwGA1UECwwFZmQuaW8xFjAUBgNVBAMMDXRlc3R0bHMuZmQuaW8x\r\n"
202 : "IjAgBgkqhkiG9w0BCQEWE3ZwcC1kZXZAbGlzdHMuZmQuaW8wHhcNMTgwMzA1MjEx\r\n"
203 : "NTEyWhcNMjgwMzAyMjExNTEyWjCBiTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNB\r\n"
204 : "MREwDwYDVQQHDAhTYW4gSm9zZTEOMAwGA1UECgwFQ2lzY28xDjAMBgNVBAsMBWZk\r\n"
205 : "LmlvMRYwFAYDVQQDDA10ZXN0dGxzLmZkLmlvMSIwIAYJKoZIhvcNAQkBFhN2cHAt\r\n"
206 : "ZGV2QGxpc3RzLmZkLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\r\n"
207 : "4C1k8a1DuStgggqT4o09fP9sJ2dC54bxhS/Xk2VEfaIZ222WSo4X/syRVfVy9Yah\r\n"
208 : "cpI1zJ/RDxaZSFhgA+nPZBrFMsrULkrdAOpOVj8eDEp9JuWdO2ODSoFnCvLxcYWB\r\n"
209 : "Yc5kHryJpEaGJl1sFQSesnzMFty/59ta0stk0Fp8r5NhIjWvSovGzPo6Bhz+VS2c\r\n"
210 : "ebIZh4x1t2hHaFcgm0qJoJ6DceReWCW8w+yOVovTolGGq+bpb2Hn7MnRSZ2K2NdL\r\n"
211 : "+aLXpkZbS/AODP1FF2vTO1mYL290LO7/51vJmPXNKSDYMy5EvILr5/VqtjsFCwRL\r\n"
212 : "Q4jcM/+GeHSAFWx4qIv0BwIDAQABo1AwTjAdBgNVHQ4EFgQUWa1SOB37xmT53tZQ\r\n"
213 : "aXuLLhRI7U8wHwYDVR0jBBgwFoAUWa1SOB37xmT53tZQaXuLLhRI7U8wDAYDVR0T\r\n"
214 : "BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoUht13W4ya27NVzQuCMvqPWL3VM4\r\n"
215 : "3xbPFk02FaGz/WupPu276zGlzJAZrbuDcQowwwU1Ni1Yygxl96s1c2M5rHDTrOKG\r\n"
216 : "rK0hbkSFBo+i6I8u4HiiQ4rYmG0Hv6+sXn3of0HsbtDPGgWZoipPWDljPYEURu3e\r\n"
217 : "3HRe/Dtsj9CakBoSDzs8ndWaBR+f4sM9Tk1cjD46Gq2T/qpSPXqKxEUXlzhdCAn4\r\n"
218 : "twub17Bq2kykHpppCwPg5M+v30tHG/R2Go15MeFWbEJthFk3TZMjKL7UFs7fH+x2\r\n"
219 : "wSonXb++jY+KmCb93C+soABBizE57g/KmiR2IxQ/LMjDik01RSUIaM0lLA==\r\n"
220 : "-----END CERTIFICATE-----\r\n";
221 : static uint32_t vcl_test_crt_rsa_len = sizeof (vcl_test_crt_rsa);
222 :
223 : static char vcl_test_key_rsa[] =
224 : "-----BEGIN PRIVATE KEY-----\r\n"
225 : "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgLWTxrUO5K2CC\r\n"
226 : "CpPijT18/2wnZ0LnhvGFL9eTZUR9ohnbbZZKjhf+zJFV9XL1hqFykjXMn9EPFplI\r\n"
227 : "WGAD6c9kGsUyytQuSt0A6k5WPx4MSn0m5Z07Y4NKgWcK8vFxhYFhzmQevImkRoYm\r\n"
228 : "XWwVBJ6yfMwW3L/n21rSy2TQWnyvk2EiNa9Ki8bM+joGHP5VLZx5shmHjHW3aEdo\r\n"
229 : "VyCbSomgnoNx5F5YJbzD7I5Wi9OiUYar5ulvYefsydFJnYrY10v5otemRltL8A4M\r\n"
230 : "/UUXa9M7WZgvb3Qs7v/nW8mY9c0pINgzLkS8guvn9Wq2OwULBEtDiNwz/4Z4dIAV\r\n"
231 : "bHioi/QHAgMBAAECggEBAMzGipP8+oT166U+NlJXRFifFVN1DvdhG9PWnOxGL+c3\r\n"
232 : "ILmBBC08WQzmHshPemBvR6DZkA1H23cV5JTiLWrFtC00CvhXsLRMrE5+uWotI6yE\r\n"
233 : "iofybMroHvD6/X5R510UX9hQ6MHu5ShLR5VZ9zXHz5MpTmB/60jG5dLx+jgcwBK8\r\n"
234 : "LuGv2YB/WCUwT9QJ3YU2eaingnXtz/MrFbkbltrqlnBdlD+kTtw6Yac9y1XuuQXc\r\n"
235 : "BPeulLNDuPolJVWbUvDBZrpt2dXTgz8ws1sv+wCNE0xwQJsqW4Nx3QkpibUL9RUr\r\n"
236 : "CVbKlNfa9lopT6nGKlgX69R/uH35yh9AOsfasro6w0ECgYEA82UJ8u/+ORah+0sF\r\n"
237 : "Q0FfW5MTdi7OAUHOz16pUsGlaEv0ERrjZxmAkHA/VRwpvDBpx4alCv0Hc39PFLIk\r\n"
238 : "nhSsM2BEuBkTAs6/GaoNAiBtQVE/hN7awNRWVmlieS0go3Y3dzaE9IUMyj8sPOFT\r\n"
239 : "5JdJ6BM69PHKCkY3dKdnnfpFEuECgYEA68mRpteunF1mdZgXs+WrN+uLlRrQR20F\r\n"
240 : "ZyMYiUCH2Dtn26EzA2moy7FipIIrQcX/j+KhYNGM3e7MU4LymIO29E18mn8JODnH\r\n"
241 : "sQOXzBTsf8A4yIVMkcuQD3bfb0JiUGYUPOidTp2N7IJA7+6Yc3vQOyb74lnKnJoO\r\n"
242 : "gougPT2wS+cCgYAn7muzb6xFsXDhyW0Tm6YJYBfRS9yAWEuVufINobeBZPSl2cN1\r\n"
243 : "Jrnw+HlrfTNbrJWuJmjtZJXUXQ6cVp2rUbjutNyRV4vG6iRwEXYQ40EJdkr1gZpi\r\n"
244 : "CHQhuShuuPih2MNAy7EEbM+sXrDjTBR3bFqzuHPzu7dp+BshCFX3lRfAAQKBgGQt\r\n"
245 : "K5i7IhCFDjb/+3IPLgOAK7mZvsvZ4eXD33TQ2eZgtut1PXtBtNl17/b85uv293Fm\r\n"
246 : "VDISVcsk3eLNS8zIiT6afUoWlxAwXEs0v5WRfjl4radkGvgGiJpJYvyeM67877RB\r\n"
247 : "EDSKc/X8ESLfOB44iGvZUEMG6zJFscx9DgN25iQZAoGAbyd+JEWwdVH9/K3IH1t2\r\n"
248 : "PBkZX17kNWv+iVM1WyFjbe++vfKZCrOJiyiqhDeEqgrP3AuNMlaaduC3VRC3G5oV\r\n"
249 : "Mj1tlhDWQ/qhvKdCKNdIVQYDE75nw+FRWV8yYkHAnXYW3tNoweDIwixE0hkPR1bc\r\n"
250 : "oEjPLVNtx8SOj/M4rhaPT3I=\r\n"
251 : "-----END PRIVATE KEY-----\r\n";
252 : static uint32_t vcl_test_key_rsa_len = sizeof (vcl_test_key_rsa);
253 :
254 : static int
255 6 : vt_add_cert_key_pair ()
256 : {
257 6 : vcl_test_main_t *vt = &vcl_test_main;
258 : vppcom_cert_key_pair_t ckpair;
259 : int ckp_index;
260 :
261 6 : vtinf ("Adding tls certs ...");
262 :
263 6 : ckpair.cert = vcl_test_crt_rsa;
264 6 : ckpair.key = vcl_test_key_rsa;
265 6 : ckpair.cert_len = vcl_test_crt_rsa_len;
266 6 : ckpair.key_len = vcl_test_key_rsa_len;
267 6 : ckp_index = vppcom_add_cert_key_pair (&ckpair);
268 6 : if (ckp_index < 0)
269 : {
270 0 : vterr ("vppcom_add_cert_key_pair()", ckp_index);
271 0 : return ckp_index;
272 : }
273 :
274 6 : vt->ckpair_index = ckp_index;
275 6 : return 0;
276 : }
277 :
278 : static int
279 4 : vt_tls_init (vcl_test_cfg_t *cfg)
280 : {
281 4 : return vt_add_cert_key_pair ();
282 : }
283 :
284 : static int
285 2 : vt_tls_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
286 : {
287 2 : vcl_test_main_t *vt = &vcl_test_main;
288 : uint32_t flags, flen, ckp_len;
289 : int rv;
290 :
291 2 : ts->fd = vppcom_session_create (VPPCOM_PROTO_TLS, ts->noblk_connect);
292 2 : if (ts->fd < 0)
293 : {
294 0 : vterr ("vppcom_session_create()", ts->fd);
295 0 : return ts->fd;
296 : }
297 :
298 2 : ckp_len = sizeof (vt->ckpair_index);
299 2 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
300 : &ckp_len);
301 :
302 2 : rv = vppcom_session_connect (ts->fd, endpt);
303 2 : if (rv < 0 && rv != VPPCOM_EINPROGRESS)
304 : {
305 0 : vterr ("vppcom_session_connect()", rv);
306 0 : return rv;
307 : }
308 :
309 2 : ts->read = vcl_test_read;
310 2 : ts->write = vcl_test_write;
311 :
312 2 : if (!ts->noblk_connect)
313 : {
314 2 : flags = O_NONBLOCK;
315 2 : flen = sizeof (flags);
316 2 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
317 2 : vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
318 : }
319 :
320 2 : return 0;
321 : }
322 :
323 : static int
324 2 : vt_tls_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
325 : {
326 2 : vcl_test_main_t *vt = &vcl_test_main;
327 : uint32_t ckp_len;
328 : int rv;
329 :
330 2 : ts->fd = vppcom_session_create (VPPCOM_PROTO_TLS, 1 /* is_nonblocking */);
331 2 : if (ts->fd < 0)
332 : {
333 0 : vterr ("vppcom_session_create()", ts->fd);
334 0 : return ts->fd;
335 : }
336 :
337 2 : ckp_len = sizeof (vt->ckpair_index);
338 2 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
339 : &ckp_len);
340 :
341 2 : rv = vppcom_session_bind (ts->fd, endpt);
342 2 : if (rv < 0)
343 : {
344 0 : vterr ("vppcom_session_bind()", rv);
345 0 : return rv;
346 : }
347 :
348 2 : rv = vppcom_session_listen (ts->fd, 10);
349 2 : if (rv < 0)
350 : {
351 0 : vterr ("vppcom_session_listen()", rv);
352 0 : return rv;
353 : }
354 :
355 2 : return 0;
356 : }
357 :
358 : static int
359 2 : vt_tls_accept (int listen_fd, vcl_test_session_t *ts)
360 : {
361 : int client_fd;
362 :
363 2 : client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
364 2 : if (client_fd < 0)
365 : {
366 0 : vterr ("vppcom_session_accept()", client_fd);
367 0 : return client_fd;
368 : }
369 2 : ts->fd = client_fd;
370 2 : ts->is_open = 1;
371 2 : ts->read = vcl_test_read;
372 2 : ts->write = vcl_test_write;
373 :
374 2 : return 0;
375 : }
376 :
377 : static const vcl_test_proto_vft_t vcl_test_tls = {
378 : .init = vt_tls_init,
379 : .open = vt_tls_connect,
380 : .listen = vt_tls_listen,
381 : .accept = vt_tls_accept,
382 : };
383 :
384 24 : VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_TLS, vcl_test_tls);
385 :
386 : static int
387 2 : vt_dtls_init (vcl_test_cfg_t *cfg)
388 : {
389 2 : return vt_add_cert_key_pair ();
390 : }
391 :
392 : static int
393 1 : vt_dtls_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
394 : {
395 1 : vcl_test_main_t *vt = &vcl_test_main;
396 : uint32_t flags, flen, ckp_len;
397 : int rv;
398 :
399 1 : ts->fd = vppcom_session_create (VPPCOM_PROTO_DTLS, ts->noblk_connect);
400 1 : if (ts->fd < 0)
401 : {
402 0 : vterr ("vppcom_session_create()", ts->fd);
403 0 : return ts->fd;
404 : }
405 :
406 1 : ckp_len = sizeof (vt->ckpair_index);
407 1 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
408 : &ckp_len);
409 :
410 1 : rv = vppcom_session_connect (ts->fd, endpt);
411 1 : if (rv < 0 && rv != VPPCOM_EINPROGRESS)
412 : {
413 0 : vterr ("vppcom_session_connect()", rv);
414 0 : return rv;
415 : }
416 :
417 1 : ts->read = vcl_test_read;
418 1 : ts->write = vcl_test_write;
419 :
420 1 : if (!ts->noblk_connect)
421 : {
422 1 : flags = O_NONBLOCK;
423 1 : flen = sizeof (flags);
424 1 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
425 1 : vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
426 : }
427 :
428 1 : return 0;
429 : }
430 :
431 : static int
432 1 : vt_dtls_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
433 : {
434 1 : vcl_test_main_t *vt = &vcl_test_main;
435 : uint32_t ckp_len;
436 : int rv;
437 :
438 1 : ts->fd = vppcom_session_create (VPPCOM_PROTO_DTLS, 1 /* is_nonblocking */);
439 1 : if (ts->fd < 0)
440 : {
441 0 : vterr ("vppcom_session_create()", ts->fd);
442 0 : return ts->fd;
443 : }
444 :
445 1 : ckp_len = sizeof (vt->ckpair_index);
446 1 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
447 : &ckp_len);
448 :
449 1 : rv = vppcom_session_bind (ts->fd, endpt);
450 1 : if (rv < 0)
451 : {
452 0 : vterr ("vppcom_session_bind()", rv);
453 0 : return rv;
454 : }
455 :
456 1 : rv = vppcom_session_listen (ts->fd, 10);
457 1 : if (rv < 0)
458 : {
459 0 : vterr ("vppcom_session_listen()", rv);
460 0 : return rv;
461 : }
462 :
463 1 : return 0;
464 : }
465 :
466 : static int
467 1 : vt_dtls_accept (int listen_fd, vcl_test_session_t *ts)
468 : {
469 : int client_fd;
470 :
471 1 : client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
472 1 : if (client_fd < 0)
473 : {
474 0 : vterr ("vppcom_session_accept()", client_fd);
475 0 : return client_fd;
476 : }
477 1 : ts->fd = client_fd;
478 1 : ts->is_open = 1;
479 1 : ts->read = vcl_test_read;
480 1 : ts->write = vcl_test_write;
481 :
482 1 : return 0;
483 : }
484 :
485 : static const vcl_test_proto_vft_t vcl_test_dtls = {
486 : .init = vt_dtls_init,
487 : .open = vt_dtls_connect,
488 : .listen = vt_dtls_listen,
489 : .accept = vt_dtls_accept,
490 : };
491 :
492 24 : VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_DTLS, vcl_test_dtls);
493 :
494 : static int
495 0 : vt_quic_init (vcl_test_cfg_t *cfg)
496 : {
497 0 : vcl_test_main_t *vt = &vcl_test_main;
498 :
499 0 : if (cfg)
500 0 : vt->cfg = *cfg;
501 :
502 0 : return vt_add_cert_key_pair ();
503 : }
504 :
505 : static int
506 0 : vt_quic_maybe_init_wrk (vcl_test_main_t *vt, vcl_test_wrk_t *wrk,
507 : vppcom_endpt_t *endpt)
508 : {
509 : uint32_t size, i, flags, flen, ckp_len;
510 : vcl_test_session_t *tq;
511 : int rv;
512 :
513 : /* Test already initialized */
514 0 : if (wrk->n_qsessions == vt->cfg.num_test_qsessions)
515 0 : return 0;
516 :
517 : /* Make sure pool is large enough */
518 0 : if (!wrk->qsessions)
519 : {
520 0 : wrk->qsessions =
521 0 : calloc (vt->cfg.num_test_qsessions, sizeof (vcl_test_session_t));
522 : }
523 : else
524 : {
525 0 : size = vt->cfg.num_test_qsessions * sizeof (vcl_test_session_t);
526 0 : wrk->qsessions = realloc (wrk->qsessions, size);
527 : }
528 :
529 0 : if (!wrk->qsessions)
530 : {
531 0 : vterr ("failed to alloc Qsessions", -errno);
532 0 : return errno;
533 : }
534 :
535 0 : for (i = 0; i < vt->cfg.num_test_qsessions; i++)
536 : {
537 0 : tq = &wrk->qsessions[i];
538 0 : tq->fd =
539 0 : vppcom_session_create (VPPCOM_PROTO_QUIC, 0 /* is_nonblocking */);
540 0 : tq->session_index = i;
541 0 : if (tq->fd < 0)
542 : {
543 0 : vterr ("vppcom_session_create()", tq->fd);
544 0 : return tq->fd;
545 : }
546 :
547 0 : ckp_len = sizeof (vt->ckpair_index);
548 0 : vppcom_session_attr (tq->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
549 : &ckp_len);
550 :
551 : /* Connect is blocking */
552 0 : rv = vppcom_session_connect (tq->fd, endpt);
553 0 : if (rv < 0)
554 : {
555 0 : vterr ("vppcom_session_connect()", rv);
556 0 : return rv;
557 : }
558 0 : flags = O_NONBLOCK;
559 0 : flen = sizeof (flags);
560 0 : vppcom_session_attr (tq->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
561 0 : vtinf ("Test Qsession %d (fd %d) connected.", i, tq->fd);
562 : }
563 0 : wrk->n_qsessions = vt->cfg.num_test_qsessions;
564 :
565 0 : return 0;
566 : }
567 :
568 : static int
569 0 : vt_quic_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
570 : {
571 0 : vcl_test_main_t *vt = &vcl_test_main;
572 : uint32_t wrk_index, flags, flen;
573 : vcl_test_session_t *tq;
574 : vcl_test_wrk_t *wrk;
575 : int rv;
576 :
577 0 : wrk_index = vcl_test_worker_index ();
578 0 : wrk = &vt->wrk[wrk_index];
579 :
580 : /* Make sure qsessions are initialized */
581 0 : vt_quic_maybe_init_wrk (vt, wrk, endpt);
582 :
583 0 : ts->fd = vppcom_session_create (VPPCOM_PROTO_QUIC, ts->noblk_connect);
584 0 : if (ts->fd < 0)
585 : {
586 0 : vterr ("vppcom_session_create()", ts->fd);
587 0 : return ts->fd;
588 : }
589 :
590 : /* Choose qession to use for stream */
591 0 : tq = &wrk->qsessions[ts->session_index / vt->cfg.num_test_sessions_perq];
592 :
593 0 : rv = vppcom_session_stream_connect (ts->fd, tq->fd);
594 0 : if (rv < 0 && rv != VPPCOM_EINPROGRESS)
595 : {
596 0 : vterr ("vppcom_session_stream_connect()", rv);
597 0 : return rv;
598 : }
599 :
600 0 : ts->read = vcl_test_read;
601 0 : ts->write = vcl_test_write;
602 :
603 0 : if (!ts->noblk_connect)
604 : {
605 0 : flags = O_NONBLOCK;
606 0 : flen = sizeof (flags);
607 0 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
608 0 : vtinf ("Test (quic stream) session %d (fd %d) connected.",
609 : ts->session_index, ts->fd);
610 : }
611 :
612 0 : return 0;
613 : }
614 :
615 : static int
616 0 : vt_quic_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
617 : {
618 0 : vcl_test_main_t *vt = &vcl_test_main;
619 : uint32_t ckp_len;
620 : int rv;
621 :
622 0 : ts->fd = vppcom_session_create (VPPCOM_PROTO_QUIC, 1 /* is_nonblocking */);
623 0 : if (ts->fd < 0)
624 : {
625 0 : vterr ("vppcom_session_create()", ts->fd);
626 0 : return ts->fd;
627 : }
628 :
629 0 : ckp_len = sizeof (vt->ckpair_index);
630 0 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
631 : &ckp_len);
632 :
633 0 : rv = vppcom_session_bind (ts->fd, endpt);
634 0 : if (rv < 0)
635 : {
636 0 : vterr ("vppcom_session_bind()", rv);
637 0 : return rv;
638 : }
639 :
640 0 : rv = vppcom_session_listen (ts->fd, 10);
641 0 : if (rv < 0)
642 : {
643 0 : vterr ("vppcom_session_listen()", rv);
644 0 : return rv;
645 : }
646 :
647 0 : return 0;
648 : }
649 :
650 : static int
651 0 : vt_quic_accept (int listen_fd, vcl_test_session_t *ts)
652 : {
653 : int client_fd;
654 :
655 0 : client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
656 0 : if (client_fd < 0)
657 : {
658 0 : vterr ("vppcom_session_accept()", client_fd);
659 0 : return client_fd;
660 : }
661 0 : ts->fd = client_fd;
662 0 : ts->is_open = 1;
663 0 : ts->read = vcl_test_read;
664 0 : ts->write = vcl_test_write;
665 :
666 0 : return 0;
667 : }
668 :
669 : static int
670 0 : vt_quic_close (vcl_test_session_t *ts)
671 : {
672 0 : int listener_fd = vppcom_session_listener (ts->fd);
673 :
674 0 : if ((vppcom_session_n_accepted (listener_fd) == 0) &
675 0 : vppcom_session_is_connectable_listener (listener_fd))
676 : {
677 0 : vtinf ("Connected Listener fd %x has no more sessions", listener_fd);
678 0 : vppcom_session_close (listener_fd);
679 : }
680 :
681 0 : return 0;
682 : }
683 :
684 : static const vcl_test_proto_vft_t vcl_test_quic = {
685 : .init = vt_quic_init,
686 : .open = vt_quic_connect,
687 : .listen = vt_quic_listen,
688 : .accept = vt_quic_accept,
689 : .close = vt_quic_close,
690 : };
691 :
692 24 : VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_QUIC, vcl_test_quic);
693 :
694 : static unsigned char test_key[46] = {
695 : 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, 0xd6, 0x4f, 0xa3, 0x2c,
696 : 0x06, 0xde, 0x41, 0x39, 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb,
697 : 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6, 0xc1, 0x73, 0xc3, 0x17, 0xf2, 0xda,
698 : 0xbe, 0x35, 0x77, 0x93, 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6
699 : };
700 :
701 : typedef struct
702 : {
703 : unsigned char cc : 4;
704 : unsigned char x : 1;
705 : unsigned char p : 1;
706 : unsigned char version : 2;
707 : unsigned char pt : 7;
708 : unsigned char m : 1;
709 : uint16_t seq;
710 : uint32_t ts;
711 : uint32_t ssrc;
712 : } rtp_hdr_t;
713 :
714 : typedef struct
715 : {
716 : rtp_hdr_t tx_hdr;
717 : rtp_hdr_t rx_hdr;
718 : } rtp_headers_t;
719 :
720 : typedef struct transport_endpt_cfg_srtp_policy
721 : {
722 : uint32_t ssrc_type;
723 : uint32_t ssrc_value;
724 : uint32_t window_size;
725 : uint8_t allow_repeat_tx;
726 : uint8_t key_len;
727 : uint8_t key[46];
728 : } transport_endpt_cfg_srtp_policy_t;
729 :
730 : typedef struct transport_endpt_cfg_srtp
731 : {
732 : transport_endpt_cfg_srtp_policy_t policy[2];
733 : } transport_endpt_cfg_srtp_t;
734 :
735 : static void
736 0 : vt_session_add_srtp_policy (vcl_test_session_t *ts, int is_connect)
737 : {
738 : transport_endpt_cfg_srtp_t *srtp_cfg;
739 : transport_endpt_cfg_srtp_policy_t *test_policy;
740 : uint32_t rx_ssrc, tx_ssrc;
741 : uint32_t cfg_size;
742 :
743 0 : rx_ssrc = is_connect ? 0xcafebeef : 0xbeefcafe;
744 0 : tx_ssrc = is_connect ? 0xbeefcafe : 0xcafebeef;
745 :
746 0 : cfg_size = sizeof (transport_endpt_cfg_srtp_t);
747 0 : srtp_cfg = malloc (cfg_size);
748 0 : memset (srtp_cfg, 0, cfg_size);
749 :
750 0 : test_policy = &srtp_cfg->policy[0];
751 0 : test_policy->ssrc_type = 1 /* ssrc_specific */;
752 0 : test_policy->ssrc_value = rx_ssrc;
753 0 : memcpy (test_policy->key, test_key, sizeof (test_key));
754 0 : test_policy->key_len = sizeof (test_key);
755 0 : test_policy->window_size = 128;
756 0 : test_policy->allow_repeat_tx = 1;
757 :
758 0 : test_policy = &srtp_cfg->policy[1];
759 0 : test_policy->ssrc_type = 1 /* ssrc_specific */;
760 0 : test_policy->ssrc_value = tx_ssrc;
761 0 : memcpy (test_policy->key, test_key, sizeof (test_key));
762 0 : test_policy->key_len = sizeof (test_key);
763 0 : test_policy->window_size = 128;
764 0 : test_policy->allow_repeat_tx = 1;
765 :
766 0 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_ENDPT_EXT_CFG, srtp_cfg,
767 : &cfg_size);
768 0 : free (srtp_cfg);
769 0 : }
770 :
771 : static void
772 0 : vt_srtp_session_init (vcl_test_session_t *ts, int is_connect)
773 : {
774 : uint32_t rx_ssrc, tx_ssrc;
775 : rtp_headers_t *rtp_hdrs;
776 : rtp_hdr_t *hdr;
777 :
778 0 : rx_ssrc = is_connect ? 0xcafebeef : 0xbeefcafe;
779 0 : tx_ssrc = is_connect ? 0xbeefcafe : 0xcafebeef;
780 :
781 0 : rtp_hdrs = malloc (sizeof (rtp_headers_t));
782 0 : memset (rtp_hdrs, 0, sizeof (*rtp_hdrs));
783 0 : ts->opaque = rtp_hdrs;
784 :
785 0 : hdr = &rtp_hdrs->rx_hdr;
786 0 : hdr->version = 2;
787 0 : hdr->p = 0;
788 0 : hdr->x = 0;
789 0 : hdr->cc = 0;
790 0 : hdr->m = 0;
791 0 : hdr->pt = 0x1;
792 0 : hdr->seq = 0;
793 0 : hdr->ts = 0;
794 0 : hdr->ssrc = htonl (rx_ssrc);
795 :
796 0 : hdr = &rtp_hdrs->tx_hdr;
797 0 : hdr->version = 2;
798 0 : hdr->p = 0;
799 0 : hdr->x = 0;
800 0 : hdr->cc = 0;
801 0 : hdr->m = 0;
802 0 : hdr->pt = 0x1;
803 0 : hdr->seq = 0;
804 0 : hdr->ts = 0;
805 0 : hdr->ssrc = htonl (tx_ssrc);
806 0 : }
807 :
808 : static int
809 0 : vt_srtp_write (vcl_test_session_t *ts, void *buf, uint32_t nbytes)
810 : {
811 0 : int tx_bytes = 0, nbytes_left = nbytes, rv;
812 0 : vcl_test_stats_t *stats = &ts->stats;
813 : rtp_hdr_t *hdr;
814 :
815 0 : hdr = &((rtp_headers_t *) ts->opaque)->tx_hdr;
816 0 : hdr->seq = htons (ntohs (hdr->seq) + 1);
817 0 : hdr->ts = htonl (ntohl (hdr->ts) + 1);
818 :
819 0 : memcpy (buf, hdr, sizeof (*hdr));
820 :
821 : do
822 : {
823 0 : stats->tx_xacts++;
824 0 : rv = vppcom_session_write (ts->fd, buf, nbytes_left);
825 0 : if (rv < 0)
826 : {
827 0 : if ((rv == VPPCOM_EAGAIN || rv == VPPCOM_EWOULDBLOCK))
828 0 : stats->tx_eagain++;
829 0 : break;
830 : }
831 0 : tx_bytes += rv;
832 0 : nbytes_left = nbytes_left - rv;
833 0 : buf += rv;
834 0 : stats->tx_incomp++;
835 : }
836 0 : while (tx_bytes != nbytes);
837 :
838 0 : if (tx_bytes < 0)
839 0 : return 0;
840 :
841 0 : stats->tx_bytes += tx_bytes;
842 :
843 0 : return (tx_bytes);
844 : }
845 :
846 : static inline int
847 0 : vt_srtp_read (vcl_test_session_t *ts, void *buf, uint32_t nbytes)
848 : {
849 0 : vcl_test_stats_t *stats = &ts->stats;
850 : rtp_hdr_t *hdr;
851 : int rx_bytes;
852 :
853 0 : stats->rx_xacts++;
854 0 : rx_bytes = vppcom_session_read (ts->fd, buf, nbytes);
855 :
856 0 : if (rx_bytes <= 0)
857 : {
858 0 : if (rx_bytes == VPPCOM_EAGAIN || rx_bytes == VPPCOM_EWOULDBLOCK)
859 0 : stats->rx_eagain++;
860 : else
861 0 : return -1;
862 : }
863 :
864 0 : if (rx_bytes < nbytes)
865 0 : stats->rx_incomp++;
866 :
867 0 : stats->rx_bytes += rx_bytes;
868 :
869 0 : hdr = &((rtp_headers_t *) ts->opaque)->rx_hdr;
870 0 : if (((rtp_hdr_t *) buf)->ssrc != hdr->ssrc)
871 0 : hdr->ssrc = ((rtp_hdr_t *) buf)->ssrc;
872 0 : return (rx_bytes);
873 : }
874 :
875 : static int
876 0 : vt_srtp_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
877 : {
878 : uint32_t flags, flen;
879 : int rv;
880 :
881 0 : ts->fd = vppcom_session_create (VPPCOM_PROTO_SRTP, ts->noblk_connect);
882 0 : if (ts->fd < 0)
883 : {
884 0 : vterr ("vppcom_session_create()", ts->fd);
885 0 : return ts->fd;
886 : }
887 :
888 0 : vt_session_add_srtp_policy (ts, 1 /* is connect */);
889 :
890 0 : rv = vppcom_session_connect (ts->fd, endpt);
891 0 : if (rv < 0 && rv != VPPCOM_EINPROGRESS)
892 : {
893 0 : vterr ("vppcom_session_connect()", rv);
894 0 : return rv;
895 : }
896 :
897 0 : ts->read = vt_srtp_read;
898 0 : ts->write = vt_srtp_write;
899 :
900 0 : if (!ts->noblk_connect)
901 : {
902 0 : flags = O_NONBLOCK;
903 0 : flen = sizeof (flags);
904 0 : vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
905 0 : vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
906 : }
907 :
908 0 : vt_srtp_session_init (ts, 1 /* is connect */);
909 :
910 0 : return 0;
911 : }
912 :
913 : static int
914 0 : vt_srtp_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
915 : {
916 : int rv;
917 :
918 0 : ts->fd = vppcom_session_create (VPPCOM_PROTO_SRTP, 1 /* is_nonblocking */);
919 0 : if (ts->fd < 0)
920 : {
921 0 : vterr ("vppcom_session_create()", ts->fd);
922 0 : return ts->fd;
923 : }
924 :
925 0 : vt_session_add_srtp_policy (ts, 0 /* is connect */);
926 :
927 0 : rv = vppcom_session_bind (ts->fd, endpt);
928 0 : if (rv < 0)
929 : {
930 0 : vterr ("vppcom_session_bind()", rv);
931 0 : return rv;
932 : }
933 :
934 0 : rv = vppcom_session_listen (ts->fd, 10);
935 0 : if (rv < 0)
936 : {
937 0 : vterr ("vppcom_session_listen()", rv);
938 0 : return rv;
939 : }
940 :
941 0 : return 0;
942 : }
943 :
944 : static int
945 0 : vt_srtp_accept (int listen_fd, vcl_test_session_t *ts)
946 : {
947 : int client_fd;
948 :
949 0 : client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
950 0 : if (client_fd < 0)
951 : {
952 0 : vterr ("vppcom_session_accept()", client_fd);
953 0 : return client_fd;
954 : }
955 0 : ts->fd = client_fd;
956 0 : ts->is_open = 1;
957 0 : ts->read = vt_srtp_read;
958 0 : ts->write = vt_srtp_write;
959 :
960 0 : vt_srtp_session_init (ts, 0 /* is connect */);
961 :
962 0 : return 0;
963 : }
964 :
965 : static int
966 0 : vt_srtp_close (vcl_test_session_t *ts)
967 : {
968 0 : free (ts->opaque);
969 0 : return 0;
970 : }
971 :
972 : static const vcl_test_proto_vft_t vcl_test_srtp = {
973 : .open = vt_srtp_connect,
974 : .listen = vt_srtp_listen,
975 : .accept = vt_srtp_accept,
976 : .close = vt_srtp_close,
977 : };
978 :
979 24 : VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_SRTP, vcl_test_srtp);
980 :
981 : /*
982 : * fd.io coding-style-patch-verification: ON
983 : *
984 : * Local Variables:
985 : * eval: (c-set-style "gnu")
986 : * End:
987 : */
|