Initial commit of vpp code.
[vpp.git] / vnet / 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
36   if (! unformat_user (input, unformat_line_input, line_input))
37     return 0;
38
39   if (unformat (line_input, "%U %u", unformat_vnet_sw_interface, im->vnet_main,
40                 &sw_if_index, &spd_id))
41     ;
42   else if (unformat (line_input, "del"))
43     is_add = 0;
44   else
45     return clib_error_return (0, "parse error: '%U'",
46                               format_unformat_error, line_input);
47
48   unformat_free (line_input);
49
50   ipsec_set_interface_spd(vm, sw_if_index, spd_id, is_add);
51
52   return 0;
53 }
54
55 VLIB_CLI_COMMAND (set_interface_spd_command, static) = {
56     .path = "set interface ipsec spd",
57     .short_help =
58     "set interface ipsec spd <int> <id>",
59     .function = set_interface_spd_command_fn,
60 };
61
62 static clib_error_t *
63 ipsec_sa_add_del_command_fn (vlib_main_t * vm,
64                               unformat_input_t * input,
65                               vlib_cli_command_t * cmd)
66 {
67   unformat_input_t _line_input, * line_input = &_line_input;
68   ipsec_sa_t sa;
69   int is_add = ~0;
70   u8 * ck, * ik;
71
72   memset(&sa, 0, sizeof(sa));
73
74   if (! unformat_user (input, unformat_line_input, line_input))
75     return 0;
76
77   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
78     if (unformat (line_input, "add %u", &sa.id))
79       is_add = 1;
80     else if (unformat (line_input, "del %u", &sa.id))
81       is_add = 0;
82     else if (unformat (line_input, "spi %u", &sa.spi))
83       ;
84     else if (unformat (line_input, "esp"))
85       sa.protocol = IPSEC_PROTOCOL_ESP;
86     else if (unformat (line_input, "ah"))
87       //sa.protocol = IPSEC_PROTOCOL_AH;
88       return clib_error_return(0, "unsupported security protocol 'AH'");
89     else if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
90       sa.crypto_key_len = vec_len (ck);
91     else if (unformat (line_input, "crypto-alg %U", unformat_ipsec_crypto_alg,
92                        &sa.crypto_alg))
93       {
94         if (sa.crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
95             sa.crypto_alg > IPSEC_CRYPTO_ALG_AES_CBC_256)
96           return clib_error_return(0, "unsupported crypto-alg: '%U'",
97                                    format_ipsec_crypto_alg, sa.crypto_alg);
98       }
99     else if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
100       sa.integ_key_len = vec_len (ik);
101     else if (unformat (line_input, "integ-alg %U", unformat_ipsec_integ_alg,
102                        &sa.integ_alg))
103       {
104         if (sa.integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
105              sa.integ_alg > IPSEC_INTEG_ALG_SHA_512_256)
106           return clib_error_return(0, "unsupported integ-alg: '%U'",
107                                    format_ipsec_integ_alg, sa.integ_alg);
108       }
109     else if (unformat (line_input, "tunnel-src %U",
110                        unformat_ip4_address, &sa.tunnel_src_addr.ip4))
111       sa.is_tunnel = 1;
112     else if (unformat (line_input, "tunnel-dst %U",
113                        unformat_ip4_address, &sa.tunnel_dst_addr.ip4))
114       sa.is_tunnel = 1;
115     else if (unformat (line_input, "tunnel-src %U",
116                        unformat_ip6_address, &sa.tunnel_src_addr.ip6))
117       { sa.is_tunnel = 1; sa.is_tunnel_ip6 = 1; }
118     else if (unformat (line_input, "tunnel-dst %U",
119                        unformat_ip6_address, &sa.tunnel_dst_addr.ip6))
120       { sa.is_tunnel = 1; sa.is_tunnel_ip6 = 1; }
121     else 
122       return clib_error_return (0, "parse error: '%U'",
123                               format_unformat_error, line_input);
124   }
125
126   unformat_free (line_input);
127
128   if (sa.crypto_key_len > sizeof(sa.crypto_key))
129     sa.crypto_key_len = sizeof(sa.crypto_key);
130
131   if (sa.integ_key_len > sizeof(sa.integ_key))
132     sa.integ_key_len = sizeof(sa.integ_key);
133
134   if (ck)
135     strncpy((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
136
137   if (ik)
138     strncpy((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
139
140   ipsec_add_del_sa(vm, &sa, is_add);
141
142   return 0;
143 }
144
145 VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
146     .path = "ipsec sa",
147     .short_help =
148     "ipsec sa [add|del]",
149     .function = ipsec_sa_add_del_command_fn,
150 };
151
152 static clib_error_t *
153 ipsec_spd_add_del_command_fn (vlib_main_t * vm,
154                               unformat_input_t * input,
155                               vlib_cli_command_t * cmd)
156 {
157   unformat_input_t _line_input, * line_input = &_line_input;
158   u32 spd_id;
159   int is_add = ~0;
160
161   if (! unformat_user (input, unformat_line_input, line_input))
162     return 0;
163
164   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
165     if (unformat (line_input, "add"))
166       is_add = 1;
167     else if (unformat (line_input, "del"))
168       is_add = 0;
169     else if (unformat (line_input, "%u", &spd_id))
170       ;
171     else
172       return clib_error_return (0, "parse error: '%U'",
173                               format_unformat_error, line_input);
174   }
175
176   unformat_free (line_input);
177
178   ipsec_add_del_spd(vm, spd_id, is_add);
179
180   return 0;
181 }
182
183 VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
184     .path = "ipsec spd",
185     .short_help =
186     "ipsec spd [add|del] <id>",
187     .function = ipsec_spd_add_del_command_fn,
188 };
189
190
191 static clib_error_t *
192 ipsec_policy_add_del_command_fn (vlib_main_t * vm,
193                                  unformat_input_t * input,
194                                  vlib_cli_command_t * cmd)
195 {
196   unformat_input_t _line_input, * line_input = &_line_input;
197   ipsec_policy_t p;
198   int is_add = 0;
199   int is_ip_any = 1;
200   u32 tmp, tmp2;
201
202   memset(&p, 0, sizeof(p));
203   p.lport.stop = p.rport.stop = ~0;
204   p.laddr.stop.ip4.as_u32 = p.raddr.stop.ip4.as_u32 = (u32) ~0;
205   p.laddr.stop.ip6.as_u64[0] = p.laddr.stop.ip6.as_u64[1] = (u64) ~0;
206   p.raddr.stop.ip6.as_u64[0] = p.raddr.stop.ip6.as_u64[1] = (u64) ~0;
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     if (unformat (line_input, "add"))
213       is_add = 1;
214     else if (unformat (line_input, "del"))
215       is_add = 0;
216     else if (unformat (line_input, "spd %u", &p.id))
217       ;
218     else if (unformat (line_input, "inbound"))
219       p.is_outbound = 0;
220     else if (unformat (line_input, "outbound"))
221       p.is_outbound = 1;
222     else if (unformat (line_input, "priority %d", &p.priority))
223       ;
224     else if (unformat (line_input, "protocol %u", &tmp))
225       p.protocol = (u8) tmp;
226     else if (unformat (line_input, "action %U", unformat_ipsec_policy_action,
227                        &p.policy))
228       {
229         if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
230           return clib_error_return(0, "unsupported action: 'resolve'");
231       }
232     else if (unformat (line_input, "sa %u", &p.sa_id))
233       ;
234     else if (unformat (line_input, "local-ip-range %U - %U",
235                        unformat_ip4_address, &p.laddr.start.ip4,
236                        unformat_ip4_address, &p.laddr.stop.ip4))
237       is_ip_any = 0;
238     else if (unformat (line_input, "remote-ip-range %U - %U",
239                        unformat_ip4_address, &p.raddr.start.ip4,
240                        unformat_ip4_address, &p.raddr.stop.ip4))
241       is_ip_any = 0;
242     else if (unformat (line_input, "local-ip-range %U - %U",
243                        unformat_ip6_address, &p.laddr.start.ip6,
244                        unformat_ip6_address, &p.laddr.stop.ip6))
245       {
246         p.is_ipv6 = 1;
247         is_ip_any = 0;
248       }
249     else if (unformat (line_input, "remote-ip-range %U - %U",
250                        unformat_ip6_address, &p.raddr.start.ip6,
251                        unformat_ip6_address, &p.raddr.stop.ip6))
252       {
253         p.is_ipv6 = 1;
254         is_ip_any = 0;
255       }
256     else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
257       { p.lport.start = tmp; p.lport.stop = tmp2; }
258     else if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
259       { p.rport.start = tmp; p.rport.stop = tmp2; }
260     else 
261       return clib_error_return (0, "parse error: '%U'",
262                               format_unformat_error, line_input);
263   }
264
265   unformat_free (line_input);
266
267   ipsec_add_del_policy(vm, &p, is_add);
268   if (is_ip_any)
269     {
270       p.is_ipv6 = 1;
271       ipsec_add_del_policy(vm, &p, is_add);
272     }
273   return 0;
274 }
275
276 VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
277     .path = "ipsec policy",
278     .short_help =
279     "ipsec policy [add|del] spd <id> priority <n> ",
280     .function = ipsec_policy_add_del_command_fn,
281 };
282
283 static clib_error_t *
284 set_ipsec_sa_key_command_fn (vlib_main_t * vm,
285                              unformat_input_t * input,
286                              vlib_cli_command_t * cmd)
287 {
288   unformat_input_t _line_input, * line_input = &_line_input;
289   ipsec_sa_t sa;
290   u8 * ck, * ik;
291
292   memset(&sa, 0, sizeof(sa));
293
294   if (! unformat_user (input, unformat_line_input, line_input))
295     return 0;
296
297   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
298     if (unformat (line_input, "%u", &sa.id))
299       ;
300     else if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
301       sa.crypto_key_len = vec_len (ck);
302     else if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
303       sa.integ_key_len = vec_len (ik);
304     else
305       return clib_error_return (0, "parse error: '%U'", format_unformat_error,
306                                 line_input);
307   }
308
309   unformat_free (line_input);
310
311   if (sa.crypto_key_len > sizeof(sa.crypto_key))
312     sa.crypto_key_len = sizeof(sa.crypto_key);
313
314   if (sa.integ_key_len > sizeof(sa.integ_key))
315     sa.integ_key_len = sizeof(sa.integ_key);
316
317   if (ck)
318     strncpy((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
319
320   if (ik)
321     strncpy((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
322
323   ipsec_set_sa_key(vm, &sa);
324
325   return 0;
326 }
327
328 VLIB_CLI_COMMAND (set_ipsec_sa_key_command, static) = {
329     .path = "set ipsec sa",
330     .short_help =
331     "set ipsec sa <id> crypto-key <key> integ-key <key>",
332     .function = set_ipsec_sa_key_command_fn,
333 };
334
335 static clib_error_t *
336 show_ipsec_command_fn (vlib_main_t * vm,
337                        unformat_input_t * input,
338                        vlib_cli_command_t * cmd)
339 {
340   ipsec_spd_t * spd;
341   ipsec_sa_t * sa;
342   ipsec_policy_t * p;
343   ipsec_main_t * im = &ipsec_main;
344   u32 * i;
345   ipsec_tunnel_if_t * t;
346   vnet_hw_interface_t * hi;
347
348   pool_foreach (sa, im->sad, ({
349     if (sa->id) {
350       vlib_cli_output(vm, "sa %u spi %u mode %s protocol %s", sa->id, sa->spi,
351                       sa->is_tunnel ? "tunnel" : "transport",
352                       sa->protocol ? "esp" : "ah");
353       if (sa->protocol == IPSEC_PROTOCOL_ESP) {
354         vlib_cli_output(vm, "  crypto alg %U%s%U integrity alg %U%s%U",
355                         format_ipsec_crypto_alg, sa->crypto_alg,
356                         sa->crypto_alg ? " key " : "",
357                         format_hex_bytes, sa->crypto_key, sa->crypto_key_len,
358                         format_ipsec_integ_alg, sa->integ_alg,
359                         sa->integ_alg ? " key " : "",
360                         format_hex_bytes, sa->integ_key, sa->integ_key_len);
361       }
362       if (sa->is_tunnel && sa->is_tunnel_ip6) {
363         vlib_cli_output(vm, "  tunnel src %U dst %U",
364                         format_ip6_address, &sa->tunnel_src_addr.ip6,
365                         format_ip6_address, &sa->tunnel_dst_addr.ip6);
366       } else if (sa->is_tunnel) {
367         vlib_cli_output(vm, "  tunnel src %U dst %U",
368                         format_ip4_address, &sa->tunnel_src_addr.ip4,
369                         format_ip4_address, &sa->tunnel_dst_addr.ip4);
370       }
371     }
372   }));
373
374   pool_foreach (spd, im->spds, ({
375     vlib_cli_output(vm, "spd %u", spd->id);
376
377     vlib_cli_output(vm, " outbound policies");
378     vec_foreach(i, spd->ipv4_outbound_policies)
379       {
380         p = pool_elt_at_index(spd->policies, *i);
381         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
382                         p->priority,
383                         format_ipsec_policy_action, p->policy,
384                         p->protocol ?
385                           format(0, "%U", format_ip_protocol, p->protocol) :
386                           (u8 *) "any",
387                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
388                           format(0, " sa %u", p->sa_id) :
389                           (u8 *) "");
390         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
391                         format_ip4_address, &p->laddr.start.ip4,
392                         format_ip4_address, &p->laddr.stop.ip4,
393                         p->lport.start, p->lport.stop);
394         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
395                         format_ip4_address, &p->raddr.start.ip4,
396                         format_ip4_address, &p->raddr.stop.ip4,
397                         p->rport.start, p->rport.stop);
398         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
399                         p->counter.bytes);
400       };
401     vec_foreach(i, spd->ipv6_outbound_policies)
402       {
403         p = pool_elt_at_index(spd->policies, *i);
404         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
405                         p->priority,
406                         format_ipsec_policy_action, p->policy,
407                         p->protocol ?
408                           format(0, "%U", format_ip_protocol, p->protocol) :
409                           (u8 *) "any",
410                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
411                           format(0, " sa %u", p->sa_id) :
412                           (u8 *) "");
413         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
414                         format_ip6_address, &p->laddr.start.ip6,
415                         format_ip6_address, &p->laddr.stop.ip6,
416                         p->lport.start, p->lport.stop);
417         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
418                         format_ip6_address, &p->raddr.start.ip6,
419                         format_ip6_address, &p->raddr.stop.ip6,
420                         p->rport.start, p->rport.stop);
421         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
422                         p->counter.bytes);
423       };
424     vlib_cli_output(vm, " inbound policies");
425     vec_foreach(i, spd->ipv4_inbound_protect_policy_indices)
426       {
427         p = pool_elt_at_index(spd->policies, *i);
428         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
429                         p->priority,
430                         format_ipsec_policy_action, p->policy,
431                         p->protocol ?
432                           format(0, "%U", format_ip_protocol, p->protocol) :
433                           (u8 *) "any",
434                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
435                           format(0, " sa %u", p->sa_id) :
436                           (u8 *) "");
437         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
438                         format_ip4_address, &p->laddr.start.ip4,
439                         format_ip4_address, &p->laddr.stop.ip4,
440                         p->lport.start, p->lport.stop);
441         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
442                         format_ip4_address, &p->raddr.start.ip4,
443                         format_ip4_address, &p->raddr.stop.ip4,
444                         p->rport.start, p->rport.stop);
445         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
446                         p->counter.bytes);
447       };
448     vec_foreach(i, spd->ipv4_inbound_policy_discard_and_bypass_indices)
449       {
450         p = pool_elt_at_index(spd->policies, *i);
451         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
452                         p->priority,
453                         format_ipsec_policy_action, p->policy,
454                         p->protocol ?
455                           format(0, "%U", format_ip_protocol, p->protocol) :
456                           (u8 *) "any",
457                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
458                           format(0, " sa %u", p->sa_id) :
459                           (u8 *) "");
460         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
461                         format_ip4_address, &p->laddr.start.ip4,
462                         format_ip4_address, &p->laddr.stop.ip4,
463                         p->lport.start, p->lport.stop);
464         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
465                         format_ip4_address, &p->raddr.start.ip4,
466                         format_ip4_address, &p->raddr.stop.ip4,
467                         p->rport.start, p->rport.stop);
468         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
469                         p->counter.bytes);
470       };
471     vec_foreach(i, spd->ipv6_inbound_protect_policy_indices)
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_ip6_address, &p->laddr.start.ip6,
485                         format_ip6_address, &p->laddr.stop.ip6,
486                         p->lport.start, p->lport.stop);
487         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
488                         format_ip6_address, &p->raddr.start.ip6,
489                         format_ip6_address, &p->raddr.stop.ip6,
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_inbound_policy_discard_and_bypass_indices)
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   }));
518
519   vlib_cli_output(vm, "tunnel interfaces");
520   pool_foreach (t, im->tunnel_interfaces, ({
521     hi = vnet_get_hw_interface (im->vnet_main, t->hw_if_index);
522     vlib_cli_output(vm, "  %s seq", hi->name);
523     sa = pool_elt_at_index(im->sad, t->output_sa_index);
524     vlib_cli_output(vm, "   seq %u seq-hi %u esn %u anti-replay %u",
525                     sa->seq, sa->seq_hi, sa->use_esn, sa->use_anti_replay);
526     vlib_cli_output(vm, "   local-spi %u local-ip %U", sa->spi,
527                     format_ip4_address, &sa->tunnel_src_addr.ip4);
528     vlib_cli_output(vm, "   local-crypto %U %U",
529                     format_ipsec_crypto_alg, sa->crypto_alg,
530                     format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
531     vlib_cli_output(vm, "   local-integrity %U %U",
532                     format_ipsec_integ_alg, sa->integ_alg,
533                     format_hex_bytes, sa->integ_key, sa->integ_key_len);
534     sa = pool_elt_at_index(im->sad, t->input_sa_index);
535     vlib_cli_output(vm, "   last-seq %u last-seq-hi %u esn %u anti-replay %u window %U",
536                     sa->last_seq, sa->last_seq_hi, sa->use_esn,
537                     sa->use_anti_replay,
538                     format_ipsec_replay_window, sa->replay_window);
539     vlib_cli_output(vm, "   remote-spi %u remote-ip %U", sa->spi,
540                     format_ip4_address, &sa->tunnel_src_addr.ip4);
541     vlib_cli_output(vm, "   remote-crypto %U %U",
542                     format_ipsec_crypto_alg, sa->crypto_alg,
543                     format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
544     vlib_cli_output(vm, "   remote-integrity %U %U",
545                     format_ipsec_integ_alg, sa->integ_alg,
546                     format_hex_bytes, sa->integ_key, sa->integ_key_len);
547   }));
548   return 0;
549 }
550
551 VLIB_CLI_COMMAND (show_ipsec_command, static) = {
552     .path = "show ipsec",
553     .short_help = "show ipsec",
554     .function = show_ipsec_command_fn,
555 };
556
557 static clib_error_t *
558 clear_ipsec_counters_command_fn (vlib_main_t * vm,
559                                  unformat_input_t * input,
560                                  vlib_cli_command_t * cmd)
561 {
562   ipsec_main_t * im = &ipsec_main;
563   ipsec_spd_t * spd;
564   ipsec_policy_t * p;
565
566   pool_foreach (spd, im->spds, ({
567     pool_foreach(p, spd->policies, ({
568       p->counter.packets = p->counter.bytes = 0;
569     }));
570   }));
571
572   return 0;
573 }
574
575 VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
576     .path = "clear ipsec counters",
577     .short_help = "clear ipsec counters",
578     .function = clear_ipsec_counters_command_fn,
579 };
580
581 static clib_error_t *
582 create_ipsec_tunnel_command_fn (vlib_main_t * vm,
583      unformat_input_t * input,
584      vlib_cli_command_t * cmd)
585 {
586   unformat_input_t _line_input, * line_input = &_line_input;
587   ipsec_add_del_tunnel_args_t a;
588   ipsec_main_t *im = &ipsec_main;
589   int rv;
590   u32 num_m_args = 0;
591   a.is_add = 1;
592   a.anti_replay = 0;
593   a.esn = 0;
594
595   /* Get a line of input. */
596   if (! unformat_user (input, unformat_line_input, line_input))
597     return 0;
598
599   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
600     if (unformat (line_input, "local-ip %U", unformat_ip4_address, &a.local_ip))
601       num_m_args++;
602     else if (unformat (line_input, "remote-ip %U", unformat_ip4_address, &a.remote_ip))
603       num_m_args++;
604     else if (unformat (line_input, "local-spi %u", &a.local_spi))
605       num_m_args++;
606     else if (unformat (line_input, "remote-spi %u", &a.remote_spi))
607       num_m_args++;
608     else if (unformat (line_input, "del"))
609       a.is_add = 0;
610     else
611       return clib_error_return (0, "unknown input `%U'",
612                                 format_unformat_error, input);
613   }
614   unformat_free (line_input);
615
616   if (num_m_args < 4)
617       return clib_error_return (0, "mandatory argument(s) missing");
618
619   rv = ipsec_add_del_tunnel_if (im->vnet_main, &a);
620
621  switch(rv)
622     {
623     case 0:
624       break;
625     case VNET_API_ERROR_INVALID_VALUE:
626       if (a.is_add)
627         return clib_error_return (0, "IPSec tunnel interface already exists...");
628       else
629         return clib_error_return (0, "IPSec tunnel interface not exists...");
630     default:
631       return clib_error_return (0, "ipsec_register_interface returned %d", rv);
632     }
633
634   return 0;
635 }
636
637 VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
638   .path = "create ipsec tunnel",
639   .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> remote-ip <addr> remote-spi <spi>",
640   .function = create_ipsec_tunnel_command_fn,
641 };
642
643 static clib_error_t *
644 set_interface_key_command_fn (vlib_main_t * vm,
645                               unformat_input_t * input,
646                               vlib_cli_command_t * cmd)
647 {
648   unformat_input_t _line_input, * line_input = &_line_input;
649   ipsec_main_t *im = &ipsec_main;
650   ipsec_if_set_key_type_t type = IPSEC_IF_SET_KEY_TYPE_NONE;
651   u32 hw_if_index = (u32) ~0;
652   u32 alg;
653   u8 * key = 0;
654
655   if (! unformat_user (input, unformat_line_input, line_input))
656     return 0;
657
658   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
659     {
660       if (unformat (line_input, "%U",
661                     unformat_vnet_hw_interface, im->vnet_main, &hw_if_index))
662         ;
663       else if (unformat (line_input, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
664         type = IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO;
665       else if (unformat (line_input, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
666         type = IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO;
667       else if (unformat (line_input, "local integ %U", unformat_ipsec_integ_alg, &alg))
668         type = IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG;
669       else if (unformat (line_input, "remote integ %U", unformat_ipsec_integ_alg, &alg))
670         type = IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG;
671       else if (unformat (line_input, "%U", unformat_hex_string, &key))
672         ;
673       else
674         return clib_error_return (0, "parse error: '%U'",
675                                   format_unformat_error, line_input);
676     }
677
678   unformat_free (line_input);
679
680   if (type == IPSEC_IF_SET_KEY_TYPE_NONE)
681       return clib_error_return (0, "unknown key type");
682
683   if (alg > 0 && vec_len(key)==0)
684       return clib_error_return (0, "key is not specified");
685
686   if (hw_if_index == (u32) ~0)
687       return clib_error_return (0, "interface not specified");
688
689   ipsec_set_interface_key(im->vnet_main, hw_if_index, type, alg, key);
690   vec_free(key);
691
692   return 0;
693 }
694
695 VLIB_CLI_COMMAND (set_interface_key_command, static) = {
696     .path = "set interface ipsec key",
697     .short_help =
698     "set interface ipsec key <int> <local|remote> <crypto|integ> <key type> <key>",
699     .function = set_interface_key_command_fn,
700 };
701
702
703 clib_error_t *
704 ipsec_cli_init (vlib_main_t * vm)
705 {
706   return 0;
707 }
708
709 VLIB_INIT_FUNCTION (ipsec_cli_init);
710