ipsec: new api for sa ips and ports updates
[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_sad_entry_update (vat_main_t *vat)
311 {
312   return -1;
313 }
314
315 static int
316 api_ipsec_tunnel_protect_update (vat_main_t *vat)
317 {
318   return -1;
319 }
320
321 static void
322 vl_api_ipsec_backend_details_t_handler (vl_api_ipsec_backend_details_t *mp)
323 {
324 }
325
326 static int
327 api_ipsec_sa_v3_dump (vat_main_t *vat)
328 {
329   return -1;
330 }
331
332 static int
333 api_ipsec_tunnel_protect_dump (vat_main_t *vat)
334 {
335   return -1;
336 }
337
338 static int
339 api_ipsec_tunnel_protect_del (vat_main_t *vat)
340 {
341   return -1;
342 }
343
344 static void
345 vl_api_ipsec_tunnel_protect_details_t_handler (
346   vl_api_ipsec_tunnel_protect_details_t *mp)
347 {
348 }
349
350 static int
351 api_ipsec_sad_entry_add (vat_main_t *vat)
352 {
353   return -1;
354 }
355
356 static void
357 vl_api_ipsec_spd_entry_add_del_reply_t_handler (
358   vl_api_ipsec_spd_entry_add_del_reply_t *mp)
359 {
360 }
361
362 static void
363 vl_api_ipsec_spd_entry_add_del_v2_reply_t_handler (
364   vl_api_ipsec_spd_entry_add_del_v2_reply_t *mp)
365 {
366 }
367
368 static int
369 api_ipsec_spds_dump (vat_main_t *vam)
370 {
371   return -1;
372 }
373
374 static int
375 api_ipsec_itf_dump (vat_main_t *vam)
376 {
377   return -1;
378 }
379
380 static void
381 vl_api_ipsec_sa_v3_details_t_handler (vl_api_ipsec_sa_v3_details_t *mp)
382 {
383 }
384
385 static int
386 api_ipsec_spd_interface_dump (vat_main_t *vat)
387 {
388   return -1;
389 }
390
391 static void
392 vl_api_ipsec_sa_v2_details_t_handler (vl_api_ipsec_sa_v2_details_t *mp)
393 {
394 }
395
396 static int
397 api_ipsec_sa_v2_dump (vat_main_t *mp)
398 {
399   return -1;
400 }
401
402 static int
403 api_ipsec_sa_dump (vat_main_t *vam)
404 {
405   unformat_input_t *i = vam->input;
406   vl_api_ipsec_sa_dump_t *mp;
407   vl_api_control_ping_t *mp_ping;
408   u32 sa_id = ~0;
409   int ret;
410
411   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
412     {
413       if (unformat (i, "sa_id %d", &sa_id))
414         ;
415       else
416         {
417           clib_warning ("parse error '%U'", format_unformat_error, i);
418           return -99;
419         }
420     }
421
422   M (IPSEC_SA_DUMP, mp);
423
424   mp->sa_id = ntohl (sa_id);
425
426   S (mp);
427
428   /* Use a control ping for synchronization */
429   PING (&ipsec_test_main, mp_ping);
430   S (mp_ping);
431
432   W (ret);
433   return ret;
434 }
435
436 static void
437 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t *mp)
438 {
439   vat_main_t *vam = &vat_main;
440
441   print (vam->ofp,
442          "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
443          "crypto_key %U integ_alg %u integ_key %U flags %x "
444          "tunnel_src_addr %U tunnel_dst_addr %U "
445          "salt %u seq_outbound %lu last_seq_inbound %lu "
446          "replay_window %lu stat_index %u\n",
447          ntohl (mp->entry.sad_id), ntohl (mp->sw_if_index),
448          ntohl (mp->entry.spi), ntohl (mp->entry.protocol),
449          ntohl (mp->entry.crypto_algorithm), format_hex_bytes,
450          mp->entry.crypto_key.data, mp->entry.crypto_key.length,
451          ntohl (mp->entry.integrity_algorithm), format_hex_bytes,
452          mp->entry.integrity_key.data, mp->entry.integrity_key.length,
453          ntohl (mp->entry.flags), format_vl_api_address, &mp->entry.tunnel_src,
454          format_vl_api_address, &mp->entry.tunnel_dst, ntohl (mp->salt),
455          clib_net_to_host_u64 (mp->seq_outbound),
456          clib_net_to_host_u64 (mp->last_seq_inbound),
457          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
458 }
459
460 static int
461 api_ipsec_spd_dump (vat_main_t *vam)
462 {
463   return -1;
464 }
465
466 uword
467 unformat_ipsec_api_crypto_alg (unformat_input_t *input, va_list *args)
468 {
469   u32 *r = va_arg (*args, u32 *);
470
471   if (0)
472     ;
473 #define _(v, f, s) else if (unformat (input, s)) *r = IPSEC_API_CRYPTO_ALG_##f;
474   foreach_ipsec_crypto_alg
475 #undef _
476     else return 0;
477   return 1;
478 }
479
480 uword
481 unformat_ipsec_api_integ_alg (unformat_input_t *input, va_list *args)
482 {
483   u32 *r = va_arg (*args, u32 *);
484
485   if (0)
486     ;
487 #define _(v, f, s) else if (unformat (input, s)) *r = IPSEC_API_INTEG_ALG_##f;
488   foreach_ipsec_integ_alg
489 #undef _
490     else return 0;
491   return 1;
492 }
493
494 static int
495 api_ipsec_sad_entry_add_del (vat_main_t *vam)
496 {
497   unformat_input_t *i = vam->input;
498   vl_api_ipsec_sad_entry_add_del_t *mp;
499   u32 sad_id = 0, spi = 0;
500   u8 *ck = 0, *ik = 0;
501   u8 is_add = 1;
502
503   vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
504   vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
505   vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
506   vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
507   vl_api_address_t tun_src, tun_dst;
508   int ret;
509
510   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
511     {
512       if (unformat (i, "del"))
513         is_add = 0;
514       else if (unformat (i, "sad_id %d", &sad_id))
515         ;
516       else if (unformat (i, "spi %d", &spi))
517         ;
518       else if (unformat (i, "esp"))
519         protocol = IPSEC_API_PROTO_ESP;
520       else if (unformat (i, "tunnel_src %U", unformat_vl_api_address,
521                          &tun_src))
522         {
523           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
524           if (ADDRESS_IP6 == tun_src.af)
525             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
526         }
527       else if (unformat (i, "tunnel_dst %U", unformat_vl_api_address,
528                          &tun_dst))
529         {
530           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
531           if (ADDRESS_IP6 == tun_src.af)
532             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
533         }
534       else if (unformat (i, "crypto_alg %U", unformat_ipsec_api_crypto_alg,
535                          &crypto_alg))
536         ;
537       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
538         ;
539       else if (unformat (i, "integ_alg %U", unformat_ipsec_api_integ_alg,
540                          &integ_alg))
541         ;
542       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
543         ;
544       else
545         {
546           clib_warning ("parse error '%U'", format_unformat_error, i);
547           return -99;
548         }
549     }
550
551   M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
552
553   mp->is_add = is_add;
554   mp->entry.sad_id = ntohl (sad_id);
555   mp->entry.protocol = protocol;
556   mp->entry.spi = ntohl (spi);
557   mp->entry.flags = flags;
558
559   mp->entry.crypto_algorithm = crypto_alg;
560   mp->entry.integrity_algorithm = integ_alg;
561   mp->entry.crypto_key.length = vec_len (ck);
562   mp->entry.integrity_key.length = vec_len (ik);
563
564   if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
565     mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
566
567   if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
568     mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
569
570   if (ck)
571     clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
572   if (ik)
573     clib_memcpy (mp->entry.integrity_key.data, ik,
574                  mp->entry.integrity_key.length);
575
576   if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
577     {
578       clib_memcpy (&mp->entry.tunnel_src, &tun_src,
579                    sizeof (mp->entry.tunnel_src));
580       clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
581                    sizeof (mp->entry.tunnel_dst));
582     }
583
584   S (mp);
585   W (ret);
586   return ret;
587 }
588
589 static int
590 api_ipsec_sad_entry_add_del_v2 (vat_main_t *vam)
591 {
592   return -1;
593 }
594
595 static int
596 api_ipsec_interface_add_del_spd (vat_main_t *vam)
597 {
598   vnet_main_t *vnm = vnet_get_main ();
599   unformat_input_t *i = vam->input;
600   vl_api_ipsec_interface_add_del_spd_t *mp;
601   u32 sw_if_index;
602   u8 sw_if_index_set = 0;
603   u32 spd_id = (u32) ~0;
604   u8 is_add = 1;
605   int ret;
606
607   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
608     {
609       if (unformat (i, "del"))
610         is_add = 0;
611       else if (unformat (i, "spd_id %d", &spd_id))
612         ;
613       else if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
614                          &sw_if_index))
615         sw_if_index_set = 1;
616       else if (unformat (i, "sw_if_index %d", &sw_if_index))
617         sw_if_index_set = 1;
618       else
619         {
620           clib_warning ("parse error '%U'", format_unformat_error, i);
621           return -99;
622         }
623     }
624
625   if (spd_id == (u32) ~0)
626     {
627       errmsg ("spd_id must be set");
628       return -99;
629     }
630
631   if (sw_if_index_set == 0)
632     {
633       errmsg ("missing interface name or sw_if_index");
634       return -99;
635     }
636
637   M (IPSEC_INTERFACE_ADD_DEL_SPD, mp);
638
639   mp->spd_id = ntohl (spd_id);
640   mp->sw_if_index = ntohl (sw_if_index);
641   mp->is_add = is_add;
642
643   S (mp);
644   W (ret);
645   return ret;
646 }
647
648 static int
649 api_ipsec_backend_dump (vat_main_t *vam)
650 {
651   return -1;
652 }
653
654 static int
655 api_ipsec_select_backend (vat_main_t *vam)
656 {
657   return -1;
658 }
659
660 static int
661 api_ipsec_set_async_mode (vat_main_t *vam)
662 {
663   return -1;
664 }
665
666 static int
667 api_ipsec_spd_add_del (vat_main_t *vam)
668 {
669   unformat_input_t *i = vam->input;
670   vl_api_ipsec_spd_add_del_t *mp;
671   u32 spd_id = ~0;
672   u8 is_add = 1;
673   int ret;
674
675   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
676     {
677       if (unformat (i, "spd_id %d", &spd_id))
678         ;
679       else if (unformat (i, "del"))
680         is_add = 0;
681       else
682         {
683           clib_warning ("parse error '%U'", format_unformat_error, i);
684           return -99;
685         }
686     }
687   if (spd_id == ~0)
688     {
689       errmsg ("spd_id must be set");
690       return -99;
691     }
692
693   M (IPSEC_SPD_ADD_DEL, mp);
694
695   mp->spd_id = ntohl (spd_id);
696   mp->is_add = is_add;
697
698   S (mp);
699   W (ret);
700   return ret;
701 }
702
703 #include <vnet/ipsec/ipsec.api_test.c>
704
705 /*
706  * Local Variables:
707  * eval: (c-set-style "gnu")
708  * End:
709  */