VPP-635: CLI Memory leak with invalid parameter
[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           error = clib_error_return (0, "unsupported security protocol 'AH'");
101           goto done;
102         }
103       else
104         if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
105         sa.crypto_key_len = vec_len (ck);
106       else
107         if (unformat
108             (line_input, "crypto-alg %U", unformat_ipsec_crypto_alg,
109              &sa.crypto_alg))
110         {
111           if (sa.crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
112               sa.crypto_alg >= IPSEC_CRYPTO_N_ALG)
113             {
114               error = clib_error_return (0, "unsupported crypto-alg: '%U'",
115                                          format_ipsec_crypto_alg,
116                                          sa.crypto_alg);
117               goto done;
118             }
119         }
120       else
121         if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
122         sa.integ_key_len = vec_len (ik);
123       else if (unformat (line_input, "integ-alg %U", unformat_ipsec_integ_alg,
124                          &sa.integ_alg))
125         {
126           if (sa.integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
127               sa.integ_alg >= IPSEC_INTEG_N_ALG)
128             {
129               error = clib_error_return (0, "unsupported integ-alg: '%U'",
130                                          format_ipsec_integ_alg,
131                                          sa.integ_alg);
132               goto done;
133             }
134         }
135       else if (unformat (line_input, "tunnel-src %U",
136                          unformat_ip4_address, &sa.tunnel_src_addr.ip4))
137         sa.is_tunnel = 1;
138       else if (unformat (line_input, "tunnel-dst %U",
139                          unformat_ip4_address, &sa.tunnel_dst_addr.ip4))
140         sa.is_tunnel = 1;
141       else if (unformat (line_input, "tunnel-src %U",
142                          unformat_ip6_address, &sa.tunnel_src_addr.ip6))
143         {
144           sa.is_tunnel = 1;
145           sa.is_tunnel_ip6 = 1;
146         }
147       else if (unformat (line_input, "tunnel-dst %U",
148                          unformat_ip6_address, &sa.tunnel_dst_addr.ip6))
149         {
150           sa.is_tunnel = 1;
151           sa.is_tunnel_ip6 = 1;
152         }
153       else
154         {
155           error = clib_error_return (0, "parse error: '%U'",
156                                      format_unformat_error, line_input);
157           goto done;
158         }
159     }
160
161   if (sa.crypto_key_len > sizeof (sa.crypto_key))
162     sa.crypto_key_len = sizeof (sa.crypto_key);
163
164   if (sa.integ_key_len > sizeof (sa.integ_key))
165     sa.integ_key_len = sizeof (sa.integ_key);
166
167   if (ck)
168     strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
169
170   if (ik)
171     strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
172
173   if (is_add)
174     {
175       ASSERT (im->cb.check_support_cb);
176       error = im->cb.check_support_cb (&sa);
177       if (error)
178         goto done;
179     }
180
181   ipsec_add_del_sa (vm, &sa, is_add);
182
183 done:
184   unformat_free (line_input);
185
186   return error;
187 }
188
189 /* *INDENT-OFF* */
190 VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
191     .path = "ipsec sa",
192     .short_help =
193     "ipsec sa [add|del]",
194     .function = ipsec_sa_add_del_command_fn,
195 };
196 /* *INDENT-ON* */
197
198 static clib_error_t *
199 ipsec_spd_add_del_command_fn (vlib_main_t * vm,
200                               unformat_input_t * input,
201                               vlib_cli_command_t * cmd)
202 {
203   unformat_input_t _line_input, *line_input = &_line_input;
204   u32 spd_id = ~0;
205   int is_add = ~0;
206   clib_error_t *error = NULL;
207
208   if (!unformat_user (input, unformat_line_input, line_input))
209     return 0;
210
211   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
212     {
213       if (unformat (line_input, "add"))
214         is_add = 1;
215       else if (unformat (line_input, "del"))
216         is_add = 0;
217       else if (unformat (line_input, "%u", &spd_id))
218         ;
219       else
220         {
221           error = clib_error_return (0, "parse error: '%U'",
222                                      format_unformat_error, line_input);
223           goto done;
224         }
225     }
226
227   if (spd_id == ~0)
228     {
229       error = clib_error_return (0, "please specify SPD ID");
230       goto done;
231     }
232
233   ipsec_add_del_spd (vm, spd_id, is_add);
234
235 done:
236   unformat_free (line_input);
237
238   return error;
239 }
240
241 /* *INDENT-OFF* */
242 VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
243     .path = "ipsec spd",
244     .short_help =
245     "ipsec spd [add|del] <id>",
246     .function = ipsec_spd_add_del_command_fn,
247 };
248 /* *INDENT-ON* */
249
250
251 static clib_error_t *
252 ipsec_policy_add_del_command_fn (vlib_main_t * vm,
253                                  unformat_input_t * input,
254                                  vlib_cli_command_t * cmd)
255 {
256   unformat_input_t _line_input, *line_input = &_line_input;
257   ipsec_policy_t p;
258   int is_add = 0;
259   int is_ip_any = 1;
260   u32 tmp, tmp2;
261   clib_error_t *error = NULL;
262
263   memset (&p, 0, sizeof (p));
264   p.lport.stop = p.rport.stop = ~0;
265   p.laddr.stop.ip4.as_u32 = p.raddr.stop.ip4.as_u32 = (u32) ~ 0;
266   p.laddr.stop.ip6.as_u64[0] = p.laddr.stop.ip6.as_u64[1] = (u64) ~ 0;
267   p.raddr.stop.ip6.as_u64[0] = p.raddr.stop.ip6.as_u64[1] = (u64) ~ 0;
268
269   if (!unformat_user (input, unformat_line_input, line_input))
270     return 0;
271
272   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
273     {
274       if (unformat (line_input, "add"))
275         is_add = 1;
276       else if (unformat (line_input, "del"))
277         is_add = 0;
278       else if (unformat (line_input, "spd %u", &p.id))
279         ;
280       else if (unformat (line_input, "inbound"))
281         p.is_outbound = 0;
282       else if (unformat (line_input, "outbound"))
283         p.is_outbound = 1;
284       else if (unformat (line_input, "priority %d", &p.priority))
285         ;
286       else if (unformat (line_input, "protocol %u", &tmp))
287         p.protocol = (u8) tmp;
288       else
289         if (unformat
290             (line_input, "action %U", unformat_ipsec_policy_action,
291              &p.policy))
292         {
293           if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
294             {
295               error = clib_error_return (0, "unsupported action: 'resolve'");
296               goto done;
297             }
298         }
299       else if (unformat (line_input, "sa %u", &p.sa_id))
300         ;
301       else if (unformat (line_input, "local-ip-range %U - %U",
302                          unformat_ip4_address, &p.laddr.start.ip4,
303                          unformat_ip4_address, &p.laddr.stop.ip4))
304         is_ip_any = 0;
305       else if (unformat (line_input, "remote-ip-range %U - %U",
306                          unformat_ip4_address, &p.raddr.start.ip4,
307                          unformat_ip4_address, &p.raddr.stop.ip4))
308         is_ip_any = 0;
309       else if (unformat (line_input, "local-ip-range %U - %U",
310                          unformat_ip6_address, &p.laddr.start.ip6,
311                          unformat_ip6_address, &p.laddr.stop.ip6))
312         {
313           p.is_ipv6 = 1;
314           is_ip_any = 0;
315         }
316       else if (unformat (line_input, "remote-ip-range %U - %U",
317                          unformat_ip6_address, &p.raddr.start.ip6,
318                          unformat_ip6_address, &p.raddr.stop.ip6))
319         {
320           p.is_ipv6 = 1;
321           is_ip_any = 0;
322         }
323       else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
324         {
325           p.lport.start = tmp;
326           p.lport.stop = tmp2;
327         }
328       else
329         if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
330         {
331           p.rport.start = tmp;
332           p.rport.stop = tmp2;
333         }
334       else
335         {
336           error = clib_error_return (0, "parse error: '%U'",
337                                      format_unformat_error, line_input);
338           goto done;
339         }
340     }
341
342   ipsec_add_del_policy (vm, &p, is_add);
343   if (is_ip_any)
344     {
345       p.is_ipv6 = 1;
346       ipsec_add_del_policy (vm, &p, is_add);
347     }
348
349 done:
350   unformat_free (line_input);
351
352   return error;
353 }
354
355 /* *INDENT-OFF* */
356 VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
357     .path = "ipsec policy",
358     .short_help =
359     "ipsec policy [add|del] spd <id> priority <n> ",
360     .function = ipsec_policy_add_del_command_fn,
361 };
362 /* *INDENT-ON* */
363
364 static clib_error_t *
365 set_ipsec_sa_key_command_fn (vlib_main_t * vm,
366                              unformat_input_t * input,
367                              vlib_cli_command_t * cmd)
368 {
369   unformat_input_t _line_input, *line_input = &_line_input;
370   ipsec_sa_t sa;
371   u8 *ck = 0, *ik = 0;
372   clib_error_t *error = NULL;
373
374   memset (&sa, 0, sizeof (sa));
375
376   if (!unformat_user (input, unformat_line_input, line_input))
377     return 0;
378
379   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
380     {
381       if (unformat (line_input, "%u", &sa.id))
382         ;
383       else
384         if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
385         sa.crypto_key_len = vec_len (ck);
386       else
387         if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
388         sa.integ_key_len = vec_len (ik);
389       else
390         {
391           error = clib_error_return (0, "parse error: '%U'",
392                                      format_unformat_error, line_input);
393           goto done;
394         }
395     }
396
397   if (sa.crypto_key_len > sizeof (sa.crypto_key))
398     sa.crypto_key_len = sizeof (sa.crypto_key);
399
400   if (sa.integ_key_len > sizeof (sa.integ_key))
401     sa.integ_key_len = sizeof (sa.integ_key);
402
403   if (ck)
404     strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
405
406   if (ik)
407     strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
408
409   ipsec_set_sa_key (vm, &sa);
410
411 done:
412   unformat_free (line_input);
413
414   return error;
415 }
416
417 /* *INDENT-OFF* */
418 VLIB_CLI_COMMAND (set_ipsec_sa_key_command, static) = {
419     .path = "set ipsec sa",
420     .short_help =
421     "set ipsec sa <id> crypto-key <key> integ-key <key>",
422     .function = set_ipsec_sa_key_command_fn,
423 };
424 /* *INDENT-ON* */
425
426 static clib_error_t *
427 show_ipsec_command_fn (vlib_main_t * vm,
428                        unformat_input_t * input, vlib_cli_command_t * cmd)
429 {
430   ipsec_spd_t *spd;
431   ipsec_sa_t *sa;
432   ipsec_policy_t *p;
433   ipsec_main_t *im = &ipsec_main;
434   u32 *i;
435   ipsec_tunnel_if_t *t;
436   vnet_hw_interface_t *hi;
437
438   /* *INDENT-OFF* */
439   pool_foreach (sa, im->sad, ({
440     if (sa->id) {
441       vlib_cli_output(vm, "sa %u spi %u mode %s protocol %s", sa->id, sa->spi,
442                       sa->is_tunnel ? "tunnel" : "transport",
443                       sa->protocol ? "esp" : "ah");
444       if (sa->protocol == IPSEC_PROTOCOL_ESP) {
445         vlib_cli_output(vm, "  crypto alg %U%s%U integrity alg %U%s%U",
446                         format_ipsec_crypto_alg, sa->crypto_alg,
447                         sa->crypto_alg ? " key " : "",
448                         format_hex_bytes, sa->crypto_key, sa->crypto_key_len,
449                         format_ipsec_integ_alg, sa->integ_alg,
450                         sa->integ_alg ? " key " : "",
451                         format_hex_bytes, sa->integ_key, sa->integ_key_len);
452       }
453       if (sa->is_tunnel && sa->is_tunnel_ip6) {
454         vlib_cli_output(vm, "  tunnel src %U dst %U",
455                         format_ip6_address, &sa->tunnel_src_addr.ip6,
456                         format_ip6_address, &sa->tunnel_dst_addr.ip6);
457       } else if (sa->is_tunnel) {
458         vlib_cli_output(vm, "  tunnel src %U dst %U",
459                         format_ip4_address, &sa->tunnel_src_addr.ip4,
460                         format_ip4_address, &sa->tunnel_dst_addr.ip4);
461       }
462     }
463   }));
464   /* *INDENT-ON* */
465
466   /* *INDENT-OFF* */
467   pool_foreach (spd, im->spds, ({
468     vlib_cli_output(vm, "spd %u", spd->id);
469
470     vlib_cli_output(vm, " outbound policies");
471     vec_foreach(i, spd->ipv4_outbound_policies)
472       {
473         p = pool_elt_at_index(spd->policies, *i);
474         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
475                         p->priority,
476                         format_ipsec_policy_action, p->policy,
477                         p->protocol ?
478                           format(0, "%U", format_ip_protocol, p->protocol) :
479                           (u8 *) "any",
480                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
481                           format(0, " sa %u", p->sa_id) :
482                           (u8 *) "");
483         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
484                         format_ip4_address, &p->laddr.start.ip4,
485                         format_ip4_address, &p->laddr.stop.ip4,
486                         p->lport.start, p->lport.stop);
487         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
488                         format_ip4_address, &p->raddr.start.ip4,
489                         format_ip4_address, &p->raddr.stop.ip4,
490                         p->rport.start, p->rport.stop);
491         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
492                         p->counter.bytes);
493       };
494     vec_foreach(i, spd->ipv6_outbound_policies)
495       {
496         p = pool_elt_at_index(spd->policies, *i);
497         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
498                         p->priority,
499                         format_ipsec_policy_action, p->policy,
500                         p->protocol ?
501                           format(0, "%U", format_ip_protocol, p->protocol) :
502                           (u8 *) "any",
503                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
504                           format(0, " sa %u", p->sa_id) :
505                           (u8 *) "");
506         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
507                         format_ip6_address, &p->laddr.start.ip6,
508                         format_ip6_address, &p->laddr.stop.ip6,
509                         p->lport.start, p->lport.stop);
510         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
511                         format_ip6_address, &p->raddr.start.ip6,
512                         format_ip6_address, &p->raddr.stop.ip6,
513                         p->rport.start, p->rport.stop);
514         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
515                         p->counter.bytes);
516       };
517     vlib_cli_output(vm, " inbound policies");
518     vec_foreach(i, spd->ipv4_inbound_protect_policy_indices)
519       {
520         p = pool_elt_at_index(spd->policies, *i);
521         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
522                         p->priority,
523                         format_ipsec_policy_action, p->policy,
524                         p->protocol ?
525                           format(0, "%U", format_ip_protocol, p->protocol) :
526                           (u8 *) "any",
527                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
528                           format(0, " sa %u", p->sa_id) :
529                           (u8 *) "");
530         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
531                         format_ip4_address, &p->laddr.start.ip4,
532                         format_ip4_address, &p->laddr.stop.ip4,
533                         p->lport.start, p->lport.stop);
534         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
535                         format_ip4_address, &p->raddr.start.ip4,
536                         format_ip4_address, &p->raddr.stop.ip4,
537                         p->rport.start, p->rport.stop);
538         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
539                         p->counter.bytes);
540       };
541     vec_foreach(i, spd->ipv4_inbound_policy_discard_and_bypass_indices)
542       {
543         p = pool_elt_at_index(spd->policies, *i);
544         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
545                         p->priority,
546                         format_ipsec_policy_action, p->policy,
547                         p->protocol ?
548                           format(0, "%U", format_ip_protocol, p->protocol) :
549                           (u8 *) "any",
550                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
551                           format(0, " sa %u", p->sa_id) :
552                           (u8 *) "");
553         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
554                         format_ip4_address, &p->laddr.start.ip4,
555                         format_ip4_address, &p->laddr.stop.ip4,
556                         p->lport.start, p->lport.stop);
557         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
558                         format_ip4_address, &p->raddr.start.ip4,
559                         format_ip4_address, &p->raddr.stop.ip4,
560                         p->rport.start, p->rport.stop);
561         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
562                         p->counter.bytes);
563       };
564     vec_foreach(i, spd->ipv6_inbound_protect_policy_indices)
565       {
566         p = pool_elt_at_index(spd->policies, *i);
567         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
568                         p->priority,
569                         format_ipsec_policy_action, p->policy,
570                         p->protocol ?
571                           format(0, "%U", format_ip_protocol, p->protocol) :
572                           (u8 *) "any",
573                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
574                           format(0, " sa %u", p->sa_id) :
575                           (u8 *) "");
576         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
577                         format_ip6_address, &p->laddr.start.ip6,
578                         format_ip6_address, &p->laddr.stop.ip6,
579                         p->lport.start, p->lport.stop);
580         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
581                         format_ip6_address, &p->raddr.start.ip6,
582                         format_ip6_address, &p->raddr.stop.ip6,
583                         p->rport.start, p->rport.stop);
584         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
585                         p->counter.bytes);
586       };
587     vec_foreach(i, spd->ipv6_inbound_policy_discard_and_bypass_indices)
588       {
589         p = pool_elt_at_index(spd->policies, *i);
590         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
591                         p->priority,
592                         format_ipsec_policy_action, p->policy,
593                         p->protocol ?
594                           format(0, "%U", format_ip_protocol, p->protocol) :
595                           (u8 *) "any",
596                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
597                           format(0, " sa %u", p->sa_id) :
598                           (u8 *) "");
599         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
600                         format_ip6_address, &p->laddr.start.ip6,
601                         format_ip6_address, &p->laddr.stop.ip6,
602                         p->lport.start, p->lport.stop);
603         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
604                         format_ip6_address, &p->raddr.start.ip6,
605                         format_ip6_address, &p->raddr.stop.ip6,
606                         p->rport.start, p->rport.stop);
607         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
608                         p->counter.bytes);
609       };
610   }));
611   /* *INDENT-ON* */
612
613   vlib_cli_output (vm, "tunnel interfaces");
614   /* *INDENT-OFF* */
615   pool_foreach (t, im->tunnel_interfaces, ({
616     if (t->hw_if_index == ~0)
617       continue;
618     hi = vnet_get_hw_interface (im->vnet_main, t->hw_if_index);
619     vlib_cli_output(vm, "  %s seq", hi->name);
620     sa = pool_elt_at_index(im->sad, t->output_sa_index);
621     vlib_cli_output(vm, "   seq %u seq-hi %u esn %u anti-replay %u",
622                     sa->seq, sa->seq_hi, sa->use_esn, sa->use_anti_replay);
623     vlib_cli_output(vm, "   local-spi %u local-ip %U", sa->spi,
624                     format_ip4_address, &sa->tunnel_src_addr.ip4);
625     vlib_cli_output(vm, "   local-crypto %U %U",
626                     format_ipsec_crypto_alg, sa->crypto_alg,
627                     format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
628     vlib_cli_output(vm, "   local-integrity %U %U",
629                     format_ipsec_integ_alg, sa->integ_alg,
630                     format_hex_bytes, sa->integ_key, sa->integ_key_len);
631     sa = pool_elt_at_index(im->sad, t->input_sa_index);
632     vlib_cli_output(vm, "   last-seq %u last-seq-hi %u esn %u anti-replay %u window %U",
633                     sa->last_seq, sa->last_seq_hi, sa->use_esn,
634                     sa->use_anti_replay,
635                     format_ipsec_replay_window, sa->replay_window);
636     vlib_cli_output(vm, "   remote-spi %u remote-ip %U", sa->spi,
637                     format_ip4_address, &sa->tunnel_src_addr.ip4);
638     vlib_cli_output(vm, "   remote-crypto %U %U",
639                     format_ipsec_crypto_alg, sa->crypto_alg,
640                     format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
641     vlib_cli_output(vm, "   remote-integrity %U %U",
642                     format_ipsec_integ_alg, sa->integ_alg,
643                     format_hex_bytes, sa->integ_key, sa->integ_key_len);
644   }));
645   /* *INDENT-ON* */
646   return 0;
647 }
648
649 /* *INDENT-OFF* */
650 VLIB_CLI_COMMAND (show_ipsec_command, static) = {
651     .path = "show ipsec",
652     .short_help = "show ipsec",
653     .function = show_ipsec_command_fn,
654 };
655 /* *INDENT-ON* */
656
657 static clib_error_t *
658 clear_ipsec_counters_command_fn (vlib_main_t * vm,
659                                  unformat_input_t * input,
660                                  vlib_cli_command_t * cmd)
661 {
662   ipsec_main_t *im = &ipsec_main;
663   ipsec_spd_t *spd;
664   ipsec_policy_t *p;
665
666   /* *INDENT-OFF* */
667   pool_foreach (spd, im->spds, ({
668     pool_foreach(p, spd->policies, ({
669       p->counter.packets = p->counter.bytes = 0;
670     }));
671   }));
672   /* *INDENT-ON* */
673
674   return 0;
675 }
676
677 /* *INDENT-OFF* */
678 VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
679     .path = "clear ipsec counters",
680     .short_help = "clear ipsec counters",
681     .function = clear_ipsec_counters_command_fn,
682 };
683 /* *INDENT-ON* */
684
685 static clib_error_t *
686 create_ipsec_tunnel_command_fn (vlib_main_t * vm,
687                                 unformat_input_t * input,
688                                 vlib_cli_command_t * cmd)
689 {
690   unformat_input_t _line_input, *line_input = &_line_input;
691   ipsec_add_del_tunnel_args_t a;
692   int rv;
693   u32 num_m_args = 0;
694   clib_error_t *error = NULL;
695
696   memset (&a, 0, sizeof (a));
697   a.is_add = 1;
698
699   /* Get a line of input. */
700   if (!unformat_user (input, unformat_line_input, line_input))
701     return 0;
702
703   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
704     {
705       if (unformat
706           (line_input, "local-ip %U", unformat_ip4_address, &a.local_ip))
707         num_m_args++;
708       else
709         if (unformat
710             (line_input, "remote-ip %U", unformat_ip4_address, &a.remote_ip))
711         num_m_args++;
712       else if (unformat (line_input, "local-spi %u", &a.local_spi))
713         num_m_args++;
714       else if (unformat (line_input, "remote-spi %u", &a.remote_spi))
715         num_m_args++;
716       else if (unformat (line_input, "del"))
717         a.is_add = 0;
718       else
719         {
720           error = clib_error_return (0, "unknown input `%U'",
721                                      format_unformat_error, line_input);
722           goto done;
723         }
724     }
725
726   if (num_m_args < 4)
727     {
728       error = clib_error_return (0, "mandatory argument(s) missing");
729       goto done;
730     }
731
732   rv = ipsec_add_del_tunnel_if (&a);
733
734   switch (rv)
735     {
736     case 0:
737       break;
738     case VNET_API_ERROR_INVALID_VALUE:
739       if (a.is_add)
740         error = clib_error_return (0,
741                                    "IPSec tunnel interface already exists...");
742       else
743         error = clib_error_return (0, "IPSec tunnel interface not exists...");
744       goto done;
745     default:
746       error = clib_error_return (0, "ipsec_register_interface returned %d",
747                                  rv);
748       goto done;
749     }
750
751 done:
752   unformat_free (line_input);
753
754   return error;
755 }
756
757 /* *INDENT-OFF* */
758 VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
759   .path = "create ipsec tunnel",
760   .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> remote-ip <addr> remote-spi <spi>",
761   .function = create_ipsec_tunnel_command_fn,
762 };
763 /* *INDENT-ON* */
764
765 static clib_error_t *
766 set_interface_key_command_fn (vlib_main_t * vm,
767                               unformat_input_t * input,
768                               vlib_cli_command_t * cmd)
769 {
770   unformat_input_t _line_input, *line_input = &_line_input;
771   ipsec_main_t *im = &ipsec_main;
772   ipsec_if_set_key_type_t type = IPSEC_IF_SET_KEY_TYPE_NONE;
773   u32 hw_if_index = (u32) ~ 0;
774   u32 alg;
775   u8 *key = 0;
776   clib_error_t *error = NULL;
777
778   if (!unformat_user (input, unformat_line_input, line_input))
779     return 0;
780
781   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
782     {
783       if (unformat (line_input, "%U",
784                     unformat_vnet_hw_interface, im->vnet_main, &hw_if_index))
785         ;
786       else
787         if (unformat
788             (line_input, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
789         type = IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO;
790       else
791         if (unformat
792             (line_input, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
793         type = IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO;
794       else
795         if (unformat
796             (line_input, "local integ %U", unformat_ipsec_integ_alg, &alg))
797         type = IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG;
798       else
799         if (unformat
800             (line_input, "remote integ %U", unformat_ipsec_integ_alg, &alg))
801         type = IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG;
802       else if (unformat (line_input, "%U", unformat_hex_string, &key))
803         ;
804       else
805         {
806           error = clib_error_return (0, "parse error: '%U'",
807                                      format_unformat_error, line_input);
808           goto done;
809         }
810     }
811
812   if (type == IPSEC_IF_SET_KEY_TYPE_NONE)
813     {
814       error = clib_error_return (0, "unknown key type");
815       goto done;
816     }
817
818   if (alg > 0 && vec_len (key) == 0)
819     {
820       error = clib_error_return (0, "key is not specified");
821       goto done;
822     }
823
824   if (hw_if_index == (u32) ~ 0)
825     {
826       error = clib_error_return (0, "interface not specified");
827       goto done;
828     }
829
830   ipsec_set_interface_key (im->vnet_main, hw_if_index, type, alg, key);
831
832 done:
833   vec_free (key);
834   unformat_free (line_input);
835
836   return error;
837 }
838
839 /* *INDENT-OFF* */
840 VLIB_CLI_COMMAND (set_interface_key_command, static) = {
841     .path = "set interface ipsec key",
842     .short_help =
843     "set interface ipsec key <int> <local|remote> <crypto|integ> <key type> <key>",
844     .function = set_interface_key_command_fn,
845 };
846 /* *INDENT-ON* */
847
848 clib_error_t *
849 ipsec_cli_init (vlib_main_t * vm)
850 {
851   return 0;
852 }
853
854 VLIB_INIT_FUNCTION (ipsec_cli_init);
855
856
857 /*
858  * fd.io coding-style-patch-verification: ON
859  *
860  * Local Variables:
861  * eval: (c-set-style "gnu")
862  * End:
863  */