ipsec: fast path outbound policy matching implementation for ipv6
[vpp.git] / src / vnet / ipsec / ipsec_test.c
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2021 Cisco Systems, Inc.
3  */
4
5 #include <vat/vat.h>
6 #include <vlibapi/api.h>
7 #include <vlibmemory/api.h>
8 #include <vppinfra/error.h>
9 #include <vpp/api/types.h>
10
11 #include <vnet/ipsec/ipsec.h>
12 #include <vnet/ip/ip_types_api.h>
13
14 #define __plugin_msg_base ipsec_test_main.msg_id_base
15 #include <vlibapi/vat_helper_macros.h>
16
17 #include <vlibmemory/vlib.api_enum.h>
18 #include <vlibmemory/vlib.api_types.h>
19
20 /* Declare message IDs */
21 #include <vnet/format_fns.h>
22 #include <vnet/ipsec/ipsec.api_enum.h>
23 #include <vnet/ipsec/ipsec.api_types.h>
24
25 #define vl_endianfun /* define message structures */
26 #include <vnet/ipsec/ipsec.api.h>
27 #undef vl_endianfun
28
29 #define vl_calcsizefun
30 #include <vnet/ipsec/ipsec.api.h>
31 #undef vl_calcsizefun
32
33 typedef struct
34 {
35   /* API message ID base */
36   u16 msg_id_base;
37   u32 ping_id;
38   vat_main_t *vat_main;
39 } ipsec_test_main_t;
40
41 static ipsec_test_main_t ipsec_test_main;
42
43 static void
44 vl_api_ipsec_spds_details_t_handler (vl_api_ipsec_spds_details_t *mp)
45 {
46 }
47
48 static void
49 vl_api_ipsec_itf_details_t_handler (vl_api_ipsec_itf_details_t *mp)
50 {
51 }
52
53 static int
54 api_ipsec_itf_delete (vat_main_t *vat)
55 {
56   return -1;
57 }
58
59 static int
60 api_ipsec_itf_create (vat_main_t *vat)
61 {
62   return -1;
63 }
64
65 static void
66 vl_api_ipsec_itf_create_reply_t_handler (vl_api_ipsec_itf_create_reply_t *vat)
67 {
68 }
69
70 static int
71 api_ipsec_spd_entry_add_del (vat_main_t *vam)
72 {
73   unformat_input_t *i = vam->input;
74   vl_api_ipsec_spd_entry_add_del_t *mp;
75   u8 is_add = 1, is_outbound = 0;
76   u32 spd_id = 0, sa_id = 0, protocol = IPSEC_POLICY_PROTOCOL_ANY, policy = 0;
77   i32 priority = 0;
78   u32 rport_start = 0, rport_stop = (u32) ~0;
79   u32 lport_start = 0, lport_stop = (u32) ~0;
80   vl_api_address_t laddr_start = {}, laddr_stop = {}, raddr_start = {},
81                    raddr_stop = {};
82   int ret;
83
84   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
85     {
86       if (unformat (i, "del"))
87         is_add = 0;
88       if (unformat (i, "outbound"))
89         is_outbound = 1;
90       if (unformat (i, "inbound"))
91         is_outbound = 0;
92       else if (unformat (i, "spd_id %d", &spd_id))
93         ;
94       else if (unformat (i, "sa_id %d", &sa_id))
95         ;
96       else if (unformat (i, "priority %d", &priority))
97         ;
98       else if (unformat (i, "protocol %d", &protocol))
99         ;
100       else if (unformat (i, "lport_start %d", &lport_start))
101         ;
102       else if (unformat (i, "lport_stop %d", &lport_stop))
103         ;
104       else if (unformat (i, "rport_start %d", &rport_start))
105         ;
106       else if (unformat (i, "rport_stop %d", &rport_stop))
107         ;
108       else if (unformat (i, "laddr_start %U", unformat_vl_api_address,
109                          &laddr_start))
110         ;
111       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
112                          &laddr_stop))
113         ;
114       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
115                          &raddr_start))
116         ;
117       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
118                          &raddr_stop))
119         ;
120       else if (unformat (i, "action %U", unformat_ipsec_policy_action,
121                          &policy))
122         {
123           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
124             {
125               clib_warning ("unsupported action: 'resolve'");
126               return -99;
127             }
128         }
129       else
130         {
131           clib_warning ("parse error '%U'", format_unformat_error, i);
132           return -99;
133         }
134     }
135
136   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
137
138   mp->is_add = is_add;
139
140   mp->entry.spd_id = ntohl (spd_id);
141   mp->entry.priority = ntohl (priority);
142   mp->entry.is_outbound = is_outbound;
143
144   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
145                sizeof (vl_api_address_t));
146   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
147                sizeof (vl_api_address_t));
148   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
149                sizeof (vl_api_address_t));
150   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
151                sizeof (vl_api_address_t));
152
153   mp->entry.protocol = protocol ? (u8) protocol : IPSEC_POLICY_PROTOCOL_ANY;
154   mp->entry.local_port_start = ntohs ((u16) lport_start);
155   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
156   mp->entry.remote_port_start = ntohs ((u16) rport_start);
157   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
158   mp->entry.policy = (u8) policy;
159   mp->entry.sa_id = ntohl (sa_id);
160
161   S (mp);
162   W (ret);
163   return ret;
164 }
165
166 static int
167 api_ipsec_spd_entry_add_del_v2 (vat_main_t *vam)
168 {
169   unformat_input_t *i = vam->input;
170   vl_api_ipsec_spd_entry_add_del_t *mp;
171   u8 is_add = 1, is_outbound = 0;
172   u32 spd_id = 0, sa_id = 0, protocol = IPSEC_POLICY_PROTOCOL_ANY, policy = 0;
173   i32 priority = 0;
174   u32 rport_start = 0, rport_stop = (u32) ~0;
175   u32 lport_start = 0, lport_stop = (u32) ~0;
176   vl_api_address_t laddr_start = {}, laddr_stop = {}, raddr_start = {},
177                    raddr_stop = {};
178   int ret;
179
180   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
181     {
182       if (unformat (i, "del"))
183         is_add = 0;
184       if (unformat (i, "outbound"))
185         is_outbound = 1;
186       if (unformat (i, "inbound"))
187         is_outbound = 0;
188       else if (unformat (i, "spd_id %d", &spd_id))
189         ;
190       else if (unformat (i, "sa_id %d", &sa_id))
191         ;
192       else if (unformat (i, "priority %d", &priority))
193         ;
194       else if (unformat (i, "protocol %d", &protocol))
195         ;
196       else if (unformat (i, "lport_start %d", &lport_start))
197         ;
198       else if (unformat (i, "lport_stop %d", &lport_stop))
199         ;
200       else if (unformat (i, "rport_start %d", &rport_start))
201         ;
202       else if (unformat (i, "rport_stop %d", &rport_stop))
203         ;
204       else if (unformat (i, "laddr_start %U", unformat_vl_api_address,
205                          &laddr_start))
206         ;
207       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
208                          &laddr_stop))
209         ;
210       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
211                          &raddr_start))
212         ;
213       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
214                          &raddr_stop))
215         ;
216       else if (unformat (i, "action %U", unformat_ipsec_policy_action,
217                          &policy))
218         {
219           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
220             {
221               clib_warning ("unsupported action: 'resolve'");
222               return -99;
223             }
224         }
225       else
226         {
227           clib_warning ("parse error '%U'", format_unformat_error, i);
228           return -99;
229         }
230     }
231
232   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
233
234   mp->is_add = is_add;
235
236   mp->entry.spd_id = ntohl (spd_id);
237   mp->entry.priority = ntohl (priority);
238   mp->entry.is_outbound = is_outbound;
239
240   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
241                sizeof (vl_api_address_t));
242   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
243                sizeof (vl_api_address_t));
244   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
245                sizeof (vl_api_address_t));
246   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
247                sizeof (vl_api_address_t));
248
249   mp->entry.protocol = (u8) protocol;
250   mp->entry.local_port_start = ntohs ((u16) lport_start);
251   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
252   mp->entry.remote_port_start = ntohs ((u16) rport_start);
253   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
254   mp->entry.policy = (u8) policy;
255   mp->entry.sa_id = ntohl (sa_id);
256
257   S (mp);
258   W (ret);
259   return ret;
260 }
261
262 static void
263 vl_api_ipsec_spd_details_t_handler (vl_api_ipsec_spd_details_t *mp)
264 {
265 }
266
267 static void
268 vl_api_ipsec_sad_entry_add_del_reply_t_handler (
269   vl_api_ipsec_sad_entry_add_del_reply_t *mp)
270 {
271 }
272
273 static void
274 vl_api_ipsec_sad_entry_add_del_v3_reply_t_handler (
275   vl_api_ipsec_sad_entry_add_del_v3_reply_t *mp)
276 {
277 }
278
279 static void
280 vl_api_ipsec_sad_entry_add_reply_t_handler (
281   vl_api_ipsec_sad_entry_add_reply_t *mp)
282 {
283 }
284
285 static int
286 api_ipsec_sad_entry_del (vat_main_t *vat)
287 {
288   return -1;
289 }
290
291 static void
292 vl_api_ipsec_sad_entry_add_del_v2_reply_t_handler (
293   vl_api_ipsec_sad_entry_add_del_v2_reply_t *mp)
294 {
295 }
296
297 static void
298 vl_api_ipsec_spd_interface_details_t_handler (
299   vl_api_ipsec_spd_interface_details_t *vat)
300 {
301 }
302
303 static int
304 api_ipsec_sad_entry_add_del_v3 (vat_main_t *vat)
305 {
306   return -1;
307 }
308
309 static int
310 api_ipsec_tunnel_protect_update (vat_main_t *vat)
311 {
312   return -1;
313 }
314
315 static void
316 vl_api_ipsec_backend_details_t_handler (vl_api_ipsec_backend_details_t *mp)
317 {
318 }
319
320 static int
321 api_ipsec_sa_v3_dump (vat_main_t *vat)
322 {
323   return -1;
324 }
325
326 static int
327 api_ipsec_tunnel_protect_dump (vat_main_t *vat)
328 {
329   return -1;
330 }
331
332 static int
333 api_ipsec_tunnel_protect_del (vat_main_t *vat)
334 {
335   return -1;
336 }
337
338 static void
339 vl_api_ipsec_tunnel_protect_details_t_handler (
340   vl_api_ipsec_tunnel_protect_details_t *mp)
341 {
342 }
343
344 static int
345 api_ipsec_sad_entry_add (vat_main_t *vat)
346 {
347   return -1;
348 }
349
350 static void
351 vl_api_ipsec_spd_entry_add_del_reply_t_handler (
352   vl_api_ipsec_spd_entry_add_del_reply_t *mp)
353 {
354 }
355
356 static void
357 vl_api_ipsec_spd_entry_add_del_v2_reply_t_handler (
358   vl_api_ipsec_spd_entry_add_del_v2_reply_t *mp)
359 {
360 }
361
362 static int
363 api_ipsec_spds_dump (vat_main_t *vam)
364 {
365   return -1;
366 }
367
368 static int
369 api_ipsec_itf_dump (vat_main_t *vam)
370 {
371   return -1;
372 }
373
374 static void
375 vl_api_ipsec_sa_v3_details_t_handler (vl_api_ipsec_sa_v3_details_t *mp)
376 {
377 }
378
379 static int
380 api_ipsec_spd_interface_dump (vat_main_t *vat)
381 {
382   return -1;
383 }
384
385 static void
386 vl_api_ipsec_sa_v2_details_t_handler (vl_api_ipsec_sa_v2_details_t *mp)
387 {
388 }
389
390 static int
391 api_ipsec_sa_v2_dump (vat_main_t *mp)
392 {
393   return -1;
394 }
395
396 static int
397 api_ipsec_sa_dump (vat_main_t *vam)
398 {
399   unformat_input_t *i = vam->input;
400   vl_api_ipsec_sa_dump_t *mp;
401   vl_api_control_ping_t *mp_ping;
402   u32 sa_id = ~0;
403   int ret;
404
405   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
406     {
407       if (unformat (i, "sa_id %d", &sa_id))
408         ;
409       else
410         {
411           clib_warning ("parse error '%U'", format_unformat_error, i);
412           return -99;
413         }
414     }
415
416   M (IPSEC_SA_DUMP, mp);
417
418   mp->sa_id = ntohl (sa_id);
419
420   S (mp);
421
422   /* Use a control ping for synchronization */
423   PING (&ipsec_test_main, mp_ping);
424   S (mp_ping);
425
426   W (ret);
427   return ret;
428 }
429
430 static void
431 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t *mp)
432 {
433   vat_main_t *vam = &vat_main;
434
435   print (vam->ofp,
436          "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
437          "crypto_key %U integ_alg %u integ_key %U flags %x "
438          "tunnel_src_addr %U tunnel_dst_addr %U "
439          "salt %u seq_outbound %lu last_seq_inbound %lu "
440          "replay_window %lu stat_index %u\n",
441          ntohl (mp->entry.sad_id), ntohl (mp->sw_if_index),
442          ntohl (mp->entry.spi), ntohl (mp->entry.protocol),
443          ntohl (mp->entry.crypto_algorithm), format_hex_bytes,
444          mp->entry.crypto_key.data, mp->entry.crypto_key.length,
445          ntohl (mp->entry.integrity_algorithm), format_hex_bytes,
446          mp->entry.integrity_key.data, mp->entry.integrity_key.length,
447          ntohl (mp->entry.flags), format_vl_api_address, &mp->entry.tunnel_src,
448          format_vl_api_address, &mp->entry.tunnel_dst, ntohl (mp->salt),
449          clib_net_to_host_u64 (mp->seq_outbound),
450          clib_net_to_host_u64 (mp->last_seq_inbound),
451          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
452 }
453
454 static int
455 api_ipsec_spd_dump (vat_main_t *vam)
456 {
457   return -1;
458 }
459
460 uword
461 unformat_ipsec_api_crypto_alg (unformat_input_t *input, va_list *args)
462 {
463   u32 *r = va_arg (*args, u32 *);
464
465   if (0)
466     ;
467 #define _(v, f, s) else if (unformat (input, s)) *r = IPSEC_API_CRYPTO_ALG_##f;
468   foreach_ipsec_crypto_alg
469 #undef _
470     else return 0;
471   return 1;
472 }
473
474 uword
475 unformat_ipsec_api_integ_alg (unformat_input_t *input, va_list *args)
476 {
477   u32 *r = va_arg (*args, u32 *);
478
479   if (0)
480     ;
481 #define _(v, f, s) else if (unformat (input, s)) *r = IPSEC_API_INTEG_ALG_##f;
482   foreach_ipsec_integ_alg
483 #undef _
484     else return 0;
485   return 1;
486 }
487
488 static int
489 api_ipsec_sad_entry_add_del (vat_main_t *vam)
490 {
491   unformat_input_t *i = vam->input;
492   vl_api_ipsec_sad_entry_add_del_t *mp;
493   u32 sad_id = 0, spi = 0;
494   u8 *ck = 0, *ik = 0;
495   u8 is_add = 1;
496
497   vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
498   vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
499   vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
500   vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
501   vl_api_address_t tun_src, tun_dst;
502   int ret;
503
504   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
505     {
506       if (unformat (i, "del"))
507         is_add = 0;
508       else if (unformat (i, "sad_id %d", &sad_id))
509         ;
510       else if (unformat (i, "spi %d", &spi))
511         ;
512       else if (unformat (i, "esp"))
513         protocol = IPSEC_API_PROTO_ESP;
514       else if (unformat (i, "tunnel_src %U", unformat_vl_api_address,
515                          &tun_src))
516         {
517           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
518           if (ADDRESS_IP6 == tun_src.af)
519             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
520         }
521       else if (unformat (i, "tunnel_dst %U", unformat_vl_api_address,
522                          &tun_dst))
523         {
524           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
525           if (ADDRESS_IP6 == tun_src.af)
526             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
527         }
528       else if (unformat (i, "crypto_alg %U", unformat_ipsec_api_crypto_alg,
529                          &crypto_alg))
530         ;
531       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
532         ;
533       else if (unformat (i, "integ_alg %U", unformat_ipsec_api_integ_alg,
534                          &integ_alg))
535         ;
536       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
537         ;
538       else
539         {
540           clib_warning ("parse error '%U'", format_unformat_error, i);
541           return -99;
542         }
543     }
544
545   M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
546
547   mp->is_add = is_add;
548   mp->entry.sad_id = ntohl (sad_id);
549   mp->entry.protocol = protocol;
550   mp->entry.spi = ntohl (spi);
551   mp->entry.flags = flags;
552
553   mp->entry.crypto_algorithm = crypto_alg;
554   mp->entry.integrity_algorithm = integ_alg;
555   mp->entry.crypto_key.length = vec_len (ck);
556   mp->entry.integrity_key.length = vec_len (ik);
557
558   if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
559     mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
560
561   if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
562     mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
563
564   if (ck)
565     clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
566   if (ik)
567     clib_memcpy (mp->entry.integrity_key.data, ik,
568                  mp->entry.integrity_key.length);
569
570   if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
571     {
572       clib_memcpy (&mp->entry.tunnel_src, &tun_src,
573                    sizeof (mp->entry.tunnel_src));
574       clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
575                    sizeof (mp->entry.tunnel_dst));
576     }
577
578   S (mp);
579   W (ret);
580   return ret;
581 }
582
583 static int
584 api_ipsec_sad_entry_add_del_v2 (vat_main_t *vam)
585 {
586   return -1;
587 }
588
589 static int
590 api_ipsec_interface_add_del_spd (vat_main_t *vam)
591 {
592   vnet_main_t *vnm = vnet_get_main ();
593   unformat_input_t *i = vam->input;
594   vl_api_ipsec_interface_add_del_spd_t *mp;
595   u32 sw_if_index;
596   u8 sw_if_index_set = 0;
597   u32 spd_id = (u32) ~0;
598   u8 is_add = 1;
599   int ret;
600
601   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
602     {
603       if (unformat (i, "del"))
604         is_add = 0;
605       else if (unformat (i, "spd_id %d", &spd_id))
606         ;
607       else if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
608                          &sw_if_index))
609         sw_if_index_set = 1;
610       else if (unformat (i, "sw_if_index %d", &sw_if_index))
611         sw_if_index_set = 1;
612       else
613         {
614           clib_warning ("parse error '%U'", format_unformat_error, i);
615           return -99;
616         }
617     }
618
619   if (spd_id == (u32) ~0)
620     {
621       errmsg ("spd_id must be set");
622       return -99;
623     }
624
625   if (sw_if_index_set == 0)
626     {
627       errmsg ("missing interface name or sw_if_index");
628       return -99;
629     }
630
631   M (IPSEC_INTERFACE_ADD_DEL_SPD, mp);
632
633   mp->spd_id = ntohl (spd_id);
634   mp->sw_if_index = ntohl (sw_if_index);
635   mp->is_add = is_add;
636
637   S (mp);
638   W (ret);
639   return ret;
640 }
641
642 static int
643 api_ipsec_backend_dump (vat_main_t *vam)
644 {
645   return -1;
646 }
647
648 static int
649 api_ipsec_select_backend (vat_main_t *vam)
650 {
651   return -1;
652 }
653
654 static int
655 api_ipsec_set_async_mode (vat_main_t *vam)
656 {
657   return -1;
658 }
659
660 static int
661 api_ipsec_spd_add_del (vat_main_t *vam)
662 {
663   unformat_input_t *i = vam->input;
664   vl_api_ipsec_spd_add_del_t *mp;
665   u32 spd_id = ~0;
666   u8 is_add = 1;
667   int ret;
668
669   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
670     {
671       if (unformat (i, "spd_id %d", &spd_id))
672         ;
673       else if (unformat (i, "del"))
674         is_add = 0;
675       else
676         {
677           clib_warning ("parse error '%U'", format_unformat_error, i);
678           return -99;
679         }
680     }
681   if (spd_id == ~0)
682     {
683       errmsg ("spd_id must be set");
684       return -99;
685     }
686
687   M (IPSEC_SPD_ADD_DEL, mp);
688
689   mp->spd_id = ntohl (spd_id);
690   mp->is_add = is_add;
691
692   S (mp);
693   W (ret);
694   return ret;
695 }
696
697 #include <vnet/ipsec/ipsec.api_test.c>
698
699 /*
700  * Local Variables:
701  * eval: (c-set-style "gnu")
702  * End:
703  */