FD.io VPP  v19.01.1-17-ge106252
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  ipsec_main_t *im = &ipsec_main;
77  unformat_input_t _line_input, *line_input = &_line_input;
78  ipsec_sa_t sa;
79  int is_add = ~0;
80  u8 *ck = 0, *ik = 0;
81  clib_error_t *error = NULL;
82 
83  clib_memset (&sa, 0, sizeof (sa));
84  sa.tx_fib_index = ~((u32) 0); /* Only supported for ipsec interfaces */
85 
86  if (!unformat_user (input, unformat_line_input, line_input))
87  return 0;
88 
89  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
90  {
91  if (unformat (line_input, "add %u", &sa.id))
92  is_add = 1;
93  else if (unformat (line_input, "del %u", &sa.id))
94  is_add = 0;
95  else if (unformat (line_input, "spi %u", &sa.spi))
96  ;
97  else if (unformat (line_input, "esp"))
99  else if (unformat (line_input, "ah"))
100  {
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_NONE ||
113  {
114  error = clib_error_return (0, "unsupported crypto-alg: '%U'",
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_NONE ||
128  {
129  error = clib_error_return (0, "unsupported integ-alg: '%U'",
131  sa.integ_alg);
132  goto done;
133  }
134  }
135  else if (unformat (line_input, "tunnel-src %U",
137  sa.is_tunnel = 1;
138  else if (unformat (line_input, "tunnel-dst %U",
140  sa.is_tunnel = 1;
141  else if (unformat (line_input, "tunnel-src %U",
143  {
144  sa.is_tunnel = 1;
145  sa.is_tunnel_ip6 = 1;
146  }
147  else if (unformat (line_input, "tunnel-dst %U",
149  {
150  sa.is_tunnel = 1;
151  sa.is_tunnel_ip6 = 1;
152  }
153  else if (unformat (line_input, "udp-encap"))
154  {
155  sa.udp_encap = 1;
156  }
157  else
158  {
159  error = clib_error_return (0, "parse error: '%U'",
160  format_unformat_error, line_input);
161  goto done;
162  }
163  }
164 
165  if (sa.crypto_key_len > sizeof (sa.crypto_key))
166  sa.crypto_key_len = sizeof (sa.crypto_key);
167 
168  if (sa.integ_key_len > sizeof (sa.integ_key))
169  sa.integ_key_len = sizeof (sa.integ_key);
170 
171  if (ck)
172  memcpy (sa.crypto_key, ck, sa.crypto_key_len);
173 
174  if (ik)
175  memcpy (sa.integ_key, ik, sa.integ_key_len);
176 
177  if (is_add)
178  {
179  error = ipsec_check_support_cb (im, &sa);
180  if (error)
181  goto done;
182  }
183 
184  ipsec_add_del_sa (vm, &sa, is_add);
185 
186 done:
187  unformat_free (line_input);
188 
189  return error;
190 }
191 
192 /* *INDENT-OFF* */
193 VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
194  .path = "ipsec sa",
195  .short_help =
196  "ipsec sa [add|del]",
197  .function = ipsec_sa_add_del_command_fn,
198 };
199 /* *INDENT-ON* */
200 
201 static clib_error_t *
203  unformat_input_t * input,
204  vlib_cli_command_t * cmd)
205 {
206  unformat_input_t _line_input, *line_input = &_line_input;
207  u32 spd_id = ~0;
208  int is_add = ~0;
209  clib_error_t *error = NULL;
210 
211  if (!unformat_user (input, unformat_line_input, line_input))
212  return 0;
213 
214  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
215  {
216  if (unformat (line_input, "add"))
217  is_add = 1;
218  else if (unformat (line_input, "del"))
219  is_add = 0;
220  else if (unformat (line_input, "%u", &spd_id))
221  ;
222  else
223  {
224  error = clib_error_return (0, "parse error: '%U'",
225  format_unformat_error, line_input);
226  goto done;
227  }
228  }
229 
230  if (spd_id == ~0)
231  {
232  error = clib_error_return (0, "please specify SPD ID");
233  goto done;
234  }
235 
236  ipsec_add_del_spd (vm, spd_id, is_add);
237 
238 done:
239  unformat_free (line_input);
240 
241  return error;
242 }
243 
244 /* *INDENT-OFF* */
245 VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
246  .path = "ipsec spd",
247  .short_help =
248  "ipsec spd [add|del] <id>",
249  .function = ipsec_spd_add_del_command_fn,
250 };
251 /* *INDENT-ON* */
252 
253 
254 static clib_error_t *
256  unformat_input_t * input,
257  vlib_cli_command_t * cmd)
258 {
259  unformat_input_t _line_input, *line_input = &_line_input;
260  ipsec_policy_t p;
261  int is_add = 0;
262  int is_ip_any = 1;
263  u32 tmp, tmp2;
264  clib_error_t *error = NULL;
265 
266  clib_memset (&p, 0, sizeof (p));
267  p.lport.stop = p.rport.stop = ~0;
268  p.laddr.stop.ip4.as_u32 = p.raddr.stop.ip4.as_u32 = (u32) ~ 0;
269  p.laddr.stop.ip6.as_u64[0] = p.laddr.stop.ip6.as_u64[1] = (u64) ~ 0;
270  p.raddr.stop.ip6.as_u64[0] = p.raddr.stop.ip6.as_u64[1] = (u64) ~ 0;
271 
272  if (!unformat_user (input, unformat_line_input, line_input))
273  return 0;
274 
275  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
276  {
277  if (unformat (line_input, "add"))
278  is_add = 1;
279  else if (unformat (line_input, "del"))
280  is_add = 0;
281  else if (unformat (line_input, "spd %u", &p.id))
282  ;
283  else if (unformat (line_input, "inbound"))
284  p.is_outbound = 0;
285  else if (unformat (line_input, "outbound"))
286  p.is_outbound = 1;
287  else if (unformat (line_input, "priority %d", &p.priority))
288  ;
289  else if (unformat (line_input, "protocol %u", &tmp))
290  p.protocol = (u8) tmp;
291  else
292  if (unformat
293  (line_input, "action %U", unformat_ipsec_policy_action,
294  &p.policy))
295  {
296  if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
297  {
298  error = clib_error_return (0, "unsupported action: 'resolve'");
299  goto done;
300  }
301  }
302  else if (unformat (line_input, "sa %u", &p.sa_id))
303  ;
304  else if (unformat (line_input, "local-ip-range %U - %U",
307  is_ip_any = 0;
308  else if (unformat (line_input, "remote-ip-range %U - %U",
311  is_ip_any = 0;
312  else if (unformat (line_input, "local-ip-range %U - %U",
315  {
316  p.is_ipv6 = 1;
317  is_ip_any = 0;
318  }
319  else if (unformat (line_input, "remote-ip-range %U - %U",
322  {
323  p.is_ipv6 = 1;
324  is_ip_any = 0;
325  }
326  else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
327  {
328  p.lport.start = tmp;
329  p.lport.stop = tmp2;
330  }
331  else
332  if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
333  {
334  p.rport.start = tmp;
335  p.rport.stop = tmp2;
336  }
337  else
338  {
339  error = clib_error_return (0, "parse error: '%U'",
340  format_unformat_error, line_input);
341  goto done;
342  }
343  }
344 
345  /* Check if SA is for IPv6/AH which is not supported. Return error if TRUE. */
346  if (p.sa_id)
347  {
348  uword *p1;
349  ipsec_main_t *im = &ipsec_main;
350  ipsec_sa_t *sa = 0;
351  p1 = hash_get (im->sa_index_by_sa_id, p.sa_id);
352  if (!p1)
353  {
354  error =
355  clib_error_return (0, "SA with index %u not found", p.sa_id);
356  goto done;
357  }
358  sa = pool_elt_at_index (im->sad, p1[0]);
359  if (sa && sa->protocol == IPSEC_PROTOCOL_AH && is_add && p.is_ipv6)
360  {
361  error = clib_error_return (0, "AH not supported for IPV6: '%U'",
362  format_unformat_error, line_input);
363  goto done;
364  }
365  }
366  ipsec_add_del_policy (vm, &p, is_add);
367  if (is_ip_any)
368  {
369  p.is_ipv6 = 1;
370  ipsec_add_del_policy (vm, &p, is_add);
371  }
372 
373 done:
374  unformat_free (line_input);
375 
376  return error;
377 }
378 
379 /* *INDENT-OFF* */
380 VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
381  .path = "ipsec policy",
382  .short_help =
383  "ipsec policy [add|del] spd <id> priority <n> ",
385 };
386 /* *INDENT-ON* */
387 
388 static clib_error_t *
390  unformat_input_t * input,
391  vlib_cli_command_t * cmd)
392 {
393  unformat_input_t _line_input, *line_input = &_line_input;
394  ipsec_sa_t sa;
395  u8 *ck = 0, *ik = 0;
396  clib_error_t *error = NULL;
397 
398  clib_memset (&sa, 0, sizeof (sa));
399 
400  if (!unformat_user (input, unformat_line_input, line_input))
401  return 0;
402 
403  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
404  {
405  if (unformat (line_input, "%u", &sa.id))
406  ;
407  else
408  if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
409  sa.crypto_key_len = vec_len (ck);
410  else
411  if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
412  sa.integ_key_len = vec_len (ik);
413  else
414  {
415  error = clib_error_return (0, "parse error: '%U'",
416  format_unformat_error, line_input);
417  goto done;
418  }
419  }
420 
421  if (sa.crypto_key_len > sizeof (sa.crypto_key))
422  sa.crypto_key_len = sizeof (sa.crypto_key);
423 
424  if (sa.integ_key_len > sizeof (sa.integ_key))
425  sa.integ_key_len = sizeof (sa.integ_key);
426 
427  if (ck)
428  strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
429 
430  if (ik)
431  strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
432 
433  ipsec_set_sa_key (vm, &sa);
434 
435 done:
436  unformat_free (line_input);
437 
438  return error;
439 }
440 
441 /* *INDENT-OFF* */
442 VLIB_CLI_COMMAND (set_ipsec_sa_key_command, static) = {
443  .path = "set ipsec sa",
444  .short_help =
445  "set ipsec sa <id> crypto-key <key> integ-key <key>",
446  .function = set_ipsec_sa_key_command_fn,
447 };
448 /* *INDENT-ON* */
449 
450 static clib_error_t *
452  unformat_input_t * input, vlib_cli_command_t * cmd)
453 {
454  ipsec_spd_t *spd;
455  ipsec_sa_t *sa;
456  ipsec_policy_t *p;
457  ipsec_main_t *im = &ipsec_main;
458  u32 *i;
461  u8 *protocol = NULL;
462  u8 *policy = NULL;
463  u32 tx_table_id;
464 
465  /* *INDENT-OFF* */
466  pool_foreach (sa, im->sad, ({
467  if (sa->id) {
468  vlib_cli_output(vm, "sa %u spi %u mode %s protocol %s%s%s%s", sa->id, sa->spi,
469  sa->is_tunnel ? "tunnel" : "transport",
470  sa->protocol ? "esp" : "ah",
471  sa->udp_encap ? " udp-encap-enabled" : "",
472  sa->use_anti_replay ? " anti-replay" : "",
473  sa->use_esn ? " extended-sequence-number" : "");
474  if (sa->protocol == IPSEC_PROTOCOL_ESP) {
475  vlib_cli_output(vm, " crypto alg %U%s%U integrity alg %U%s%U",
476  format_ipsec_crypto_alg, sa->crypto_alg,
477  sa->crypto_alg ? " key " : "",
478  format_hex_bytes, sa->crypto_key, sa->crypto_key_len,
479  format_ipsec_integ_alg, sa->integ_alg,
480  sa->integ_alg ? " key " : "",
481  format_hex_bytes, sa->integ_key, sa->integ_key_len);
482  }
483  if (sa->is_tunnel && sa->is_tunnel_ip6) {
484  vlib_cli_output(vm, " tunnel src %U dst %U",
485  format_ip6_address, &sa->tunnel_src_addr.ip6,
486  format_ip6_address, &sa->tunnel_dst_addr.ip6);
487  } else if (sa->is_tunnel) {
488  vlib_cli_output(vm, " tunnel src %U dst %U",
489  format_ip4_address, &sa->tunnel_src_addr.ip4,
490  format_ip4_address, &sa->tunnel_dst_addr.ip4);
491  }
492  }
493  }));
494  /* *INDENT-ON* */
495 
496  /* *INDENT-OFF* */
497  pool_foreach (spd, im->spds, ({
498  vlib_cli_output(vm, "spd %u", spd->id);
499 
500  vlib_cli_output(vm, " outbound policies");
501  vec_foreach(i, spd->ipv4_outbound_policies)
502  {
503  p = pool_elt_at_index(spd->policies, *i);
504  vec_reset_length(protocol);
505  vec_reset_length(policy);
506  if (p->protocol) {
507  protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
508  } else {
509  protocol = format(protocol, "any");
510  }
511  if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
512  policy = format(policy, " sa %u", p->sa_id);
513  }
514 
515  vlib_cli_output(vm, " priority %d action %U protocol %v%v",
516  p->priority, format_ipsec_policy_action, p->policy,
517  protocol, policy);
518  vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
519  format_ip4_address, &p->laddr.start.ip4,
520  format_ip4_address, &p->laddr.stop.ip4,
521  p->lport.start, p->lport.stop);
522  vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
523  format_ip4_address, &p->raddr.start.ip4,
524  format_ip4_address, &p->raddr.stop.ip4,
525  p->rport.start, p->rport.stop);
526  vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
527  p->counter.bytes);
528  };
529  vec_foreach(i, spd->ipv6_outbound_policies)
530  {
531  p = pool_elt_at_index(spd->policies, *i);
532  vec_reset_length(protocol);
533  vec_reset_length(policy);
534  if (p->protocol) {
535  protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
536  } else {
537  protocol = format(protocol, "any");
538  }
539  if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
540  policy = format(policy, " sa %u", p->sa_id);
541  }
542  vlib_cli_output(vm, " priority %d action %U protocol %v%v",
543  p->priority, format_ipsec_policy_action, p->policy,
544  protocol, policy);
545  vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
546  format_ip6_address, &p->laddr.start.ip6,
547  format_ip6_address, &p->laddr.stop.ip6,
548  p->lport.start, p->lport.stop);
549  vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
550  format_ip6_address, &p->raddr.start.ip6,
551  format_ip6_address, &p->raddr.stop.ip6,
552  p->rport.start, p->rport.stop);
553  vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
554  p->counter.bytes);
555  };
556  vlib_cli_output(vm, " inbound policies");
557  vec_foreach(i, spd->ipv4_inbound_protect_policy_indices)
558  {
559  p = pool_elt_at_index(spd->policies, *i);
560  vec_reset_length(protocol);
561  vec_reset_length(policy);
562  if (p->protocol) {
563  protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
564  } else {
565  protocol = format(protocol, "any");
566  }
567  if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
568  policy = format(policy, " sa %u", p->sa_id);
569  }
570  vlib_cli_output(vm, " priority %d action %U protocol %v%v",
571  p->priority, format_ipsec_policy_action, p->policy,
572  protocol, policy);
573  vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
574  format_ip4_address, &p->laddr.start.ip4,
575  format_ip4_address, &p->laddr.stop.ip4,
576  p->lport.start, p->lport.stop);
577  vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
578  format_ip4_address, &p->raddr.start.ip4,
579  format_ip4_address, &p->raddr.stop.ip4,
580  p->rport.start, p->rport.stop);
581  vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
582  p->counter.bytes);
583  };
584  vec_foreach(i, spd->ipv4_inbound_policy_discard_and_bypass_indices)
585  {
586  p = pool_elt_at_index(spd->policies, *i);
587  vec_reset_length(protocol);
588  vec_reset_length(policy);
589  if (p->protocol) {
590  protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
591  } else {
592  protocol = format(protocol, "any");
593  }
594  if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
595  policy = format(policy, " sa %u", p->sa_id);
596  }
597  vlib_cli_output(vm, " priority %d action %U protocol %v%v",
598  p->priority, format_ipsec_policy_action, p->policy,
599  protocol, policy);
600  vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
601  format_ip4_address, &p->laddr.start.ip4,
602  format_ip4_address, &p->laddr.stop.ip4,
603  p->lport.start, p->lport.stop);
604  vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
605  format_ip4_address, &p->raddr.start.ip4,
606  format_ip4_address, &p->raddr.stop.ip4,
607  p->rport.start, p->rport.stop);
608  vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
609  p->counter.bytes);
610  };
611  vec_foreach(i, spd->ipv6_inbound_protect_policy_indices)
612  {
613  p = pool_elt_at_index(spd->policies, *i);
614  vec_reset_length(protocol);
615  vec_reset_length(policy);
616  if (p->protocol) {
617  protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
618  } else {
619  protocol = format(protocol, "any");
620  }
621  if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
622  policy = format(policy, " sa %u", p->sa_id);
623  }
624  vlib_cli_output(vm, " priority %d action %U protocol %v%v",
625  p->priority, format_ipsec_policy_action, p->policy,
626  protocol, policy);
627  vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
628  format_ip6_address, &p->laddr.start.ip6,
629  format_ip6_address, &p->laddr.stop.ip6,
630  p->lport.start, p->lport.stop);
631  vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
632  format_ip6_address, &p->raddr.start.ip6,
633  format_ip6_address, &p->raddr.stop.ip6,
634  p->rport.start, p->rport.stop);
635  vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
636  p->counter.bytes);
637  };
638  vec_foreach(i, spd->ipv6_inbound_policy_discard_and_bypass_indices)
639  {
640  p = pool_elt_at_index(spd->policies, *i);
641  vec_reset_length(protocol);
642  vec_reset_length(policy);
643  if (p->protocol) {
644  protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
645  } else {
646  protocol = format(protocol, "any");
647  }
648  if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
649  policy = format(policy, " sa %u", p->sa_id);
650  }
651  vlib_cli_output(vm, " priority %d action %U protocol %v%v",
652  p->priority, format_ipsec_policy_action, p->policy,
653  protocol, policy);
654  vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
655  format_ip6_address, &p->laddr.start.ip6,
656  format_ip6_address, &p->laddr.stop.ip6,
657  p->lport.start, p->lport.stop);
658  vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
659  format_ip6_address, &p->raddr.start.ip6,
660  format_ip6_address, &p->raddr.stop.ip6,
661  p->rport.start, p->rport.stop);
662  vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
663  p->counter.bytes);
664  };
665  }));
666  /* *INDENT-ON* */
667 
668  vlib_cli_output (vm, "tunnel interfaces");
669  /* *INDENT-OFF* */
670  pool_foreach (t, im->tunnel_interfaces, ({
671  if (t->hw_if_index == ~0)
672  continue;
673  hi = vnet_get_hw_interface (im->vnet_main, t->hw_if_index);
674  vlib_cli_output(vm, " %s seq", hi->name);
675  sa = pool_elt_at_index(im->sad, t->output_sa_index);
676 
677  tx_table_id = fib_table_get_table_id(sa->tx_fib_index, FIB_PROTOCOL_IP4);
678 
679  vlib_cli_output(vm, " seq %u seq-hi %u esn %u anti-replay %u udp-encap %u tx-table %u",
680  sa->seq, sa->seq_hi, sa->use_esn, sa->use_anti_replay, sa->udp_encap, tx_table_id);
681  vlib_cli_output(vm, " local-spi %u local-ip %U", sa->spi,
682  format_ip4_address, &sa->tunnel_src_addr.ip4);
683  vlib_cli_output(vm, " local-crypto %U %U",
684  format_ipsec_crypto_alg, sa->crypto_alg,
685  format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
686  vlib_cli_output(vm, " local-integrity %U %U",
687  format_ipsec_integ_alg, sa->integ_alg,
688  format_hex_bytes, sa->integ_key, sa->integ_key_len);
689  sa = pool_elt_at_index(im->sad, t->input_sa_index);
690  vlib_cli_output(vm, " last-seq %u last-seq-hi %u esn %u anti-replay %u window %U",
691  sa->last_seq, sa->last_seq_hi, sa->use_esn,
692  sa->use_anti_replay,
693  format_ipsec_replay_window, sa->replay_window);
694  vlib_cli_output(vm, " remote-spi %u remote-ip %U", sa->spi,
695  format_ip4_address, &sa->tunnel_src_addr.ip4);
696  vlib_cli_output(vm, " remote-crypto %U %U",
697  format_ipsec_crypto_alg, sa->crypto_alg,
698  format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
699  vlib_cli_output(vm, " remote-integrity %U %U",
700  format_ipsec_integ_alg, sa->integ_alg,
701  format_hex_bytes, sa->integ_key, sa->integ_key_len);
702  }));
703  vec_free(policy);
704  vec_free(protocol);
705  /* *INDENT-ON* */
706  return 0;
707 }
708 
709 /* *INDENT-OFF* */
711  .path = "show ipsec",
712  .short_help = "show ipsec [backends]",
713  .function = show_ipsec_command_fn,
714 };
715 /* *INDENT-ON* */
716 
717 static clib_error_t *
719  unformat_input_t * input,
720  vlib_cli_command_t * cmd)
721 {
722  ipsec_main_t *im = &ipsec_main;
723  u32 verbose = 0;
724 
725  (void) unformat (input, "verbose %u", &verbose);
726 
727  vlib_cli_output (vm, "IPsec AH backends available:");
728  u8 *s = format (NULL, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
729  ipsec_ah_backend_t *ab;
730  /* *INDENT-OFF* */
731  pool_foreach (ab, im->ah_backends, {
732  s = format (s, "%=25s %=25u %=10s\n", ab->name, ab - im->ah_backends,
733  ab - im->ah_backends == im->ah_current_backend ? "yes" : "no");
734  if (verbose) {
735  vlib_node_t *n;
736  n = vlib_get_node (vm, ab->ah4_encrypt_node_index);
737  s = format (s, " enc4 %s (next %d)\n", n->name, ab->ah4_encrypt_next_index);
738  n = vlib_get_node (vm, ab->ah4_decrypt_node_index);
739  s = format (s, " dec4 %s (next %d)\n", n->name, ab->ah4_decrypt_next_index);
740  n = vlib_get_node (vm, ab->ah6_encrypt_node_index);
741  s = format (s, " enc6 %s (next %d)\n", n->name, ab->ah6_encrypt_next_index);
742  n = vlib_get_node (vm, ab->ah6_decrypt_node_index);
743  s = format (s, " dec6 %s (next %d)\n", n->name, ab->ah6_decrypt_next_index);
744  }
745  });
746  /* *INDENT-ON* */
747  vlib_cli_output (vm, "%v", s);
748  _vec_len (s) = 0;
749  vlib_cli_output (vm, "IPsec ESP backends available:");
750  s = format (s, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
752  /* *INDENT-OFF* */
753  pool_foreach (eb, im->esp_backends, {
754  s = format (s, "%=25s %=25u %=10s\n", eb->name, eb - im->esp_backends,
755  eb - im->esp_backends == im->esp_current_backend ? "yes"
756  : "no");
757  if (verbose) {
758  vlib_node_t *n;
759  n = vlib_get_node (vm, eb->esp4_encrypt_node_index);
760  s = format (s, " enc4 %s (next %d)\n", n->name, eb->esp4_encrypt_next_index);
761  n = vlib_get_node (vm, eb->esp4_decrypt_node_index);
762  s = format (s, " dec4 %s (next %d)\n", n->name, eb->esp4_decrypt_next_index);
763  n = vlib_get_node (vm, eb->esp6_encrypt_node_index);
764  s = format (s, " enc6 %s (next %d)\n", n->name, eb->esp6_encrypt_next_index);
765  n = vlib_get_node (vm, eb->esp6_decrypt_node_index);
766  s = format (s, " dec6 %s (next %d)\n", n->name, eb->esp6_decrypt_next_index);
767  }
768  });
769  /* *INDENT-ON* */
770  vlib_cli_output (vm, "%v", s);
771 
772  vec_free (s);
773  return 0;
774 }
775 
776 /* *INDENT-OFF* */
778  .path = "show ipsec backends",
779  .short_help = "show ipsec backends",
780  .function = ipsec_show_backends_command_fn,
781 };
782 /* *INDENT-ON* */
783 
784 static clib_error_t *
786  unformat_input_t * input,
787  vlib_cli_command_t * cmd)
788 {
789  u32 backend_index;
790  ipsec_main_t *im = &ipsec_main;
791 
792  if (pool_elts (im->sad) > 0)
793  {
794  return clib_error_return (0,
795  "Cannot change IPsec backend, while %u SA entries are configured",
796  pool_elts (im->sad));
797  }
798 
799  unformat_input_t _line_input, *line_input = &_line_input;
800  /* Get a line of input. */
801  if (!unformat_user (input, unformat_line_input, line_input))
802  return 0;
803 
804  if (unformat (line_input, "ah"))
805  {
806  if (unformat (line_input, "%u", &backend_index))
807  {
808  if (ipsec_select_ah_backend (im, backend_index) < 0)
809  {
810  return clib_error_return (0, "Invalid AH backend index `%u'",
811  backend_index);
812  }
813  }
814  else
815  {
816  return clib_error_return (0, "Invalid backend index `%U'",
817  format_unformat_error, line_input);
818  }
819  }
820  else if (unformat (line_input, "esp"))
821  {
822  if (unformat (line_input, "%u", &backend_index))
823  {
824  if (ipsec_select_esp_backend (im, backend_index) < 0)
825  {
826  return clib_error_return (0, "Invalid ESP backend index `%u'",
827  backend_index);
828  }
829  }
830  else
831  {
832  return clib_error_return (0, "Invalid backend index `%U'",
833  format_unformat_error, line_input);
834  }
835  }
836  else
837  {
838  return clib_error_return (0, "Unknown input `%U'",
839  format_unformat_error, line_input);
840  }
841 
842  return 0;
843 }
844 
845 /* *INDENT-OFF* */
847  .path = "ipsec select backend",
848  .short_help = "ipsec select backend <ah|esp> <backend index>",
850 };
851 
852 /* *INDENT-ON* */
853 
854 static clib_error_t *
856  unformat_input_t * input,
857  vlib_cli_command_t * cmd)
858 {
859  ipsec_main_t *im = &ipsec_main;
860  ipsec_spd_t *spd;
861  ipsec_policy_t *p;
862 
863  /* *INDENT-OFF* */
864  pool_foreach (spd, im->spds, ({
865  pool_foreach(p, spd->policies, ({
866  p->counter.packets = p->counter.bytes = 0;
867  }));
868  }));
869  /* *INDENT-ON* */
870 
871  return 0;
872 }
873 
874 /* *INDENT-OFF* */
876  .path = "clear ipsec counters",
877  .short_help = "clear ipsec counters",
879 };
880 /* *INDENT-ON* */
881 
882 static clib_error_t *
884  unformat_input_t * input,
885  vlib_cli_command_t * cmd)
886 {
887  unformat_input_t _line_input, *line_input = &_line_input;
889  int rv;
890  u32 num_m_args = 0;
891  clib_error_t *error = NULL;
892 
893  clib_memset (&a, 0, sizeof (a));
894  a.is_add = 1;
895 
896  /* Get a line of input. */
897  if (!unformat_user (input, unformat_line_input, line_input))
898  return 0;
899 
900  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
901  {
902  if (unformat
903  (line_input, "local-ip %U", unformat_ip4_address, &a.local_ip))
904  num_m_args++;
905  else
906  if (unformat
907  (line_input, "remote-ip %U", unformat_ip4_address, &a.remote_ip))
908  num_m_args++;
909  else if (unformat (line_input, "local-spi %u", &a.local_spi))
910  num_m_args++;
911  else if (unformat (line_input, "remote-spi %u", &a.remote_spi))
912  num_m_args++;
913  else if (unformat (line_input, "instance %u", &a.show_instance))
914  a.renumber = 1;
915  else if (unformat (line_input, "del"))
916  a.is_add = 0;
917  else if (unformat (line_input, "udp-encap"))
918  a.udp_encap = 1;
919  else if (unformat (line_input, "tx-table %u", &a.tx_table_id))
920  ;
921  else
922  {
923  error = clib_error_return (0, "unknown input `%U'",
924  format_unformat_error, line_input);
925  goto done;
926  }
927  }
928 
929  if (num_m_args < 4)
930  {
931  error = clib_error_return (0, "mandatory argument(s) missing");
932  goto done;
933  }
934 
935  rv = ipsec_add_del_tunnel_if (&a);
936 
937  switch (rv)
938  {
939  case 0:
940  break;
941  case VNET_API_ERROR_INVALID_VALUE:
942  if (a.is_add)
943  error = clib_error_return (0,
944  "IPSec tunnel interface already exists...");
945  else
946  error = clib_error_return (0, "IPSec tunnel interface not exists...");
947  goto done;
948  default:
949  error = clib_error_return (0, "ipsec_register_interface returned %d",
950  rv);
951  goto done;
952  }
953 
954 done:
955  unformat_free (line_input);
956 
957  return error;
958 }
959 
960 /* *INDENT-OFF* */
962  .path = "create ipsec tunnel",
963  .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> "
964  "remote-ip <addr> remote-spi <spi> [instance <inst_num>] [udp-encap] "
965  "[tx-table <table-id>]",
966  .function = create_ipsec_tunnel_command_fn,
967 };
968 /* *INDENT-ON* */
969 
970 static clib_error_t *
972  unformat_input_t * input,
973  vlib_cli_command_t * cmd)
974 {
975  unformat_input_t _line_input, *line_input = &_line_input;
976  ipsec_main_t *im = &ipsec_main;
978  u32 hw_if_index = (u32) ~ 0;
979  u32 alg;
980  u8 *key = 0;
981  clib_error_t *error = NULL;
982 
983  if (!unformat_user (input, unformat_line_input, line_input))
984  return 0;
985 
986  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
987  {
988  if (unformat (line_input, "%U",
989  unformat_vnet_hw_interface, im->vnet_main, &hw_if_index))
990  ;
991  else
992  if (unformat
993  (line_input, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
995  else
996  if (unformat
997  (line_input, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
999  else
1000  if (unformat
1001  (line_input, "local integ %U", unformat_ipsec_integ_alg, &alg))
1003  else
1004  if (unformat
1005  (line_input, "remote integ %U", unformat_ipsec_integ_alg, &alg))
1007  else if (unformat (line_input, "%U", unformat_hex_string, &key))
1008  ;
1009  else
1010  {
1011  error = clib_error_return (0, "parse error: '%U'",
1012  format_unformat_error, line_input);
1013  goto done;
1014  }
1015  }
1016 
1017  if (type == IPSEC_IF_SET_KEY_TYPE_NONE)
1018  {
1019  error = clib_error_return (0, "unknown key type");
1020  goto done;
1021  }
1022 
1023  if (alg > 0 && vec_len (key) == 0)
1024  {
1025  error = clib_error_return (0, "key is not specified");
1026  goto done;
1027  }
1028 
1029  if (hw_if_index == (u32) ~ 0)
1030  {
1031  error = clib_error_return (0, "interface not specified");
1032  goto done;
1033  }
1034 
1035  ipsec_set_interface_key (im->vnet_main, hw_if_index, type, alg, key);
1036 
1037 done:
1038  vec_free (key);
1039  unformat_free (line_input);
1040 
1041  return error;
1042 }
1043 
1044 /* *INDENT-OFF* */
1046  .path = "set interface ipsec key",
1047  .short_help =
1048  "set interface ipsec key <int> <local|remote> <crypto|integ> <key type> <key>",
1049  .function = set_interface_key_command_fn,
1050 };
1051 /* *INDENT-ON* */
1052 
1053 clib_error_t *
1055 {
1056  return 0;
1057 }
1058 
1060 
1061 
1062 /*
1063  * fd.io coding-style-patch-verification: ON
1064  *
1065  * Local Variables:
1066  * eval: (c-set-style "gnu")
1067  * End:
1068  */
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:785
unformat_function_t unformat_vnet_hw_interface
ip46_address_t stop
Definition: ipsec.h:158
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:478
vmrglw vmrglh hi
format_function_t format_ip_protocol
Definition: format.h:45
ipsec_spd_t * spds
Definition: ipsec.h:352
u16 stop
Definition: ipsec.h:163
int ipsec_add_del_policy(vlib_main_t *vm, ipsec_policy_t *policy, int is_add)
Definition: ipsec.c:154
ip46_address_t tunnel_src_addr
Definition: ipsec.h:139
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:389
a
Definition: bitmap.h:538
u32 id
Definition: ipsec.h:121
i32 priority
Definition: ipsec.h:211
unsigned long u64
Definition: types.h:89
int ipsec_set_interface_spd(vlib_main_t *vm, u32 sw_if_index, u32 spd_id, int is_add)
Definition: ipsec.c:44
#define NULL
Definition: clib.h:58
unformat_function_t unformat_hex_string
Definition: format.h:288
ipsec_integ_alg_t integ_alg
Definition: ipsec.h:129
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:883
u8 is_tunnel
Definition: ipsec.h:136
int i
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:672
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
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:971
unformat_function_t unformat_vnet_sw_interface
unsigned char u8
Definition: types.h:56
static vlib_cli_command_t set_interface_key_command
(constructor) VLIB_CLI_COMMAND (set_interface_key_command)
Definition: ipsec_cli.c:1045
u8 crypto_key[128]
Definition: ipsec.h:127
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
int ipsec_add_del_spd(vlib_main_t *vm, u32 spd_id, int is_add)
Definition: ipsec.c:93
u32 spi
Definition: ipsec.h:122
port_range_t lport
Definition: ipsec.h:219
static vlib_cli_command_t ipsec_show_backends_command
(constructor) VLIB_CLI_COMMAND (ipsec_show_backends_command)
Definition: ipsec_cli.c:777
format_function_t format_ip4_address
Definition: format.h:75
u8 integ_key[128]
Definition: ipsec.h:131
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:490
unformat_function_t unformat_ip4_address
Definition: format.h:70
static vlib_cli_command_t show_ipsec_command
(constructor) VLIB_CLI_COMMAND (show_ipsec_command)
Definition: ipsec_cli.c:710
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
ipsec_main_t ipsec_main
Definition: ipsec.c:30
u32 sw_if_index
Definition: vxlan_gbp.api:37
uword unformat_ipsec_integ_alg(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:108
int ipsec_select_esp_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:693
ip4_address_t remote_ip
Definition: ipsec.h:171
u16 start
Definition: ipsec.h:163
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
u8 * format_ipsec_crypto_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:58
u8 udp_encap
Definition: ipsec.h:138
unformat_function_t unformat_line_input
Definition: format.h:282
#define hash_get(h, key)
Definition: hash.h:249
u32 tx_fib_index
Definition: ipsec.h:142
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:511
static vlib_cli_command_t create_ipsec_tunnel_command
(constructor) VLIB_CLI_COMMAND (create_ipsec_tunnel_command)
Definition: ipsec_cli.c:961
u8 is_tunnel_ip6
Definition: ipsec.h:137
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:255
vnet_main_t * vnet_main
Definition: ipsec.h:365
clib_error_t * ipsec_check_support_cb(ipsec_main_t *im, ipsec_sa_t *sa)
Definition: ipsec.c:579
struct _unformat_input_t unformat_input_t
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
uword unformat_ipsec_crypto_alg(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:76
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:718
ip46_address_range_t laddr
Definition: ipsec.h:216
ip46_address_t tunnel_dst_addr
Definition: ipsec.h:140
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:855
unformat_function_t unformat_ip6_address
Definition: format.h:91
ipsec_if_set_key_type_t
Definition: ipsec.h:199
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
format_function_t format_ip6_address
Definition: format.h:93
vlib_main_t * vm
Definition: buffer.c:301
ipsec_ah_backend_t * ah_backends
Definition: ipsec.h:398
int ipsec_add_del_sa(vlib_main_t *vm, ipsec_sa_t *new_sa, int is_add)
Definition: ipsec.c:432
clib_error_t * ipsec_cli_init(vlib_main_t *vm)
Definition: ipsec_cli.c:1054
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
ip46_address_t start
Definition: ipsec.h:158
uword * sa_index_by_sa_id
Definition: ipsec.h:373
int ipsec_set_sa_key(vlib_main_t *vm, ipsec_sa_t *sa_update)
Definition: ipsec.c:477
port_range_t rport
Definition: ipsec.h:220
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
ip46_address_range_t raddr
Definition: ipsec.h:217
static vlib_cli_command_t ipsec_select_backend_command
(constructor) VLIB_CLI_COMMAND (ipsec_select_backend_command)
Definition: ipsec_cli.c:846
ip4_address_t local_ip
Definition: ipsec.h:171
ipsec_sa_t * sad
Definition: ipsec.h:353
u8 integ_key_len
Definition: ipsec.h:130
ipsec_protocol_t protocol
Definition: ipsec.h:123
uword unformat_ipsec_policy_action(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:44
u8 * format_ipsec_integ_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:90
u8 crypto_key_len
Definition: ipsec.h:126
u8 * format_ipsec_policy_action(u8 *s, va_list *args)
Definition: ipsec_format.c:26
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u8 is_outbound
Definition: ipsec.h:212
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
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
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
ipsec_crypto_alg_t crypto_alg
Definition: ipsec.h:125
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:451
#define vec_foreach(var, vec)
Vector iterator.
int ipsec_add_del_tunnel_if(ipsec_add_del_tunnel_args_t *args)
Definition: ipsec_if.c:246
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:202
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
static vlib_cli_command_t clear_ipsec_counters_command
(constructor) VLIB_CLI_COMMAND (clear_ipsec_counters_command)
Definition: ipsec_cli.c:875
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128