ipsec: add udp-encap option to debug cli commands
[vpp.git] / src / vnet / ipsec / ipsec_cli.c
1 /*
2  * decap.c : IPSec tunnel support
3  *
4  * Copyright (c) 2015 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <vnet/vnet.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/interface.h>
22
23 #include <vnet/ipsec/ipsec.h>
24
25 static clib_error_t *
26 set_interface_spd_command_fn (vlib_main_t * vm,
27                               unformat_input_t * input,
28                               vlib_cli_command_t * cmd)
29 {
30   unformat_input_t _line_input, *line_input = &_line_input;
31   ipsec_main_t *im = &ipsec_main;
32   u32 sw_if_index = (u32) ~ 0;
33   u32 spd_id;
34   int is_add = 1;
35   clib_error_t *error = NULL;
36
37   if (!unformat_user (input, unformat_line_input, line_input))
38     return 0;
39
40   if (unformat
41       (line_input, "%U %u", unformat_vnet_sw_interface, im->vnet_main,
42        &sw_if_index, &spd_id))
43     ;
44   else if (unformat (line_input, "del"))
45     is_add = 0;
46   else
47     {
48       error = clib_error_return (0, "parse error: '%U'",
49                                  format_unformat_error, line_input);
50       goto done;
51     }
52
53   ipsec_set_interface_spd (vm, sw_if_index, spd_id, is_add);
54
55 done:
56   unformat_free (line_input);
57
58   return error;
59 }
60
61 /* *INDENT-OFF* */
62 VLIB_CLI_COMMAND (set_interface_spd_command, static) = {
63     .path = "set interface ipsec spd",
64     .short_help =
65     "set interface ipsec spd <int> <id>",
66     .function = set_interface_spd_command_fn,
67 };
68 /* *INDENT-ON* */
69
70 static clib_error_t *
71 ipsec_sa_add_del_command_fn (vlib_main_t * vm,
72                              unformat_input_t * input,
73                              vlib_cli_command_t * cmd)
74 {
75   ipsec_main_t *im = &ipsec_main;
76   unformat_input_t _line_input, *line_input = &_line_input;
77   ipsec_sa_t sa;
78   int is_add = ~0;
79   u8 *ck = 0, *ik = 0;
80   clib_error_t *error = NULL;
81
82   memset (&sa, 0, sizeof (sa));
83
84   if (!unformat_user (input, unformat_line_input, line_input))
85     return 0;
86
87   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
88     {
89       if (unformat (line_input, "add %u", &sa.id))
90         is_add = 1;
91       else if (unformat (line_input, "del %u", &sa.id))
92         is_add = 0;
93       else if (unformat (line_input, "spi %u", &sa.spi))
94         ;
95       else if (unformat (line_input, "esp"))
96         sa.protocol = IPSEC_PROTOCOL_ESP;
97       else if (unformat (line_input, "ah"))
98         {
99           sa.protocol = IPSEC_PROTOCOL_AH;
100         }
101       else
102         if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
103         sa.crypto_key_len = vec_len (ck);
104       else
105         if (unformat
106             (line_input, "crypto-alg %U", unformat_ipsec_crypto_alg,
107              &sa.crypto_alg))
108         {
109           if (sa.crypto_alg < IPSEC_CRYPTO_ALG_NONE ||
110               sa.crypto_alg >= IPSEC_CRYPTO_N_ALG)
111             {
112               error = clib_error_return (0, "unsupported crypto-alg: '%U'",
113                                          format_ipsec_crypto_alg,
114                                          sa.crypto_alg);
115               goto done;
116             }
117         }
118       else
119         if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
120         sa.integ_key_len = vec_len (ik);
121       else if (unformat (line_input, "integ-alg %U", unformat_ipsec_integ_alg,
122                          &sa.integ_alg))
123         {
124           if (sa.integ_alg < IPSEC_INTEG_ALG_NONE ||
125               sa.integ_alg >= IPSEC_INTEG_N_ALG)
126             {
127               error = clib_error_return (0, "unsupported integ-alg: '%U'",
128                                          format_ipsec_integ_alg,
129                                          sa.integ_alg);
130               goto done;
131             }
132         }
133       else if (unformat (line_input, "tunnel-src %U",
134                          unformat_ip4_address, &sa.tunnel_src_addr.ip4))
135         sa.is_tunnel = 1;
136       else if (unformat (line_input, "tunnel-dst %U",
137                          unformat_ip4_address, &sa.tunnel_dst_addr.ip4))
138         sa.is_tunnel = 1;
139       else if (unformat (line_input, "tunnel-src %U",
140                          unformat_ip6_address, &sa.tunnel_src_addr.ip6))
141         {
142           sa.is_tunnel = 1;
143           sa.is_tunnel_ip6 = 1;
144         }
145       else if (unformat (line_input, "tunnel-dst %U",
146                          unformat_ip6_address, &sa.tunnel_dst_addr.ip6))
147         {
148           sa.is_tunnel = 1;
149           sa.is_tunnel_ip6 = 1;
150         }
151       else if (unformat (line_input, "udp-encap"))
152         {
153           sa.udp_encap = 1;
154         }
155       else
156         {
157           error = clib_error_return (0, "parse error: '%U'",
158                                      format_unformat_error, line_input);
159           goto done;
160         }
161     }
162
163   if (sa.crypto_key_len > sizeof (sa.crypto_key))
164     sa.crypto_key_len = sizeof (sa.crypto_key);
165
166   if (sa.integ_key_len > sizeof (sa.integ_key))
167     sa.integ_key_len = sizeof (sa.integ_key);
168
169   if (ck)
170     strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
171
172   if (ik)
173     strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
174
175   if (is_add)
176     {
177       ASSERT (im->cb.check_support_cb);
178       error = im->cb.check_support_cb (&sa);
179       if (error)
180         goto done;
181     }
182
183   ipsec_add_del_sa (vm, &sa, is_add);
184
185 done:
186   unformat_free (line_input);
187
188   return error;
189 }
190
191 /* *INDENT-OFF* */
192 VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
193     .path = "ipsec sa",
194     .short_help =
195     "ipsec sa [add|del]",
196     .function = ipsec_sa_add_del_command_fn,
197 };
198 /* *INDENT-ON* */
199
200 static clib_error_t *
201 ipsec_spd_add_del_command_fn (vlib_main_t * vm,
202                               unformat_input_t * input,
203                               vlib_cli_command_t * cmd)
204 {
205   unformat_input_t _line_input, *line_input = &_line_input;
206   u32 spd_id = ~0;
207   int is_add = ~0;
208   clib_error_t *error = NULL;
209
210   if (!unformat_user (input, unformat_line_input, line_input))
211     return 0;
212
213   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
214     {
215       if (unformat (line_input, "add"))
216         is_add = 1;
217       else if (unformat (line_input, "del"))
218         is_add = 0;
219       else if (unformat (line_input, "%u", &spd_id))
220         ;
221       else
222         {
223           error = clib_error_return (0, "parse error: '%U'",
224                                      format_unformat_error, line_input);
225           goto done;
226         }
227     }
228
229   if (spd_id == ~0)
230     {
231       error = clib_error_return (0, "please specify SPD ID");
232       goto done;
233     }
234
235   ipsec_add_del_spd (vm, spd_id, is_add);
236
237 done:
238   unformat_free (line_input);
239
240   return error;
241 }
242
243 /* *INDENT-OFF* */
244 VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
245     .path = "ipsec spd",
246     .short_help =
247     "ipsec spd [add|del] <id>",
248     .function = ipsec_spd_add_del_command_fn,
249 };
250 /* *INDENT-ON* */
251
252
253 static clib_error_t *
254 ipsec_policy_add_del_command_fn (vlib_main_t * vm,
255                                  unformat_input_t * input,
256                                  vlib_cli_command_t * cmd)
257 {
258   unformat_input_t _line_input, *line_input = &_line_input;
259   ipsec_policy_t p;
260   int is_add = 0;
261   int is_ip_any = 1;
262   u32 tmp, tmp2;
263   clib_error_t *error = NULL;
264
265   memset (&p, 0, sizeof (p));
266   p.lport.stop = p.rport.stop = ~0;
267   p.laddr.stop.ip4.as_u32 = p.raddr.stop.ip4.as_u32 = (u32) ~ 0;
268   p.laddr.stop.ip6.as_u64[0] = p.laddr.stop.ip6.as_u64[1] = (u64) ~ 0;
269   p.raddr.stop.ip6.as_u64[0] = p.raddr.stop.ip6.as_u64[1] = (u64) ~ 0;
270
271   if (!unformat_user (input, unformat_line_input, line_input))
272     return 0;
273
274   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
275     {
276       if (unformat (line_input, "add"))
277         is_add = 1;
278       else if (unformat (line_input, "del"))
279         is_add = 0;
280       else if (unformat (line_input, "spd %u", &p.id))
281         ;
282       else if (unformat (line_input, "inbound"))
283         p.is_outbound = 0;
284       else if (unformat (line_input, "outbound"))
285         p.is_outbound = 1;
286       else if (unformat (line_input, "priority %d", &p.priority))
287         ;
288       else if (unformat (line_input, "protocol %u", &tmp))
289         p.protocol = (u8) tmp;
290       else
291         if (unformat
292             (line_input, "action %U", unformat_ipsec_policy_action,
293              &p.policy))
294         {
295           if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
296             {
297               error = clib_error_return (0, "unsupported action: 'resolve'");
298               goto done;
299             }
300         }
301       else if (unformat (line_input, "sa %u", &p.sa_id))
302         ;
303       else if (unformat (line_input, "local-ip-range %U - %U",
304                          unformat_ip4_address, &p.laddr.start.ip4,
305                          unformat_ip4_address, &p.laddr.stop.ip4))
306         is_ip_any = 0;
307       else if (unformat (line_input, "remote-ip-range %U - %U",
308                          unformat_ip4_address, &p.raddr.start.ip4,
309                          unformat_ip4_address, &p.raddr.stop.ip4))
310         is_ip_any = 0;
311       else if (unformat (line_input, "local-ip-range %U - %U",
312                          unformat_ip6_address, &p.laddr.start.ip6,
313                          unformat_ip6_address, &p.laddr.stop.ip6))
314         {
315           p.is_ipv6 = 1;
316           is_ip_any = 0;
317         }
318       else if (unformat (line_input, "remote-ip-range %U - %U",
319                          unformat_ip6_address, &p.raddr.start.ip6,
320                          unformat_ip6_address, &p.raddr.stop.ip6))
321         {
322           p.is_ipv6 = 1;
323           is_ip_any = 0;
324         }
325       else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
326         {
327           p.lport.start = tmp;
328           p.lport.stop = tmp2;
329         }
330       else
331         if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
332         {
333           p.rport.start = tmp;
334           p.rport.stop = tmp2;
335         }
336       else
337         {
338           error = clib_error_return (0, "parse error: '%U'",
339                                      format_unformat_error, line_input);
340           goto done;
341         }
342     }
343
344   /* Check if SA is for IPv6/AH which is not supported. Return error if TRUE. */
345   if (p.sa_id)
346     {
347       uword *p1;
348       ipsec_main_t *im = &ipsec_main;
349       ipsec_sa_t *sa = 0;
350       p1 = hash_get (im->sa_index_by_sa_id, p.sa_id);
351       if (!p1)
352         {
353           error =
354             clib_error_return (0, "SA with index %u not found", p.sa_id);
355           goto done;
356         }
357       sa = pool_elt_at_index (im->sad, p1[0]);
358       if (sa && sa->protocol == IPSEC_PROTOCOL_AH && is_add && p.is_ipv6)
359         {
360           error = clib_error_return (0, "AH not supported for IPV6: '%U'",
361                                      format_unformat_error, line_input);
362           goto done;
363         }
364     }
365   ipsec_add_del_policy (vm, &p, is_add);
366   if (is_ip_any)
367     {
368       p.is_ipv6 = 1;
369       ipsec_add_del_policy (vm, &p, is_add);
370     }
371
372 done:
373   unformat_free (line_input);
374
375   return error;
376 }
377
378 /* *INDENT-OFF* */
379 VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
380     .path = "ipsec policy",
381     .short_help =
382     "ipsec policy [add|del] spd <id> priority <n> ",
383     .function = ipsec_policy_add_del_command_fn,
384 };
385 /* *INDENT-ON* */
386
387 static clib_error_t *
388 set_ipsec_sa_key_command_fn (vlib_main_t * vm,
389                              unformat_input_t * input,
390                              vlib_cli_command_t * cmd)
391 {
392   unformat_input_t _line_input, *line_input = &_line_input;
393   ipsec_sa_t sa;
394   u8 *ck = 0, *ik = 0;
395   clib_error_t *error = NULL;
396
397   memset (&sa, 0, sizeof (sa));
398
399   if (!unformat_user (input, unformat_line_input, line_input))
400     return 0;
401
402   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
403     {
404       if (unformat (line_input, "%u", &sa.id))
405         ;
406       else
407         if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
408         sa.crypto_key_len = vec_len (ck);
409       else
410         if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
411         sa.integ_key_len = vec_len (ik);
412       else
413         {
414           error = clib_error_return (0, "parse error: '%U'",
415                                      format_unformat_error, line_input);
416           goto done;
417         }
418     }
419
420   if (sa.crypto_key_len > sizeof (sa.crypto_key))
421     sa.crypto_key_len = sizeof (sa.crypto_key);
422
423   if (sa.integ_key_len > sizeof (sa.integ_key))
424     sa.integ_key_len = sizeof (sa.integ_key);
425
426   if (ck)
427     strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
428
429   if (ik)
430     strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
431
432   ipsec_set_sa_key (vm, &sa);
433
434 done:
435   unformat_free (line_input);
436
437   return error;
438 }
439
440 /* *INDENT-OFF* */
441 VLIB_CLI_COMMAND (set_ipsec_sa_key_command, static) = {
442     .path = "set ipsec sa",
443     .short_help =
444     "set ipsec sa <id> crypto-key <key> integ-key <key>",
445     .function = set_ipsec_sa_key_command_fn,
446 };
447 /* *INDENT-ON* */
448
449 static clib_error_t *
450 show_ipsec_command_fn (vlib_main_t * vm,
451                        unformat_input_t * input, vlib_cli_command_t * cmd)
452 {
453   ipsec_spd_t *spd;
454   ipsec_sa_t *sa;
455   ipsec_policy_t *p;
456   ipsec_main_t *im = &ipsec_main;
457   u32 *i;
458   ipsec_tunnel_if_t *t;
459   vnet_hw_interface_t *hi;
460   u8 *protocol = NULL;
461   u8 *policy = NULL;
462
463   /* *INDENT-OFF* */
464   pool_foreach (sa, im->sad, ({
465     if (sa->id) {
466       vlib_cli_output(vm, "sa %u spi %u mode %s protocol %s%s", sa->id, sa->spi,
467                       sa->is_tunnel ? "tunnel" : "transport",
468                       sa->protocol ? "esp" : "ah",
469                       sa->udp_encap ? " udp-encap-enabled" : "");
470       if (sa->protocol == IPSEC_PROTOCOL_ESP) {
471         vlib_cli_output(vm, "  crypto alg %U%s%U integrity alg %U%s%U",
472                         format_ipsec_crypto_alg, sa->crypto_alg,
473                         sa->crypto_alg ? " key " : "",
474                         format_hex_bytes, sa->crypto_key, sa->crypto_key_len,
475                         format_ipsec_integ_alg, sa->integ_alg,
476                         sa->integ_alg ? " key " : "",
477                         format_hex_bytes, sa->integ_key, sa->integ_key_len);
478       }
479       if (sa->is_tunnel && sa->is_tunnel_ip6) {
480         vlib_cli_output(vm, "  tunnel src %U dst %U",
481                         format_ip6_address, &sa->tunnel_src_addr.ip6,
482                         format_ip6_address, &sa->tunnel_dst_addr.ip6);
483       } else if (sa->is_tunnel) {
484         vlib_cli_output(vm, "  tunnel src %U dst %U",
485                         format_ip4_address, &sa->tunnel_src_addr.ip4,
486                         format_ip4_address, &sa->tunnel_dst_addr.ip4);
487       }
488     }
489   }));
490   /* *INDENT-ON* */
491
492   /* *INDENT-OFF* */
493   pool_foreach (spd, im->spds, ({
494     vlib_cli_output(vm, "spd %u", spd->id);
495
496     vlib_cli_output(vm, " outbound policies");
497     vec_foreach(i, spd->ipv4_outbound_policies)
498       {
499         p = pool_elt_at_index(spd->policies, *i);
500         vec_reset_length(protocol);
501         vec_reset_length(policy);
502         if (p->protocol) {
503           protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
504         } else {
505           protocol = format(protocol, "any");
506         }
507         if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
508           policy = format(policy, " sa %u", p->sa_id);
509         }
510
511         vlib_cli_output(vm, "  priority %d action %U protocol %v%v",
512                         p->priority, format_ipsec_policy_action, p->policy,
513                         protocol, policy);
514         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
515                         format_ip4_address, &p->laddr.start.ip4,
516                         format_ip4_address, &p->laddr.stop.ip4,
517                         p->lport.start, p->lport.stop);
518         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
519                         format_ip4_address, &p->raddr.start.ip4,
520                         format_ip4_address, &p->raddr.stop.ip4,
521                         p->rport.start, p->rport.stop);
522         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
523                         p->counter.bytes);
524       };
525     vec_foreach(i, spd->ipv6_outbound_policies)
526       {
527         p = pool_elt_at_index(spd->policies, *i);
528         vec_reset_length(protocol);
529         vec_reset_length(policy);
530         if (p->protocol) {
531           protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
532         } else {
533           protocol = format(protocol, "any");
534         }
535         if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
536           policy = format(policy, " sa %u", p->sa_id);
537         }
538         vlib_cli_output(vm, "  priority %d action %U protocol %v%v",
539                         p->priority, format_ipsec_policy_action, p->policy,
540                         protocol, policy);
541         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
542                         format_ip6_address, &p->laddr.start.ip6,
543                         format_ip6_address, &p->laddr.stop.ip6,
544                         p->lport.start, p->lport.stop);
545         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
546                         format_ip6_address, &p->raddr.start.ip6,
547                         format_ip6_address, &p->raddr.stop.ip6,
548                         p->rport.start, p->rport.stop);
549         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
550                         p->counter.bytes);
551       };
552     vlib_cli_output(vm, " inbound policies");
553     vec_foreach(i, spd->ipv4_inbound_protect_policy_indices)
554       {
555         p = pool_elt_at_index(spd->policies, *i);
556         vec_reset_length(protocol);
557         vec_reset_length(policy);
558         if (p->protocol) {
559           protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
560         } else {
561           protocol = format(protocol, "any");
562         }
563         if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
564           policy = format(policy, " sa %u", p->sa_id);
565         }
566         vlib_cli_output(vm, "  priority %d action %U protocol %v%v",
567                         p->priority, format_ipsec_policy_action, p->policy,
568                         protocol, policy);
569         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
570                         format_ip4_address, &p->laddr.start.ip4,
571                         format_ip4_address, &p->laddr.stop.ip4,
572                         p->lport.start, p->lport.stop);
573         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
574                         format_ip4_address, &p->raddr.start.ip4,
575                         format_ip4_address, &p->raddr.stop.ip4,
576                         p->rport.start, p->rport.stop);
577         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
578                         p->counter.bytes);
579       };
580     vec_foreach(i, spd->ipv4_inbound_policy_discard_and_bypass_indices)
581       {
582         p = pool_elt_at_index(spd->policies, *i);
583         vec_reset_length(protocol);
584         vec_reset_length(policy);
585         if (p->protocol) {
586           protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
587         } else {
588           protocol = format(protocol, "any");
589         }
590         if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
591           policy = format(policy, " sa %u", p->sa_id);
592         }
593         vlib_cli_output(vm, "  priority %d action %U protocol %v%v",
594                         p->priority, format_ipsec_policy_action, p->policy,
595                         protocol, policy);
596         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
597                         format_ip4_address, &p->laddr.start.ip4,
598                         format_ip4_address, &p->laddr.stop.ip4,
599                         p->lport.start, p->lport.stop);
600         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
601                         format_ip4_address, &p->raddr.start.ip4,
602                         format_ip4_address, &p->raddr.stop.ip4,
603                         p->rport.start, p->rport.stop);
604         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
605                         p->counter.bytes);
606       };
607     vec_foreach(i, spd->ipv6_inbound_protect_policy_indices)
608       {
609         p = pool_elt_at_index(spd->policies, *i);
610         vec_reset_length(protocol);
611         vec_reset_length(policy);
612         if (p->protocol) {
613           protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
614         } else {
615           protocol = format(protocol, "any");
616         }
617         if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
618           policy = format(policy, " sa %u", p->sa_id);
619         }
620         vlib_cli_output(vm, "  priority %d action %U protocol %v%v",
621                         p->priority, format_ipsec_policy_action, p->policy,
622                         protocol, policy);
623         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
624                         format_ip6_address, &p->laddr.start.ip6,
625                         format_ip6_address, &p->laddr.stop.ip6,
626                         p->lport.start, p->lport.stop);
627         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
628                         format_ip6_address, &p->raddr.start.ip6,
629                         format_ip6_address, &p->raddr.stop.ip6,
630                         p->rport.start, p->rport.stop);
631         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
632                         p->counter.bytes);
633       };
634     vec_foreach(i, spd->ipv6_inbound_policy_discard_and_bypass_indices)
635       {
636         p = pool_elt_at_index(spd->policies, *i);
637         vec_reset_length(protocol);
638         vec_reset_length(policy);
639         if (p->protocol) {
640           protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
641         } else {
642           protocol = format(protocol, "any");
643         }
644         if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
645           policy = format(policy, " sa %u", p->sa_id);
646         }
647         vlib_cli_output(vm, "  priority %d action %U protocol %v%v",
648                         p->priority, format_ipsec_policy_action, p->policy,
649                         protocol, policy);
650         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
651                         format_ip6_address, &p->laddr.start.ip6,
652                         format_ip6_address, &p->laddr.stop.ip6,
653                         p->lport.start, p->lport.stop);
654         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
655                         format_ip6_address, &p->raddr.start.ip6,
656                         format_ip6_address, &p->raddr.stop.ip6,
657                         p->rport.start, p->rport.stop);
658         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
659                         p->counter.bytes);
660       };
661   }));
662   /* *INDENT-ON* */
663
664   vlib_cli_output (vm, "tunnel interfaces");
665   /* *INDENT-OFF* */
666   pool_foreach (t, im->tunnel_interfaces, ({
667     if (t->hw_if_index == ~0)
668       continue;
669     hi = vnet_get_hw_interface (im->vnet_main, t->hw_if_index);
670     vlib_cli_output(vm, "  %s seq", hi->name);
671     sa = pool_elt_at_index(im->sad, t->output_sa_index);
672     vlib_cli_output(vm, "   seq %u seq-hi %u esn %u anti-replay %u udp-encap %u",
673                     sa->seq, sa->seq_hi, sa->use_esn, sa->use_anti_replay, sa->udp_encap);
674     vlib_cli_output(vm, "   local-spi %u local-ip %U", sa->spi,
675                     format_ip4_address, &sa->tunnel_src_addr.ip4);
676     vlib_cli_output(vm, "   local-crypto %U %U",
677                     format_ipsec_crypto_alg, sa->crypto_alg,
678                     format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
679     vlib_cli_output(vm, "   local-integrity %U %U",
680                     format_ipsec_integ_alg, sa->integ_alg,
681                     format_hex_bytes, sa->integ_key, sa->integ_key_len);
682     sa = pool_elt_at_index(im->sad, t->input_sa_index);
683     vlib_cli_output(vm, "   last-seq %u last-seq-hi %u esn %u anti-replay %u window %U",
684                     sa->last_seq, sa->last_seq_hi, sa->use_esn,
685                     sa->use_anti_replay,
686                     format_ipsec_replay_window, sa->replay_window);
687     vlib_cli_output(vm, "   remote-spi %u remote-ip %U", sa->spi,
688                     format_ip4_address, &sa->tunnel_src_addr.ip4);
689     vlib_cli_output(vm, "   remote-crypto %U %U",
690                     format_ipsec_crypto_alg, sa->crypto_alg,
691                     format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
692     vlib_cli_output(vm, "   remote-integrity %U %U",
693                     format_ipsec_integ_alg, sa->integ_alg,
694                     format_hex_bytes, sa->integ_key, sa->integ_key_len);
695   }));
696   vec_free(policy);
697   vec_free(protocol);
698   /* *INDENT-ON* */
699   return 0;
700 }
701
702 /* *INDENT-OFF* */
703 VLIB_CLI_COMMAND (show_ipsec_command, static) = {
704     .path = "show ipsec",
705     .short_help = "show ipsec",
706     .function = show_ipsec_command_fn,
707 };
708 /* *INDENT-ON* */
709
710 static clib_error_t *
711 clear_ipsec_counters_command_fn (vlib_main_t * vm,
712                                  unformat_input_t * input,
713                                  vlib_cli_command_t * cmd)
714 {
715   ipsec_main_t *im = &ipsec_main;
716   ipsec_spd_t *spd;
717   ipsec_policy_t *p;
718
719   /* *INDENT-OFF* */
720   pool_foreach (spd, im->spds, ({
721     pool_foreach(p, spd->policies, ({
722       p->counter.packets = p->counter.bytes = 0;
723     }));
724   }));
725   /* *INDENT-ON* */
726
727   return 0;
728 }
729
730 /* *INDENT-OFF* */
731 VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
732     .path = "clear ipsec counters",
733     .short_help = "clear ipsec counters",
734     .function = clear_ipsec_counters_command_fn,
735 };
736 /* *INDENT-ON* */
737
738 static clib_error_t *
739 create_ipsec_tunnel_command_fn (vlib_main_t * vm,
740                                 unformat_input_t * input,
741                                 vlib_cli_command_t * cmd)
742 {
743   unformat_input_t _line_input, *line_input = &_line_input;
744   ipsec_add_del_tunnel_args_t a;
745   int rv;
746   u32 num_m_args = 0;
747   clib_error_t *error = NULL;
748
749   memset (&a, 0, sizeof (a));
750   a.is_add = 1;
751
752   /* Get a line of input. */
753   if (!unformat_user (input, unformat_line_input, line_input))
754     return 0;
755
756   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
757     {
758       if (unformat
759           (line_input, "local-ip %U", unformat_ip4_address, &a.local_ip))
760         num_m_args++;
761       else
762         if (unformat
763             (line_input, "remote-ip %U", unformat_ip4_address, &a.remote_ip))
764         num_m_args++;
765       else if (unformat (line_input, "local-spi %u", &a.local_spi))
766         num_m_args++;
767       else if (unformat (line_input, "remote-spi %u", &a.remote_spi))
768         num_m_args++;
769       else if (unformat (line_input, "instance %u", &a.show_instance))
770         a.renumber = 1;
771       else if (unformat (line_input, "del"))
772         a.is_add = 0;
773       else if (unformat (line_input, "udp-encap"))
774         a.udp_encap = 1;
775       else
776         {
777           error = clib_error_return (0, "unknown input `%U'",
778                                      format_unformat_error, line_input);
779           goto done;
780         }
781     }
782
783   if (num_m_args < 4)
784     {
785       error = clib_error_return (0, "mandatory argument(s) missing");
786       goto done;
787     }
788
789   rv = ipsec_add_del_tunnel_if (&a);
790
791   switch (rv)
792     {
793     case 0:
794       break;
795     case VNET_API_ERROR_INVALID_VALUE:
796       if (a.is_add)
797         error = clib_error_return (0,
798                                    "IPSec tunnel interface already exists...");
799       else
800         error = clib_error_return (0, "IPSec tunnel interface not exists...");
801       goto done;
802     default:
803       error = clib_error_return (0, "ipsec_register_interface returned %d",
804                                  rv);
805       goto done;
806     }
807
808 done:
809   unformat_free (line_input);
810
811   return error;
812 }
813
814 /* *INDENT-OFF* */
815 VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
816   .path = "create ipsec tunnel",
817   .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> remote-ip <addr> remote-spi <spi> [instance <inst_num>] [udp-encap]",
818   .function = create_ipsec_tunnel_command_fn,
819 };
820 /* *INDENT-ON* */
821
822 static clib_error_t *
823 set_interface_key_command_fn (vlib_main_t * vm,
824                               unformat_input_t * input,
825                               vlib_cli_command_t * cmd)
826 {
827   unformat_input_t _line_input, *line_input = &_line_input;
828   ipsec_main_t *im = &ipsec_main;
829   ipsec_if_set_key_type_t type = IPSEC_IF_SET_KEY_TYPE_NONE;
830   u32 hw_if_index = (u32) ~ 0;
831   u32 alg;
832   u8 *key = 0;
833   clib_error_t *error = NULL;
834
835   if (!unformat_user (input, unformat_line_input, line_input))
836     return 0;
837
838   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
839     {
840       if (unformat (line_input, "%U",
841                     unformat_vnet_hw_interface, im->vnet_main, &hw_if_index))
842         ;
843       else
844         if (unformat
845             (line_input, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
846         type = IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO;
847       else
848         if (unformat
849             (line_input, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
850         type = IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO;
851       else
852         if (unformat
853             (line_input, "local integ %U", unformat_ipsec_integ_alg, &alg))
854         type = IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG;
855       else
856         if (unformat
857             (line_input, "remote integ %U", unformat_ipsec_integ_alg, &alg))
858         type = IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG;
859       else if (unformat (line_input, "%U", unformat_hex_string, &key))
860         ;
861       else
862         {
863           error = clib_error_return (0, "parse error: '%U'",
864                                      format_unformat_error, line_input);
865           goto done;
866         }
867     }
868
869   if (type == IPSEC_IF_SET_KEY_TYPE_NONE)
870     {
871       error = clib_error_return (0, "unknown key type");
872       goto done;
873     }
874
875   if (alg > 0 && vec_len (key) == 0)
876     {
877       error = clib_error_return (0, "key is not specified");
878       goto done;
879     }
880
881   if (hw_if_index == (u32) ~ 0)
882     {
883       error = clib_error_return (0, "interface not specified");
884       goto done;
885     }
886
887   ipsec_set_interface_key (im->vnet_main, hw_if_index, type, alg, key);
888
889 done:
890   vec_free (key);
891   unformat_free (line_input);
892
893   return error;
894 }
895
896 /* *INDENT-OFF* */
897 VLIB_CLI_COMMAND (set_interface_key_command, static) = {
898     .path = "set interface ipsec key",
899     .short_help =
900     "set interface ipsec key <int> <local|remote> <crypto|integ> <key type> <key>",
901     .function = set_interface_key_command_fn,
902 };
903 /* *INDENT-ON* */
904
905 clib_error_t *
906 ipsec_cli_init (vlib_main_t * vm)
907 {
908   return 0;
909 }
910
911 VLIB_INIT_FUNCTION (ipsec_cli_init);
912
913
914 /*
915  * fd.io coding-style-patch-verification: ON
916  *
917  * Local Variables:
918  * eval: (c-set-style "gnu")
919  * End:
920  */