FD.io VPP  v19.04.1-1-ge4a0f9f
Vector Packet Processing
ipsec_cli.c
Go to the documentation of this file.
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 #include <vnet/fib/fib.h>
23 
24 #include <vnet/ipsec/ipsec.h>
25 
26 static clib_error_t *
28  unformat_input_t * input,
29  vlib_cli_command_t * cmd)
30 {
31  unformat_input_t _line_input, *line_input = &_line_input;
32  ipsec_main_t *im = &ipsec_main;
33  u32 sw_if_index = (u32) ~ 0;
34  u32 spd_id;
35  int is_add = 1;
36  clib_error_t *error = NULL;
37 
38  if (!unformat_user (input, unformat_line_input, line_input))
39  return 0;
40 
41  if (unformat
42  (line_input, "%U %u", unformat_vnet_sw_interface, im->vnet_main,
43  &sw_if_index, &spd_id))
44  ;
45  else if (unformat (line_input, "del"))
46  is_add = 0;
47  else
48  {
49  error = clib_error_return (0, "parse error: '%U'",
50  format_unformat_error, line_input);
51  goto done;
52  }
53 
54  ipsec_set_interface_spd (vm, sw_if_index, spd_id, is_add);
55 
56 done:
57  unformat_free (line_input);
58 
59  return error;
60 }
61 
62 /* *INDENT-OFF* */
63 VLIB_CLI_COMMAND (set_interface_spd_command, static) = {
64  .path = "set interface ipsec spd",
65  .short_help =
66  "set interface ipsec spd <int> <id>",
67  .function = set_interface_spd_command_fn,
68 };
69 /* *INDENT-ON* */
70 
71 static clib_error_t *
73  unformat_input_t * input,
74  vlib_cli_command_t * cmd)
75 {
76  unformat_input_t _line_input, *line_input = &_line_input;
77  ip46_address_t tun_src = { }, tun_dst =
78  {
79  };
80  ipsec_crypto_alg_t crypto_alg;
81  ipsec_integ_alg_t integ_alg;
82  ipsec_protocol_t proto;
84  clib_error_t *error;
85  ipsec_key_t ck = { 0 };
86  ipsec_key_t ik = { 0 };
87  int is_add, rv;
88  u32 id, spi;
89 
90  error = NULL;
91  is_add = 0;
92  flags = IPSEC_SA_FLAG_NONE;
93  proto = IPSEC_PROTOCOL_ESP;
94 
95  if (!unformat_user (input, unformat_line_input, line_input))
96  return 0;
97 
98  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
99  {
100  if (unformat (line_input, "add %u", &id))
101  is_add = 1;
102  else if (unformat (line_input, "del %u", &id))
103  is_add = 0;
104  else if (unformat (line_input, "spi %u", &spi))
105  ;
106  else if (unformat (line_input, "esp"))
107  proto = IPSEC_PROTOCOL_ESP;
108  else if (unformat (line_input, "ah"))
109  proto = IPSEC_PROTOCOL_AH;
110  else if (unformat (line_input, "crypto-key %U",
111  unformat_ipsec_key, &ck))
112  ;
113  else if (unformat (line_input, "crypto-alg %U",
114  unformat_ipsec_crypto_alg, &crypto_alg))
115  ;
116  else if (unformat (line_input, "integ-key %U", unformat_ipsec_key, &ik))
117  ;
118  else if (unformat (line_input, "integ-alg %U",
119  unformat_ipsec_integ_alg, &integ_alg))
120  ;
121  else if (unformat (line_input, "tunnel-src %U",
123  {
124  flags |= IPSEC_SA_FLAG_IS_TUNNEL;
125  if (!ip46_address_is_ip4 (&tun_src))
126  flags |= IPSEC_SA_FLAG_IS_TUNNEL_V6;
127  }
128  else if (unformat (line_input, "tunnel-dst %U",
130  ;
131  else if (unformat (line_input, "udp-encap"))
132  flags |= IPSEC_SA_FLAG_UDP_ENCAP;
133  else
134  {
135  error = clib_error_return (0, "parse error: '%U'",
136  format_unformat_error, line_input);
137  goto done;
138  }
139  }
140 
141  if (is_add)
142  rv = ipsec_sa_add (id, spi, proto, crypto_alg,
143  &ck, integ_alg, &ik, flags,
144  0, 0, &tun_src, &tun_dst, NULL);
145  else
146  rv = ipsec_sa_del (id);
147 
148  if (rv)
149  clib_error_return (0, "failed");
150 
151 done:
152  unformat_free (line_input);
153 
154  return error;
155 }
156 
157 /* *INDENT-OFF* */
158 VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
159  .path = "ipsec sa",
160  .short_help =
161  "ipsec sa [add|del]",
162  .function = ipsec_sa_add_del_command_fn,
163 };
164 /* *INDENT-ON* */
165 
166 static clib_error_t *
168  unformat_input_t * input,
169  vlib_cli_command_t * cmd)
170 {
171  unformat_input_t _line_input, *line_input = &_line_input;
172  u32 spd_id = ~0;
173  int is_add = ~0;
174  clib_error_t *error = NULL;
175 
176  if (!unformat_user (input, unformat_line_input, line_input))
177  return 0;
178 
179  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
180  {
181  if (unformat (line_input, "add"))
182  is_add = 1;
183  else if (unformat (line_input, "del"))
184  is_add = 0;
185  else if (unformat (line_input, "%u", &spd_id))
186  ;
187  else
188  {
189  error = clib_error_return (0, "parse error: '%U'",
190  format_unformat_error, line_input);
191  goto done;
192  }
193  }
194 
195  if (spd_id == ~0)
196  {
197  error = clib_error_return (0, "please specify SPD ID");
198  goto done;
199  }
200 
201  ipsec_add_del_spd (vm, spd_id, is_add);
202 
203 done:
204  unformat_free (line_input);
205 
206  return error;
207 }
208 
209 /* *INDENT-OFF* */
210 VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
211  .path = "ipsec spd",
212  .short_help =
213  "ipsec spd [add|del] <id>",
214  .function = ipsec_spd_add_del_command_fn,
215 };
216 /* *INDENT-ON* */
217 
218 
219 static clib_error_t *
221  unformat_input_t * input,
222  vlib_cli_command_t * cmd)
223 {
224  unformat_input_t _line_input, *line_input = &_line_input;
225  ipsec_policy_t p;
226  int rv, is_add = 0;
227  u32 tmp, tmp2, stat_index;
228  clib_error_t *error = NULL;
230 
231  clib_memset (&p, 0, sizeof (p));
232  p.lport.stop = p.rport.stop = ~0;
233  p.laddr.stop.ip4.as_u32 = p.raddr.stop.ip4.as_u32 = (u32) ~ 0;
234  p.laddr.stop.ip6.as_u64[0] = p.laddr.stop.ip6.as_u64[1] = (u64) ~ 0;
235  p.raddr.stop.ip6.as_u64[0] = p.raddr.stop.ip6.as_u64[1] = (u64) ~ 0;
236  is_outbound = 0;
237 
238  if (!unformat_user (input, unformat_line_input, line_input))
239  return 0;
240 
241  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
242  {
243  if (unformat (line_input, "add"))
244  is_add = 1;
245  else if (unformat (line_input, "del"))
246  is_add = 0;
247  else if (unformat (line_input, "spd %u", &p.id))
248  ;
249  else if (unformat (line_input, "inbound"))
250  is_outbound = 0;
251  else if (unformat (line_input, "outbound"))
252  is_outbound = 1;
253  else if (unformat (line_input, "priority %d", &p.priority))
254  ;
255  else if (unformat (line_input, "protocol %u", &tmp))
256  p.protocol = (u8) tmp;
257  else
258  if (unformat
259  (line_input, "action %U", unformat_ipsec_policy_action,
260  &p.policy))
261  {
262  if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
263  {
264  error = clib_error_return (0, "unsupported action: 'resolve'");
265  goto done;
266  }
267  }
268  else if (unformat (line_input, "sa %u", &p.sa_id))
269  ;
270  else if (unformat (line_input, "local-ip-range %U - %U",
273  ;
274  else if (unformat (line_input, "remote-ip-range %U - %U",
277  ;
278  else if (unformat (line_input, "local-ip-range %U - %U",
281  {
282  p.is_ipv6 = 1;
283  }
284  else if (unformat (line_input, "remote-ip-range %U - %U",
287  {
288  p.is_ipv6 = 1;
289  }
290  else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
291  {
292  p.lport.start = tmp;
293  p.lport.stop = tmp2;
294  p.lport.start = clib_host_to_net_u16 (p.lport.start);
295  p.lport.stop = clib_host_to_net_u16 (p.lport.stop);
296  }
297  else
298  if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
299  {
300  p.rport.start = tmp;
301  p.rport.stop = tmp2;
302  p.rport.start = clib_host_to_net_u16 (p.rport.start);
303  p.rport.stop = clib_host_to_net_u16 (p.rport.stop);
304  }
305  else
306  {
307  error = clib_error_return (0, "parse error: '%U'",
308  format_unformat_error, line_input);
309  goto done;
310  }
311  }
312 
313  /* Check if SA is for IPv6/AH which is not supported. Return error if TRUE. */
314  if (p.sa_id)
315  {
316  uword *p1;
317  ipsec_main_t *im = &ipsec_main;
318  ipsec_sa_t *sa = 0;
319  p1 = hash_get (im->sa_index_by_sa_id, p.sa_id);
320  if (!p1)
321  {
322  error =
323  clib_error_return (0, "SA with index %u not found", p.sa_id);
324  goto done;
325  }
326  sa = pool_elt_at_index (im->sad, p1[0]);
327  if (sa && sa->protocol == IPSEC_PROTOCOL_AH && is_add && p.is_ipv6)
328  {
329  error = clib_error_return (0, "AH not supported for IPV6: '%U'",
330  format_unformat_error, line_input);
331  goto done;
332  }
333  }
334 
335  rv = ipsec_policy_mk_type (is_outbound, p.is_ipv6, p.policy, &p.type);
336 
337  if (rv)
338  {
339  error = clib_error_return (0, "unsupported policy type for:",
340  " outboud:%s %s action:%U",
341  (is_outbound ? "yes" : "no"),
342  (p.is_ipv6 ? "IPv4" : "IPv6"),
344  goto done;
345  }
346 
347  rv = ipsec_add_del_policy (vm, &p, is_add, &stat_index);
348 
349  if (!rv)
350  vlib_cli_output (vm, "policy-index:%d", stat_index);
351  else
352  vlib_cli_output (vm, "error:%d", rv);
353 
354 done:
355  unformat_free (line_input);
356 
357  return error;
358 }
359 
360 /* *INDENT-OFF* */
361 VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
362  .path = "ipsec policy",
363  .short_help =
364  "ipsec policy [add|del] spd <id> priority <n> ",
366 };
367 /* *INDENT-ON* */
368 
369 static clib_error_t *
371  unformat_input_t * input,
372  vlib_cli_command_t * cmd)
373 {
374  unformat_input_t _line_input, *line_input = &_line_input;
375  clib_error_t *error = NULL;
376  ipsec_key_t ck, ik;
377  u32 id;
378 
379  if (!unformat_user (input, unformat_line_input, line_input))
380  return 0;
381 
382  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
383  {
384  if (unformat (line_input, "%u", &id))
385  ;
386  else
387  if (unformat (line_input, "crypto-key %U", unformat_ipsec_key, &ck))
388  ;
389  else if (unformat (line_input, "integ-key %U", unformat_ipsec_key, &ik))
390  ;
391  else
392  {
393  error = clib_error_return (0, "parse error: '%U'",
394  format_unformat_error, line_input);
395  goto done;
396  }
397  }
398 
399  ipsec_set_sa_key (id, &ck, &ik);
400 
401 done:
402  unformat_free (line_input);
403 
404  return error;
405 }
406 
407 /* *INDENT-OFF* */
408 VLIB_CLI_COMMAND (set_ipsec_sa_key_command, static) = {
409  .path = "set ipsec sa",
410  .short_help = "set ipsec sa <id> crypto-key <key> integ-key <key>",
411  .function = set_ipsec_sa_key_command_fn,
412 };
413 /* *INDENT-ON* */
414 
415 static void
417 {
418  u32 sai;
419 
420  /* *INDENT-OFF* */
421  pool_foreach_index (sai, im->sad, ({
422  vlib_cli_output(vm, "%U", format_ipsec_sa, sai, IPSEC_FORMAT_BRIEF);
423  }));
424  /* *INDENT-ON* */
425 }
426 
427 static void
429 {
430  u32 spdi;
431 
432  /* *INDENT-OFF* */
433  pool_foreach_index (spdi, im->spds, ({
434  vlib_cli_output(vm, "%U", format_ipsec_spd, spdi);
435  }));
436  /* *INDENT-ON* */
437 }
438 
439 static void
441 {
442  u32 spd_id, sw_if_index;
443 
444  vlib_cli_output (vm, "SPD Bindings:");
445 
446  /* *INDENT-OFF* */
447  hash_foreach(sw_if_index, spd_id, im->spd_index_by_sw_if_index, ({
448  vlib_cli_output (vm, " %d -> %U", spd_id,
449  format_vnet_sw_if_index_name, im->vnet_main,
450  sw_if_index);
451  }));
452  /* *INDENT-ON* */
453 }
454 
455 static void
457 {
458  u32 ti;
459 
460  vlib_cli_output (vm, "Tunnel interfaces");
461  /* *INDENT-OFF* */
463  vlib_cli_output(vm, " %U", format_ipsec_tunnel, ti);
464  }));
465  /* *INDENT-ON* */
466 }
467 
468 static clib_error_t *
470  unformat_input_t * input, vlib_cli_command_t * cmd)
471 {
472  ipsec_main_t *im = &ipsec_main;
473 
474  ipsec_sa_show_all (vm, im);
475  ipsec_spd_show_all (vm, im);
477  ipsec_tunnel_show_all (vm, im);
478 
479  return 0;
480 }
481 
482 /* *INDENT-OFF* */
483 VLIB_CLI_COMMAND (show_ipsec_command, static) = {
484  .path = "show ipsec all",
485  .short_help = "show ipsec all",
486  .function = show_ipsec_command_fn,
487 };
488 /* *INDENT-ON* */
489 
490 static clib_error_t *
492  unformat_input_t * input, vlib_cli_command_t * cmd)
493 {
494  ipsec_main_t *im = &ipsec_main;
495  u32 sai = ~0;
496 
498  {
499  if (unformat (input, "%u", &sai))
500  ;
501  else
502  break;
503  }
504 
505  if (~0 == sai)
506  ipsec_sa_show_all (vm, im);
507  else
509 
510  return 0;
511 }
512 
513 /* *INDENT-OFF* */
514 VLIB_CLI_COMMAND (show_ipsec_sa_command, static) = {
515  .path = "show ipsec sa",
516  .short_help = "show ipsec sa [index]",
517  .function = show_ipsec_sa_command_fn,
518 };
519 /* *INDENT-ON* */
520 
521 static clib_error_t *
523  unformat_input_t * input, vlib_cli_command_t * cmd)
524 {
525  ipsec_main_t *im = &ipsec_main;
526  u8 show_bindings = 0;
527  u32 spdi = ~0;
528 
530  {
531  if (unformat (input, "%u", &spdi))
532  ;
533  else if (unformat (input, "bindings"))
534  show_bindings = 1;
535  else
536  break;
537  }
538 
539  if (show_bindings)
541  else if (~0 != spdi)
542  vlib_cli_output (vm, "%U", format_ipsec_spd, spdi);
543  else
544  ipsec_spd_show_all (vm, im);
545 
546  return 0;
547 }
548 
549 /* *INDENT-OFF* */
550 VLIB_CLI_COMMAND (show_ipsec_spd_command, static) = {
551  .path = "show ipsec spd",
552  .short_help = "show ipsec spd [index]",
553  .function = show_ipsec_spd_command_fn,
554 };
555 /* *INDENT-ON* */
556 
557 static clib_error_t *
559  unformat_input_t * input,
560  vlib_cli_command_t * cmd)
561 {
562  ipsec_main_t *im = &ipsec_main;
563  u32 ti = ~0;
564 
566  {
567  if (unformat (input, "%u", &ti))
568  ;
569  else
570  break;
571  }
572 
573  if (~0 != ti)
574  vlib_cli_output (vm, "%U", format_ipsec_tunnel, ti);
575  else
576  ipsec_tunnel_show_all (vm, im);
577 
578  return 0;
579 }
580 
581 /* *INDENT-OFF* */
582 VLIB_CLI_COMMAND (show_ipsec_tunnel_command, static) = {
583  .path = "show ipsec tunnel",
584  .short_help = "show ipsec tunnel [index]",
585  .function = show_ipsec_tunnel_command_fn,
586 };
587 /* *INDENT-ON* */
588 
589 static clib_error_t *
591  unformat_input_t * input,
592  vlib_cli_command_t * cmd)
593 {
594  ipsec_main_t *im = &ipsec_main;
595  u32 verbose = 0;
596 
597  (void) unformat (input, "verbose %u", &verbose);
598 
599  vlib_cli_output (vm, "IPsec AH backends available:");
600  u8 *s = format (NULL, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
601  ipsec_ah_backend_t *ab;
602  /* *INDENT-OFF* */
603  pool_foreach (ab, im->ah_backends, {
604  s = format (s, "%=25s %=25u %=10s\n", ab->name, ab - im->ah_backends,
605  ab - im->ah_backends == im->ah_current_backend ? "yes" : "no");
606  if (verbose) {
607  vlib_node_t *n;
608  n = vlib_get_node (vm, ab->ah4_encrypt_node_index);
609  s = format (s, " enc4 %s (next %d)\n", n->name, ab->ah4_encrypt_next_index);
610  n = vlib_get_node (vm, ab->ah4_decrypt_node_index);
611  s = format (s, " dec4 %s (next %d)\n", n->name, ab->ah4_decrypt_next_index);
612  n = vlib_get_node (vm, ab->ah6_encrypt_node_index);
613  s = format (s, " enc6 %s (next %d)\n", n->name, ab->ah6_encrypt_next_index);
614  n = vlib_get_node (vm, ab->ah6_decrypt_node_index);
615  s = format (s, " dec6 %s (next %d)\n", n->name, ab->ah6_decrypt_next_index);
616  }
617  });
618  /* *INDENT-ON* */
619  vlib_cli_output (vm, "%v", s);
620  _vec_len (s) = 0;
621  vlib_cli_output (vm, "IPsec ESP backends available:");
622  s = format (s, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
624  /* *INDENT-OFF* */
625  pool_foreach (eb, im->esp_backends, {
626  s = format (s, "%=25s %=25u %=10s\n", eb->name, eb - im->esp_backends,
627  eb - im->esp_backends == im->esp_current_backend ? "yes"
628  : "no");
629  if (verbose) {
630  vlib_node_t *n;
631  n = vlib_get_node (vm, eb->esp4_encrypt_node_index);
632  s = format (s, " enc4 %s (next %d)\n", n->name, eb->esp4_encrypt_next_index);
633  n = vlib_get_node (vm, eb->esp4_decrypt_node_index);
634  s = format (s, " dec4 %s (next %d)\n", n->name, eb->esp4_decrypt_next_index);
635  n = vlib_get_node (vm, eb->esp6_encrypt_node_index);
636  s = format (s, " enc6 %s (next %d)\n", n->name, eb->esp6_encrypt_next_index);
637  n = vlib_get_node (vm, eb->esp6_decrypt_node_index);
638  s = format (s, " dec6 %s (next %d)\n", n->name, eb->esp6_decrypt_next_index);
639  }
640  });
641  /* *INDENT-ON* */
642  vlib_cli_output (vm, "%v", s);
643 
644  vec_free (s);
645  return 0;
646 }
647 
648 /* *INDENT-OFF* */
649 VLIB_CLI_COMMAND (ipsec_show_backends_command, static) = {
650  .path = "show ipsec backends",
651  .short_help = "show ipsec backends",
652  .function = ipsec_show_backends_command_fn,
653 };
654 /* *INDENT-ON* */
655 
656 static clib_error_t *
658  unformat_input_t * input,
659  vlib_cli_command_t * cmd)
660 {
661  unformat_input_t _line_input, *line_input = &_line_input;
662  ipsec_main_t *im = &ipsec_main;
663  clib_error_t *error;
664  u32 backend_index;
665 
666  error = ipsec_rsc_in_use (im);
667 
668  if (error)
669  return error;
670 
671  /* Get a line of input. */
672  if (!unformat_user (input, unformat_line_input, line_input))
673  return 0;
674 
675  if (unformat (line_input, "ah"))
676  {
677  if (unformat (line_input, "%u", &backend_index))
678  {
679  if (ipsec_select_ah_backend (im, backend_index) < 0)
680  {
681  return clib_error_return (0, "Invalid AH backend index `%u'",
682  backend_index);
683  }
684  }
685  else
686  {
687  return clib_error_return (0, "Invalid backend index `%U'",
688  format_unformat_error, line_input);
689  }
690  }
691  else if (unformat (line_input, "esp"))
692  {
693  if (unformat (line_input, "%u", &backend_index))
694  {
695  if (ipsec_select_esp_backend (im, backend_index) < 0)
696  {
697  return clib_error_return (0, "Invalid ESP backend index `%u'",
698  backend_index);
699  }
700  }
701  else
702  {
703  return clib_error_return (0, "Invalid backend index `%U'",
704  format_unformat_error, line_input);
705  }
706  }
707  else
708  {
709  return clib_error_return (0, "Unknown input `%U'",
710  format_unformat_error, line_input);
711  }
712 
713  return 0;
714 }
715 
716 /* *INDENT-OFF* */
717 VLIB_CLI_COMMAND (ipsec_select_backend_command, static) = {
718  .path = "ipsec select backend",
719  .short_help = "ipsec select backend <ah|esp> <backend index>",
721 };
722 
723 /* *INDENT-ON* */
724 
725 static clib_error_t *
727  unformat_input_t * input,
728  vlib_cli_command_t * cmd)
729 {
732 
733  return (NULL);
734 }
735 
736 /* *INDENT-OFF* */
737 VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
738  .path = "clear ipsec counters",
739  .short_help = "clear ipsec counters",
741 };
742 /* *INDENT-ON* */
743 
744 static clib_error_t *
746  unformat_input_t * input,
747  vlib_cli_command_t * cmd)
748 {
749  unformat_input_t _line_input, *line_input = &_line_input;
751  int rv;
752  u32 num_m_args = 0;
753  u8 ipv4_set = 0;
754  u8 ipv6_set = 0;
755  clib_error_t *error = NULL;
756  ipsec_key_t rck = { 0 };
757  ipsec_key_t lck = { 0 };
758  ipsec_key_t lik = { 0 };
759  ipsec_key_t rik = { 0 };
760 
761  clib_memset (&a, 0, sizeof (a));
762  a.is_add = 1;
763 
764  /* Get a line of input. */
765  if (!unformat_user (input, unformat_line_input, line_input))
766  return 0;
767 
768  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
769  {
770  if (unformat
771  (line_input, "local-ip %U", unformat_ip46_address, &a.local_ip,
772  IP46_TYPE_ANY))
773  {
774  ip46_address_is_ip4 (&a.local_ip) ? (ipv4_set = 1) : (ipv6_set = 1);
775  num_m_args++;
776  }
777  else
778  if (unformat
779  (line_input, "remote-ip %U", unformat_ip46_address, &a.remote_ip,
780  IP46_TYPE_ANY))
781  {
782  ip46_address_is_ip4 (&a.remote_ip) ? (ipv4_set = 1) : (ipv6_set =
783  1);
784  num_m_args++;
785  }
786  else if (unformat (line_input, "local-spi %u", &a.local_spi))
787  num_m_args++;
788  else if (unformat (line_input, "remote-spi %u", &a.remote_spi))
789  num_m_args++;
790  else if (unformat (line_input, "instance %u", &a.show_instance))
791  a.renumber = 1;
792  else if (unformat (line_input, "salt 0x%x", &a.salt))
793  ;
794  else if (unformat (line_input, "udp-encap"))
795  a.udp_encap = 1;
796  else if (unformat (line_input, "use-esn"))
797  a.esn = 1;
798  else if (unformat (line_input, "use-anti-replay"))
799  a.anti_replay = 1;
800  else if (unformat (line_input, "tx-table %u", &a.tx_table_id))
801  ;
802  else
803  if (unformat
804  (line_input, "local-crypto-key %U", unformat_ipsec_key, &lck))
805  ;
806  else
807  if (unformat
808  (line_input, "remote-crypto-key %U", unformat_ipsec_key, &rck))
809  ;
810  else if (unformat (line_input, "crypto-alg %U",
812  ;
813  else
814  if (unformat
815  (line_input, "local-integ-key %U", unformat_ipsec_key, &lik))
816  ;
817  else
818  if (unformat
819  (line_input, "rmote-integ-key %U", unformat_ipsec_key, &rik))
820  ;
821  else if (unformat (line_input, "integ-alg %U",
823  ;
824  else if (unformat (line_input, "del"))
825  a.is_add = 0;
826  else
827  {
828  error = clib_error_return (0, "unknown input `%U'",
829  format_unformat_error, line_input);
830  goto done;
831  }
832  }
833 
834  if (num_m_args < 4)
835  {
836  error = clib_error_return (0, "mandatory argument(s) missing");
837  goto done;
838  }
839 
840  if (ipv4_set && ipv6_set)
841  return clib_error_return (0, "both IPv4 and IPv6 addresses specified");
842 
843  a.is_ip6 = ipv6_set;
844 
845  clib_memcpy (a.local_crypto_key, lck.data, lck.len);
846  a.local_crypto_key_len = lck.len;
847  clib_memcpy (a.remote_crypto_key, rck.data, rck.len);
848  a.remote_crypto_key_len = rck.len;
849 
850  clib_memcpy (a.local_integ_key, lik.data, lik.len);
851  a.local_integ_key_len = lck.len;
852  clib_memcpy (a.remote_integ_key, rik.data, rik.len);
853  a.remote_integ_key_len = rck.len;
854 
855  rv = ipsec_add_del_tunnel_if (&a);
856 
857  switch (rv)
858  {
859  case 0:
860  break;
861  case VNET_API_ERROR_INVALID_VALUE:
862  if (a.is_add)
863  error = clib_error_return (0,
864  "IPSec tunnel interface already exists...");
865  else
866  error = clib_error_return (0, "IPSec tunnel interface not exists...");
867  goto done;
868  default:
869  error = clib_error_return (0, "ipsec_register_interface returned %d",
870  rv);
871  goto done;
872  }
873 
874 done:
875  unformat_free (line_input);
876 
877  return error;
878 }
879 
880 /* *INDENT-OFF* */
881 VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
882  .path = "create ipsec tunnel",
883  .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> "
884  "remote-ip <addr> remote-spi <spi> [instance <inst_num>] [udp-encap] [use-esn] [use-anti-replay] "
885  "[tx-table <table-id>]",
886  .function = create_ipsec_tunnel_command_fn,
887 };
888 /* *INDENT-ON* */
889 
890 static clib_error_t *
892  unformat_input_t * input,
893  vlib_cli_command_t * cmd)
894 {
895  unformat_input_t _line_input, *line_input = &_line_input;
896  ipsec_main_t *im = &ipsec_main;
898  u32 hw_if_index = (u32) ~ 0;
899  u32 alg;
900  u8 *key = 0;
901  clib_error_t *error = NULL;
902 
903  if (!unformat_user (input, unformat_line_input, line_input))
904  return 0;
905 
906  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
907  {
908  if (unformat (line_input, "%U",
909  unformat_vnet_hw_interface, im->vnet_main, &hw_if_index))
910  ;
911  else
912  if (unformat
913  (line_input, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
915  else
916  if (unformat
917  (line_input, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
919  else
920  if (unformat
921  (line_input, "local integ %U", unformat_ipsec_integ_alg, &alg))
923  else
924  if (unformat
925  (line_input, "remote integ %U", unformat_ipsec_integ_alg, &alg))
927  else if (unformat (line_input, "%U", unformat_hex_string, &key))
928  ;
929  else
930  {
931  error = clib_error_return (0, "parse error: '%U'",
932  format_unformat_error, line_input);
933  goto done;
934  }
935  }
936 
937  if (type == IPSEC_IF_SET_KEY_TYPE_NONE)
938  {
939  error = clib_error_return (0, "unknown key type");
940  goto done;
941  }
942 
943  if (alg > 0 && vec_len (key) == 0)
944  {
945  error = clib_error_return (0, "key is not specified");
946  goto done;
947  }
948 
949  if (hw_if_index == (u32) ~ 0)
950  {
951  error = clib_error_return (0, "interface not specified");
952  goto done;
953  }
954 
955  ipsec_set_interface_key (im->vnet_main, hw_if_index, type, alg, key);
956 
957 done:
958  vec_free (key);
959  unformat_free (line_input);
960 
961  return error;
962 }
963 
964 /* *INDENT-OFF* */
965 VLIB_CLI_COMMAND (set_interface_key_command, static) = {
966  .path = "set interface ipsec key",
967  .short_help =
968  "set interface ipsec key <int> <local|remote> <crypto|integ> <key type> <key>",
969  .function = set_interface_key_command_fn,
970 };
971 /* *INDENT-ON* */
972 
973 clib_error_t *
975 {
976  return 0;
977 }
978 
980 
981 
982 /*
983  * fd.io coding-style-patch-verification: ON
984  *
985  * Local Variables:
986  * eval: (c-set-style "gnu")
987  * End:
988  */
static clib_error_t * ipsec_select_backend_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:657
unformat_function_t unformat_vnet_hw_interface
u32 sw_if_index
Definition: ipsec_gre.api:37
ipsec_spd_t * spds
Definition: ipsec.h:93
u32 flags
Definition: vhost_user.h:115
ipsec_tunnel_if_t * tunnel_interfaces
Definition: ipsec.h:100
u32 ipsec_sa_del(u32 id)
Definition: ipsec_sa.c:254
static clib_error_t * set_ipsec_sa_key_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:370
a
Definition: bitmap.h:538
ip46_address_t local_ip
Definition: ipsec_if.h:47
ipsec_integ_alg_t
Definition: ipsec_sa.h:60
unsigned long u64
Definition: types.h:89
ip46_address_range_t laddr
#define NULL
Definition: clib.h:58
static clib_error_t * show_ipsec_spd_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:522
unformat_function_t unformat_hex_string
Definition: format.h:288
int ipsec_policy_mk_type(bool is_outbound, bool is_ipv6, ipsec_policy_action_t action, ipsec_spd_policy_type_t *type)
int ipsec_set_sa_key(u32 id, const ipsec_key_t *ck, const ipsec_key_t *ik)
Definition: ipsec_sa.c:321
static clib_error_t * create_ipsec_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:745
ipsec_protocol_t
Definition: ipsec_sa.h:68
int ipsec_add_del_tunnel_if(ipsec_add_del_tunnel_args_t *args)
Definition: ipsec_if.c:214
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
int ipsec_select_ah_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:195
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static clib_error_t * set_interface_key_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:891
unformat_function_t unformat_vnet_sw_interface
unsigned char u8
Definition: types.h:56
uword * spd_index_by_sw_if_index
Definition: ipsec.h:110
#define clib_memcpy(d, s, n)
Definition: string.h:180
void vlib_clear_combined_counters(vlib_combined_counter_main_t *cm)
Clear a collection of combined counters.
Definition: counter.c:60
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
unformat_function_t unformat_ip4_address
Definition: format.h:70
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
ipsec_main_t ipsec_main
Definition: ipsec.c:28
int ipsec_select_esp_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:218
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
uword unformat_ipsec_crypto_alg(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:95
#define clib_error_return(e, args...)
Definition: error.h:99
port_range_t rport
u8 * format_ipsec_sa(u8 *s, va_list *args)
Definition: ipsec_format.c:267
int ipsec_set_interface_key(vnet_main_t *vnm, u32 hw_if_index, ipsec_if_set_key_type_t type, u8 alg, u8 *key)
Definition: ipsec_if.c:517
unsigned int u32
Definition: types.h:88
static void ipsec_tunnel_show_all(vlib_main_t *vm, ipsec_main_t *im)
Definition: ipsec_cli.c:456
unformat_function_t unformat_line_input
Definition: format.h:282
#define hash_get(h, key)
Definition: hash.h:249
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
vlib_combined_counter_main_t ipsec_spd_policy_counters
Policy packet & bytes counters.
u8 * format_ipsec_spd(u8 *s, va_list *args)
Definition: ipsec_format.c:199
static clib_error_t * ipsec_policy_add_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:220
vnet_main_t * vnet_main
Definition: ipsec.h:106
struct _unformat_input_t unformat_input_t
int ipsec_add_del_policy(vlib_main_t *vm, ipsec_policy_t *policy, int is_add, u32 *stat_index)
Add/Delete a SPD.
static clib_error_t * set_interface_spd_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:27
ip46_address_t remote_ip
Definition: ipsec_if.h:47
u8 * format_ipsec_tunnel(u8 *s, va_list *args)
Definition: ipsec_format.c:333
clib_error_t * ipsec_rsc_in_use(ipsec_main_t *im)
Definition: ipsec.c:178
static clib_error_t * ipsec_show_backends_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:590
ipsec_spd_policy_type_t type
static void ipsec_spd_bindings_show_all(vlib_main_t *vm, ipsec_main_t *im)
Definition: ipsec_cli.c:440
static clib_error_t * clear_ipsec_counters_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:726
#define ip46_address_is_ip4(ip46)
Definition: ip6_packet.h:88
unformat_function_t unformat_ip6_address
Definition: format.h:91
ipsec_crypto_alg_t crypto_alg
Definition: ipsec_if.h:50
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
vlib_main_t * vm
Definition: buffer.c:312
ipsec_ah_backend_t * ah_backends
Definition: ipsec.h:142
clib_error_t * ipsec_cli_init(vlib_main_t *vm)
Definition: ipsec_cli.c:974
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
ipsec_policy_action_t policy
ip46_address_t start
enum ipsec_sad_flags_t_ ipsec_sa_flags_t
uword * sa_index_by_sa_id
Definition: ipsec.h:111
u8 is_outbound
Definition: ipsec.api:92
A Secruity Policy.
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
static void ipsec_spd_show_all(vlib_main_t *vm, ipsec_main_t *im)
Definition: ipsec_cli.c:428
vlib_combined_counter_main_t ipsec_sa_counters
SA packet & bytes counters.
Definition: ipsec_sa.c:25
u32 spi
Definition: ipsec.api:270
u8 is_add
Definition: ipsec_gre.api:36
ipsec_integ_alg_t integ_alg
Definition: ipsec_if.h:55
ipsec_sa_t * sad
Definition: ipsec.h:95
static clib_error_t * show_ipsec_sa_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:491
uword unformat_ipsec_integ_alg(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:127
ipsec_protocol_t protocol
Definition: ipsec_sa.h:148
u8 * format_ipsec_policy_action(u8 *s, va_list *args)
Definition: ipsec_format.c:27
uword unformat_ipsec_policy_action(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:63
unformat_function_t unformat_ip46_address
Definition: format.h:65
int ipsec_sa_add(u32 id, u32 spi, ipsec_protocol_t proto, ipsec_crypto_alg_t crypto_alg, const ipsec_key_t *ck, ipsec_integ_alg_t integ_alg, const ipsec_key_t *ik, ipsec_sa_flags_t flags, u32 tx_table_id, u32 salt, const ip46_address_t *tun_src, const ip46_address_t *tun_dst, u32 *sa_out_index)
Definition: ipsec_sa.c:123
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip46_address_range_t raddr
u64 uword
Definition: types.h:112
static clib_error_t * show_ipsec_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:558
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
ipsec_crypto_alg_t
Definition: ipsec_sa.h:38
typedef key
Definition: ipsec.api:244
static clib_error_t * ipsec_sa_add_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:72
int ipsec_set_interface_spd(vlib_main_t *vm, u32 sw_if_index, u32 spd_id, int is_add)
Bind/attach a SPD to an interface.
Definition: ipsec_spd.c:63
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
port_range_t lport
int ipsec_add_del_spd(vlib_main_t *vm, u32 spd_id, int is_add)
Add/Delete a SPD.
Definition: ipsec_spd.c:20
static clib_error_t * show_ipsec_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:469
ipsec_if_set_key_type_t
Definition: ipsec_if.h:20
u32 id
Definition: udp.api:45
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:538
static clib_error_t * ipsec_spd_add_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:167
uword unformat_ipsec_key(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:238
static void ipsec_sa_show_all(vlib_main_t *vm, ipsec_main_t *im)
Definition: ipsec_cli.c:416
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170