Line data Source code
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 : #include <vnet/ipip/ipip.h>
24 :
25 : #include <vnet/ipsec/ipsec.h>
26 : #include <vnet/ipsec/ipsec_tun.h>
27 :
28 : static clib_error_t *
29 0 : set_interface_spd_command_fn (vlib_main_t * vm,
30 : unformat_input_t * input,
31 : vlib_cli_command_t * cmd)
32 : {
33 0 : unformat_input_t _line_input, *line_input = &_line_input;
34 0 : ipsec_main_t *im = &ipsec_main;
35 0 : u32 sw_if_index = (u32) ~ 0;
36 : u32 spd_id;
37 0 : int is_add = 1;
38 0 : clib_error_t *error = NULL;
39 : int err;
40 :
41 0 : if (!unformat_user (input, unformat_line_input, line_input))
42 0 : return 0;
43 :
44 0 : if (unformat
45 : (line_input, "%U %u", unformat_vnet_sw_interface, im->vnet_main,
46 : &sw_if_index, &spd_id))
47 : ;
48 0 : else if (unformat (line_input, "del"))
49 0 : is_add = 0;
50 : else
51 : {
52 0 : error = clib_error_return (0, "parse error: '%U'",
53 : format_unformat_error, line_input);
54 0 : goto done;
55 : }
56 :
57 0 : err = ipsec_set_interface_spd (vm, sw_if_index, spd_id, is_add);
58 0 : switch (err)
59 : {
60 0 : case VNET_API_ERROR_SYSCALL_ERROR_1:
61 0 : error = clib_error_return (0, "no such spd-id");
62 0 : break;
63 0 : case VNET_API_ERROR_SYSCALL_ERROR_2:
64 0 : error = clib_error_return (0, "spd already assigned");
65 0 : break;
66 : }
67 :
68 0 : done:
69 0 : unformat_free (line_input);
70 :
71 0 : return error;
72 : }
73 :
74 : /* *INDENT-OFF* */
75 285289 : VLIB_CLI_COMMAND (set_interface_spd_command, static) = {
76 : .path = "set interface ipsec spd",
77 : .short_help =
78 : "set interface ipsec spd <int> <id>",
79 : .function = set_interface_spd_command_fn,
80 : };
81 : /* *INDENT-ON* */
82 :
83 : static clib_error_t *
84 0 : ipsec_sa_add_del_command_fn (vlib_main_t * vm,
85 : unformat_input_t * input,
86 : vlib_cli_command_t * cmd)
87 : {
88 0 : unformat_input_t _line_input, *line_input = &_line_input;
89 : ipsec_crypto_alg_t crypto_alg;
90 : ipsec_integ_alg_t integ_alg;
91 : ipsec_protocol_t proto;
92 : ipsec_sa_flags_t flags;
93 : clib_error_t *error;
94 0 : ipsec_key_t ck = { 0 };
95 0 : ipsec_key_t ik = { 0 };
96 : u32 id, spi, salt, sai;
97 0 : int i = 0;
98 : u16 udp_src, udp_dst;
99 : int is_add, rv;
100 0 : u32 m_args = 0;
101 0 : tunnel_t tun = {};
102 :
103 0 : salt = 0;
104 0 : error = NULL;
105 0 : is_add = 0;
106 0 : flags = IPSEC_SA_FLAG_NONE;
107 0 : proto = IPSEC_PROTOCOL_ESP;
108 0 : integ_alg = IPSEC_INTEG_ALG_NONE;
109 0 : crypto_alg = IPSEC_CRYPTO_ALG_NONE;
110 0 : udp_src = udp_dst = IPSEC_UDP_PORT_NONE;
111 :
112 0 : if (!unformat_user (input, unformat_line_input, line_input))
113 0 : return 0;
114 :
115 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
116 : {
117 0 : if (unformat (line_input, "add %u", &id))
118 : {
119 0 : is_add = 1;
120 0 : m_args |= 1 << 0;
121 : }
122 0 : else if (unformat (line_input, "del %u", &id))
123 : {
124 0 : is_add = 0;
125 0 : m_args |= 1 << 0;
126 : }
127 0 : else if (unformat (line_input, "spi %u", &spi))
128 0 : m_args |= 1 << 1;
129 0 : else if (unformat (line_input, "salt 0x%x", &salt))
130 : ;
131 0 : else if (unformat (line_input, "esp"))
132 0 : proto = IPSEC_PROTOCOL_ESP;
133 0 : else if (unformat (line_input, "ah"))
134 0 : proto = IPSEC_PROTOCOL_AH;
135 0 : else if (unformat (line_input, "crypto-key %U",
136 : unformat_ipsec_key, &ck))
137 : ;
138 0 : else if (unformat (line_input, "crypto-alg %U",
139 : unformat_ipsec_crypto_alg, &crypto_alg))
140 : ;
141 0 : else if (unformat (line_input, "integ-key %U", unformat_ipsec_key, &ik))
142 : ;
143 0 : else if (unformat (line_input, "integ-alg %U",
144 : unformat_ipsec_integ_alg, &integ_alg))
145 : ;
146 0 : else if (unformat (line_input, "%U", unformat_tunnel, &tun))
147 : {
148 0 : flags |= IPSEC_SA_FLAG_IS_TUNNEL;
149 0 : if (AF_IP6 == tunnel_get_af (&tun))
150 0 : flags |= IPSEC_SA_FLAG_IS_TUNNEL_V6;
151 : }
152 0 : else if (unformat (line_input, "udp-src-port %d", &i))
153 0 : udp_src = i;
154 0 : else if (unformat (line_input, "udp-dst-port %d", &i))
155 0 : udp_dst = i;
156 0 : else if (unformat (line_input, "inbound"))
157 0 : flags |= IPSEC_SA_FLAG_IS_INBOUND;
158 0 : else if (unformat (line_input, "use-anti-replay"))
159 0 : flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY;
160 0 : else if (unformat (line_input, "use-esn"))
161 0 : flags |= IPSEC_SA_FLAG_USE_ESN;
162 0 : else if (unformat (line_input, "udp-encap"))
163 0 : flags |= IPSEC_SA_FLAG_UDP_ENCAP;
164 0 : else if (unformat (line_input, "async"))
165 0 : flags |= IPSEC_SA_FLAG_IS_ASYNC;
166 : else
167 : {
168 0 : error = clib_error_return (0, "parse error: '%U'",
169 : format_unformat_error, line_input);
170 0 : goto done;
171 : }
172 : }
173 :
174 0 : if (!(m_args & 1))
175 : {
176 0 : error = clib_error_return (0, "missing id");
177 0 : goto done;
178 : }
179 :
180 0 : if (is_add)
181 : {
182 0 : if (!(m_args & 2))
183 : {
184 0 : error = clib_error_return (0, "missing spi");
185 0 : goto done;
186 : }
187 0 : rv = ipsec_sa_add_and_lock (id, spi, proto, crypto_alg, &ck, integ_alg,
188 : &ik, flags, clib_host_to_net_u32 (salt),
189 : udp_src, udp_dst, &tun, &sai);
190 : }
191 : else
192 : {
193 0 : rv = ipsec_sa_unlock_id (id);
194 : }
195 :
196 0 : if (rv)
197 0 : error = clib_error_return (0, "failed: %d", rv);
198 :
199 0 : done:
200 0 : unformat_free (line_input);
201 :
202 0 : return error;
203 : }
204 :
205 : /* *INDENT-OFF* */
206 285289 : VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
207 : .path = "ipsec sa",
208 : .short_help =
209 : "ipsec sa [add|del]",
210 : .function = ipsec_sa_add_del_command_fn,
211 : };
212 : /* *INDENT-ON* */
213 :
214 : static clib_error_t *
215 0 : ipsec_sa_bind_cli (vlib_main_t *vm, unformat_input_t *input,
216 : vlib_cli_command_t *cmd)
217 : {
218 0 : unformat_input_t _line_input, *line_input = &_line_input;
219 0 : u32 id = ~0;
220 0 : u32 worker = ~0;
221 0 : bool bind = 1;
222 : int rv;
223 0 : clib_error_t *error = NULL;
224 :
225 0 : if (!unformat_user (input, unformat_line_input, line_input))
226 0 : return 0;
227 :
228 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
229 : {
230 0 : if (unformat (line_input, "unbind"))
231 0 : bind = 0;
232 0 : else if (id == ~0 && unformat (line_input, "%u", &id))
233 : ;
234 0 : else if (unformat (line_input, "%u", &worker))
235 : ;
236 : else
237 : {
238 0 : error = clib_error_return (0, "parse error: '%U'",
239 : format_unformat_error, line_input);
240 0 : goto done;
241 : }
242 : }
243 :
244 0 : if (id == ~0)
245 : {
246 0 : error = clib_error_return (0, "please specify SA ID");
247 0 : goto done;
248 : }
249 :
250 0 : if (bind && ~0 == worker)
251 : {
252 0 : error = clib_error_return (0, "please specify worker to bind to");
253 0 : goto done;
254 : }
255 :
256 0 : rv = ipsec_sa_bind (id, worker, bind);
257 0 : switch (rv)
258 : {
259 0 : case VNET_API_ERROR_INVALID_VALUE:
260 0 : error = clib_error_return (0, "please specify a valid SA ID");
261 0 : break;
262 0 : case VNET_API_ERROR_INVALID_WORKER:
263 0 : error = clib_error_return (0, "please specify a valid worker index");
264 0 : break;
265 : }
266 :
267 0 : done:
268 0 : unformat_free (line_input);
269 :
270 0 : return error;
271 : }
272 :
273 285289 : VLIB_CLI_COMMAND (ipsec_sa_bind_cmd, static) = {
274 : .path = "ipsec sa bind",
275 : .short_help = "ipsec sa [unbind] <sa-id> <worker>",
276 : .function = ipsec_sa_bind_cli,
277 : };
278 :
279 : static clib_error_t *
280 0 : ipsec_spd_add_del_command_fn (vlib_main_t * vm,
281 : unformat_input_t * input,
282 : vlib_cli_command_t * cmd)
283 : {
284 0 : unformat_input_t _line_input, *line_input = &_line_input;
285 0 : u32 spd_id = ~0;
286 0 : int is_add = ~0;
287 0 : clib_error_t *error = NULL;
288 :
289 0 : if (!unformat_user (input, unformat_line_input, line_input))
290 0 : return 0;
291 :
292 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
293 : {
294 0 : if (unformat (line_input, "add"))
295 0 : is_add = 1;
296 0 : else if (unformat (line_input, "del"))
297 0 : is_add = 0;
298 0 : else if (unformat (line_input, "%u", &spd_id))
299 : ;
300 : else
301 : {
302 0 : error = clib_error_return (0, "parse error: '%U'",
303 : format_unformat_error, line_input);
304 0 : goto done;
305 : }
306 : }
307 :
308 0 : if (spd_id == ~0)
309 : {
310 0 : error = clib_error_return (0, "please specify SPD ID");
311 0 : goto done;
312 : }
313 :
314 0 : ipsec_add_del_spd (vm, spd_id, is_add);
315 :
316 0 : done:
317 0 : unformat_free (line_input);
318 :
319 0 : return error;
320 : }
321 :
322 : /* *INDENT-OFF* */
323 285289 : VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
324 : .path = "ipsec spd",
325 : .short_help =
326 : "ipsec spd [add|del] <id>",
327 : .function = ipsec_spd_add_del_command_fn,
328 : };
329 : /* *INDENT-ON* */
330 :
331 :
332 : static clib_error_t *
333 0 : ipsec_policy_add_del_command_fn (vlib_main_t * vm,
334 : unformat_input_t * input,
335 : vlib_cli_command_t * cmd)
336 : {
337 0 : unformat_input_t _line_input, *line_input = &_line_input;
338 : ipsec_policy_t p;
339 0 : int rv, is_add = 0;
340 : u32 tmp, tmp2, stat_index, local_range_set, remote_range_set;
341 0 : clib_error_t *error = NULL;
342 : u32 is_outbound;
343 :
344 0 : clib_memset (&p, 0, sizeof (p));
345 0 : p.lport.stop = p.rport.stop = ~0;
346 0 : remote_range_set = local_range_set = is_outbound = 0;
347 0 : p.protocol = IPSEC_POLICY_PROTOCOL_ANY;
348 :
349 0 : if (!unformat_user (input, unformat_line_input, line_input))
350 0 : return 0;
351 :
352 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
353 : {
354 0 : if (unformat (line_input, "add"))
355 0 : is_add = 1;
356 0 : else if (unformat (line_input, "del"))
357 0 : is_add = 0;
358 0 : else if (unformat (line_input, "ip6"))
359 0 : p.is_ipv6 = 1;
360 0 : else if (unformat (line_input, "spd %u", &p.id))
361 : ;
362 0 : else if (unformat (line_input, "inbound"))
363 0 : is_outbound = 0;
364 0 : else if (unformat (line_input, "outbound"))
365 0 : is_outbound = 1;
366 0 : else if (unformat (line_input, "priority %d", &p.priority))
367 : ;
368 0 : else if (unformat (line_input, "protocol %u", &tmp))
369 0 : p.protocol = (u8) tmp;
370 : else
371 0 : if (unformat
372 : (line_input, "action %U", unformat_ipsec_policy_action,
373 : &p.policy))
374 : {
375 0 : if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
376 : {
377 0 : error = clib_error_return (0, "unsupported action: 'resolve'");
378 0 : goto done;
379 : }
380 : }
381 0 : else if (unformat (line_input, "sa %u", &p.sa_id))
382 : ;
383 0 : else if (unformat (line_input, "local-ip-range %U - %U",
384 : unformat_ip4_address, &p.laddr.start.ip4,
385 : unformat_ip4_address, &p.laddr.stop.ip4))
386 0 : local_range_set = 1;
387 0 : else if (unformat (line_input, "remote-ip-range %U - %U",
388 : unformat_ip4_address, &p.raddr.start.ip4,
389 : unformat_ip4_address, &p.raddr.stop.ip4))
390 0 : remote_range_set = 1;
391 0 : else if (unformat (line_input, "local-ip-range %U - %U",
392 : unformat_ip6_address, &p.laddr.start.ip6,
393 : unformat_ip6_address, &p.laddr.stop.ip6))
394 : {
395 0 : p.is_ipv6 = 1;
396 0 : local_range_set = 1;
397 : }
398 0 : else if (unformat (line_input, "remote-ip-range %U - %U",
399 : unformat_ip6_address, &p.raddr.start.ip6,
400 : unformat_ip6_address, &p.raddr.stop.ip6))
401 : {
402 0 : p.is_ipv6 = 1;
403 0 : remote_range_set = 1;
404 : }
405 0 : else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
406 : {
407 0 : p.lport.start = tmp;
408 0 : p.lport.stop = tmp2;
409 : }
410 : else
411 0 : if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
412 : {
413 0 : p.rport.start = tmp;
414 0 : p.rport.stop = tmp2;
415 : }
416 : else
417 : {
418 0 : error = clib_error_return (0, "parse error: '%U'",
419 : format_unformat_error, line_input);
420 0 : goto done;
421 : }
422 : }
423 :
424 0 : if (!remote_range_set)
425 : {
426 0 : if (p.is_ipv6)
427 0 : clib_memset (&p.raddr.stop.ip6, 0xff, 16);
428 : else
429 0 : clib_memset (&p.raddr.stop.ip4, 0xff, 4);
430 : }
431 0 : if (!local_range_set)
432 : {
433 0 : if (p.is_ipv6)
434 0 : clib_memset (&p.laddr.stop.ip6, 0xff, 16);
435 : else
436 0 : clib_memset (&p.laddr.stop.ip4, 0xff, 4);
437 : }
438 :
439 0 : rv = ipsec_policy_mk_type (is_outbound, p.is_ipv6, p.policy, &p.type);
440 :
441 0 : if (rv)
442 : {
443 0 : error = clib_error_return (0, "unsupported policy type for:",
444 : " outboud:%s %s action:%U",
445 : (is_outbound ? "yes" : "no"),
446 : (p.is_ipv6 ? "IPv4" : "IPv6"),
447 : format_ipsec_policy_action, p.policy);
448 0 : goto done;
449 : }
450 :
451 0 : rv = ipsec_add_del_policy (vm, &p, is_add, &stat_index);
452 :
453 0 : if (!rv)
454 0 : vlib_cli_output (vm, "policy-index:%d", stat_index);
455 : else
456 0 : vlib_cli_output (vm, "error:%d", rv);
457 :
458 0 : done:
459 0 : unformat_free (line_input);
460 :
461 0 : return error;
462 : }
463 :
464 : /* *INDENT-OFF* */
465 285289 : VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
466 : .path = "ipsec policy",
467 : .short_help =
468 : "ipsec policy [add|del] spd <id> priority <n> ",
469 : .function = ipsec_policy_add_del_command_fn,
470 : };
471 : /* *INDENT-ON* */
472 :
473 : static void
474 3644 : ipsec_sa_show_all (vlib_main_t * vm, ipsec_main_t * im, u8 detail)
475 : {
476 : u32 sai;
477 :
478 : /* *INDENT-OFF* */
479 33870 : pool_foreach_index (sai, ipsec_sa_pool)
480 : {
481 30226 : vlib_cli_output (vm, "%U", format_ipsec_sa, sai,
482 : (detail ? IPSEC_FORMAT_DETAIL : IPSEC_FORMAT_BRIEF));
483 : }
484 : /* *INDENT-ON* */
485 3644 : }
486 :
487 : static void
488 3665 : ipsec_spd_show_all (vlib_main_t * vm, ipsec_main_t * im)
489 : {
490 : u32 spdi;
491 :
492 : /* *INDENT-OFF* */
493 10327 : pool_foreach_index (spdi, im->spds) {
494 6662 : vlib_cli_output(vm, "%U", format_ipsec_spd, spdi);
495 : }
496 :
497 3665 : if (im->output_flow_cache_flag)
498 : {
499 47 : vlib_cli_output (vm, "%U", format_ipsec_out_spd_flow_cache);
500 : }
501 3665 : if (im->input_flow_cache_flag)
502 : {
503 51 : vlib_cli_output (vm, "%U", format_ipsec_in_spd_flow_cache);
504 : }
505 : /* *INDENT-ON* */
506 3665 : }
507 :
508 : static void
509 3621 : ipsec_spd_bindings_show_all (vlib_main_t * vm, ipsec_main_t * im)
510 : {
511 : u32 spd_id, sw_if_index;
512 : ipsec_spd_t *spd;
513 :
514 3621 : vlib_cli_output (vm, "SPD Bindings:");
515 :
516 : /* *INDENT-OFF* */
517 242129 : hash_foreach(sw_if_index, spd_id, im->spd_index_by_sw_if_index, ({
518 : spd = pool_elt_at_index (im->spds, spd_id);
519 : vlib_cli_output (vm, " %d -> %U", spd->id,
520 : format_vnet_sw_if_index_name, im->vnet_main,
521 : sw_if_index);
522 : }));
523 : /* *INDENT-ON* */
524 3621 : }
525 :
526 : static walk_rc_t
527 2106 : ipsec_tun_protect_show_one (index_t itpi, void *ctx)
528 : {
529 2106 : vlib_cli_output (ctx, "%U", format_ipsec_tun_protect_index, itpi);
530 :
531 2106 : return (WALK_CONTINUE);
532 : }
533 :
534 : static void
535 3 : ipsec_tunnel_show_all (vlib_main_t * vm)
536 : {
537 3 : ipsec_tun_protect_walk (ipsec_tun_protect_show_one, vm);
538 3 : }
539 :
540 : static clib_error_t *
541 3621 : show_ipsec_command_fn (vlib_main_t * vm,
542 : unformat_input_t * input, vlib_cli_command_t * cmd)
543 : {
544 3621 : ipsec_main_t *im = &ipsec_main;
545 :
546 3621 : ipsec_sa_show_all (vm, im, 0);
547 3621 : ipsec_spd_show_all (vm, im);
548 3621 : ipsec_spd_bindings_show_all (vm, im);
549 3621 : ipsec_tun_protect_walk (ipsec_tun_protect_show_one, vm);
550 :
551 3621 : vlib_cli_output (vm, "IPSec async mode: %s",
552 3621 : (im->async_mode ? "on" : "off"));
553 :
554 3621 : return 0;
555 : }
556 :
557 : /* *INDENT-OFF* */
558 285289 : VLIB_CLI_COMMAND (show_ipsec_command, static) = {
559 : .path = "show ipsec all",
560 : .short_help = "show ipsec all",
561 : .function = show_ipsec_command_fn,
562 : };
563 : /* *INDENT-ON* */
564 :
565 : static clib_error_t *
566 1524 : show_ipsec_sa_command_fn (vlib_main_t * vm,
567 : unformat_input_t * input, vlib_cli_command_t * cmd)
568 : {
569 1524 : ipsec_main_t *im = &ipsec_main;
570 1524 : u32 sai = ~0;
571 1524 : u8 detail = 0;
572 :
573 1524 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
574 : {
575 1501 : if (unformat (input, "%u", &sai))
576 : ;
577 1501 : if (unformat (input, "detail"))
578 0 : detail = 1;
579 : else
580 1501 : break;
581 : }
582 :
583 1524 : if (~0 == sai)
584 23 : ipsec_sa_show_all (vm, im, detail);
585 : else
586 1501 : vlib_cli_output (vm, "%U", format_ipsec_sa, sai,
587 : IPSEC_FORMAT_DETAIL | IPSEC_FORMAT_INSECURE);
588 :
589 1524 : return 0;
590 : }
591 :
592 : static clib_error_t *
593 2642 : clear_ipsec_sa_command_fn (vlib_main_t * vm,
594 : unformat_input_t * input, vlib_cli_command_t * cmd)
595 : {
596 2642 : u32 sai = ~0;
597 :
598 2642 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
599 : {
600 0 : if (unformat (input, "%u", &sai))
601 : ;
602 : else
603 0 : break;
604 : }
605 :
606 2642 : if (~0 == sai)
607 : {
608 : /* *INDENT-OFF* */
609 25572 : pool_foreach_index (sai, ipsec_sa_pool)
610 : {
611 22930 : ipsec_sa_clear (sai);
612 : }
613 : /* *INDENT-ON* */
614 : }
615 : else
616 : {
617 0 : if (pool_is_free_index (ipsec_sa_pool, sai))
618 0 : return clib_error_return (0, "unknown SA index: %d", sai);
619 : else
620 0 : ipsec_sa_clear (sai);
621 : }
622 :
623 2642 : return 0;
624 : }
625 :
626 : /* *INDENT-OFF* */
627 285289 : VLIB_CLI_COMMAND (show_ipsec_sa_command, static) = {
628 : .path = "show ipsec sa",
629 : .short_help = "show ipsec sa [index]",
630 : .function = show_ipsec_sa_command_fn,
631 : };
632 :
633 285289 : VLIB_CLI_COMMAND (clear_ipsec_sa_command, static) = {
634 : .path = "clear ipsec sa",
635 : .short_help = "clear ipsec sa [index]",
636 : .function = clear_ipsec_sa_command_fn,
637 : };
638 : /* *INDENT-ON* */
639 :
640 : static clib_error_t *
641 44 : show_ipsec_spd_command_fn (vlib_main_t * vm,
642 : unformat_input_t * input, vlib_cli_command_t * cmd)
643 : {
644 44 : ipsec_main_t *im = &ipsec_main;
645 44 : u8 show_bindings = 0;
646 44 : u32 spdi = ~0;
647 :
648 44 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
649 : {
650 0 : if (unformat (input, "%u", &spdi))
651 : ;
652 0 : else if (unformat (input, "bindings"))
653 0 : show_bindings = 1;
654 : else
655 0 : break;
656 : }
657 :
658 44 : if (show_bindings)
659 0 : ipsec_spd_bindings_show_all (vm, im);
660 44 : else if (~0 != spdi)
661 0 : vlib_cli_output (vm, "%U", format_ipsec_spd, spdi);
662 : else
663 44 : ipsec_spd_show_all (vm, im);
664 :
665 44 : return 0;
666 : }
667 :
668 : /* *INDENT-OFF* */
669 285289 : VLIB_CLI_COMMAND (show_ipsec_spd_command, static) = {
670 : .path = "show ipsec spd",
671 : .short_help = "show ipsec spd [index]",
672 : .function = show_ipsec_spd_command_fn,
673 : };
674 : /* *INDENT-ON* */
675 :
676 : static clib_error_t *
677 3 : show_ipsec_tunnel_command_fn (vlib_main_t * vm,
678 : unformat_input_t * input,
679 : vlib_cli_command_t * cmd)
680 : {
681 3 : ipsec_tunnel_show_all (vm);
682 :
683 3 : return 0;
684 : }
685 :
686 : /* *INDENT-OFF* */
687 285289 : VLIB_CLI_COMMAND (show_ipsec_tunnel_command, static) = {
688 : .path = "show ipsec tunnel",
689 : .short_help = "show ipsec tunnel",
690 : .function = show_ipsec_tunnel_command_fn,
691 : };
692 : /* *INDENT-ON* */
693 :
694 : static clib_error_t *
695 0 : ipsec_show_backends_command_fn (vlib_main_t * vm,
696 : unformat_input_t * input,
697 : vlib_cli_command_t * cmd)
698 : {
699 0 : ipsec_main_t *im = &ipsec_main;
700 0 : u32 verbose = 0;
701 :
702 0 : (void) unformat (input, "verbose %u", &verbose);
703 :
704 0 : vlib_cli_output (vm, "IPsec AH backends available:");
705 0 : u8 *s = format (NULL, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
706 : ipsec_ah_backend_t *ab;
707 : /* *INDENT-OFF* */
708 0 : pool_foreach (ab, im->ah_backends) {
709 0 : s = format (s, "%=25s %=25u %=10s\n", ab->name, ab - im->ah_backends,
710 0 : ab - im->ah_backends == im->ah_current_backend ? "yes" : "no");
711 0 : if (verbose) {
712 : vlib_node_t *n;
713 0 : n = vlib_get_node (vm, ab->ah4_encrypt_node_index);
714 0 : s = format (s, " enc4 %s (next %d)\n", n->name, ab->ah4_encrypt_next_index);
715 0 : n = vlib_get_node (vm, ab->ah4_decrypt_node_index);
716 0 : s = format (s, " dec4 %s (next %d)\n", n->name, ab->ah4_decrypt_next_index);
717 0 : n = vlib_get_node (vm, ab->ah6_encrypt_node_index);
718 0 : s = format (s, " enc6 %s (next %d)\n", n->name, ab->ah6_encrypt_next_index);
719 0 : n = vlib_get_node (vm, ab->ah6_decrypt_node_index);
720 0 : s = format (s, " dec6 %s (next %d)\n", n->name, ab->ah6_decrypt_next_index);
721 : }
722 : }
723 : /* *INDENT-ON* */
724 0 : vlib_cli_output (vm, "%v", s);
725 0 : vec_set_len (s, 0);
726 0 : vlib_cli_output (vm, "IPsec ESP backends available:");
727 0 : s = format (s, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
728 : ipsec_esp_backend_t *eb;
729 : /* *INDENT-OFF* */
730 0 : pool_foreach (eb, im->esp_backends) {
731 0 : s = format (s, "%=25s %=25u %=10s\n", eb->name, eb - im->esp_backends,
732 0 : eb - im->esp_backends == im->esp_current_backend ? "yes"
733 : : "no");
734 0 : if (verbose) {
735 : vlib_node_t *n;
736 0 : n = vlib_get_node (vm, eb->esp4_encrypt_node_index);
737 0 : s = format (s, " enc4 %s (next %d)\n", n->name, eb->esp4_encrypt_next_index);
738 0 : n = vlib_get_node (vm, eb->esp4_decrypt_node_index);
739 0 : s = format (s, " dec4 %s (next %d)\n", n->name, eb->esp4_decrypt_next_index);
740 0 : n = vlib_get_node (vm, eb->esp6_encrypt_node_index);
741 0 : s = format (s, " enc6 %s (next %d)\n", n->name, eb->esp6_encrypt_next_index);
742 0 : n = vlib_get_node (vm, eb->esp6_decrypt_node_index);
743 0 : s = format (s, " dec6 %s (next %d)\n", n->name, eb->esp6_decrypt_next_index);
744 : }
745 : }
746 : /* *INDENT-ON* */
747 0 : vlib_cli_output (vm, "%v", s);
748 :
749 0 : vec_free (s);
750 0 : return 0;
751 : }
752 :
753 : /* *INDENT-OFF* */
754 285289 : VLIB_CLI_COMMAND (ipsec_show_backends_command, static) = {
755 : .path = "show ipsec backends",
756 : .short_help = "show ipsec backends",
757 : .function = ipsec_show_backends_command_fn,
758 : };
759 : /* *INDENT-ON* */
760 :
761 : static clib_error_t *
762 0 : ipsec_select_backend_command_fn (vlib_main_t * vm,
763 : unformat_input_t * input,
764 : vlib_cli_command_t * cmd)
765 : {
766 0 : unformat_input_t _line_input, *line_input = &_line_input;
767 0 : ipsec_main_t *im = &ipsec_main;
768 : clib_error_t *error;
769 : u32 backend_index;
770 :
771 0 : error = ipsec_rsc_in_use (im);
772 :
773 0 : if (error)
774 0 : return error;
775 :
776 : /* Get a line of input. */
777 0 : if (!unformat_user (input, unformat_line_input, line_input))
778 0 : return 0;
779 :
780 0 : if (unformat (line_input, "ah"))
781 : {
782 0 : if (unformat (line_input, "%u", &backend_index))
783 : {
784 0 : if (ipsec_select_ah_backend (im, backend_index) < 0)
785 : {
786 0 : return clib_error_return (0, "Invalid AH backend index `%u'",
787 : backend_index);
788 : }
789 : }
790 : else
791 : {
792 0 : return clib_error_return (0, "Invalid backend index `%U'",
793 : format_unformat_error, line_input);
794 : }
795 : }
796 0 : else if (unformat (line_input, "esp"))
797 : {
798 0 : if (unformat (line_input, "%u", &backend_index))
799 : {
800 0 : if (ipsec_select_esp_backend (im, backend_index) < 0)
801 : {
802 0 : return clib_error_return (0, "Invalid ESP backend index `%u'",
803 : backend_index);
804 : }
805 : }
806 : else
807 : {
808 0 : return clib_error_return (0, "Invalid backend index `%U'",
809 : format_unformat_error, line_input);
810 : }
811 : }
812 : else
813 : {
814 0 : return clib_error_return (0, "Unknown input `%U'",
815 : format_unformat_error, line_input);
816 : }
817 :
818 0 : return 0;
819 : }
820 :
821 : /* *INDENT-OFF* */
822 285289 : VLIB_CLI_COMMAND (ipsec_select_backend_command, static) = {
823 : .path = "ipsec select backend",
824 : .short_help = "ipsec select backend <ah|esp> <backend index>",
825 : .function = ipsec_select_backend_command_fn,
826 : };
827 :
828 : /* *INDENT-ON* */
829 :
830 : static clib_error_t *
831 664 : clear_ipsec_counters_command_fn (vlib_main_t * vm,
832 : unformat_input_t * input,
833 : vlib_cli_command_t * cmd)
834 : {
835 664 : vlib_clear_combined_counters (&ipsec_spd_policy_counters);
836 664 : vlib_clear_combined_counters (&ipsec_sa_counters);
837 11288 : for (int i = 0; i < IPSEC_SA_N_ERRORS; i++)
838 10624 : vlib_clear_simple_counters (&ipsec_sa_err_counters[i]);
839 :
840 664 : return (NULL);
841 : }
842 :
843 : /* *INDENT-OFF* */
844 285289 : VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
845 : .path = "clear ipsec counters",
846 : .short_help = "clear ipsec counters",
847 : .function = clear_ipsec_counters_command_fn,
848 : };
849 : /* *INDENT-ON* */
850 :
851 : static clib_error_t *
852 0 : ipsec_tun_protect_cmd (vlib_main_t * vm,
853 : unformat_input_t * input, vlib_cli_command_t * cmd)
854 : {
855 0 : unformat_input_t _line_input, *line_input = &_line_input;
856 0 : u32 sw_if_index, is_del, sa_in, sa_out, *sa_ins = NULL;
857 0 : ip_address_t peer = { };
858 : vnet_main_t *vnm;
859 :
860 0 : is_del = 0;
861 0 : sw_if_index = ~0;
862 0 : vnm = vnet_get_main ();
863 :
864 0 : if (!unformat_user (input, unformat_line_input, line_input))
865 0 : return 0;
866 :
867 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
868 : {
869 0 : if (unformat (line_input, "del"))
870 0 : is_del = 1;
871 0 : else if (unformat (line_input, "add"))
872 0 : is_del = 0;
873 0 : else if (unformat (line_input, "sa-in %d", &sa_in))
874 0 : vec_add1 (sa_ins, sa_in);
875 0 : else if (unformat (line_input, "sa-out %d", &sa_out))
876 : ;
877 0 : else if (unformat (line_input, "%U",
878 : unformat_vnet_sw_interface, vnm, &sw_if_index))
879 : ;
880 0 : else if (unformat (line_input, "%U", unformat_ip_address, &peer))
881 : ;
882 : else
883 0 : return (clib_error_return (0, "unknown input '%U'",
884 : format_unformat_error, line_input));
885 : }
886 :
887 0 : if (!is_del)
888 0 : ipsec_tun_protect_update (sw_if_index, &peer, sa_out, sa_ins);
889 : else
890 0 : ipsec_tun_protect_del (sw_if_index, &peer);
891 :
892 0 : unformat_free (line_input);
893 0 : return NULL;
894 : }
895 :
896 : /**
897 : * Protect tunnel with IPSEC
898 : */
899 : /* *INDENT-OFF* */
900 285289 : VLIB_CLI_COMMAND (ipsec_tun_protect_cmd_node, static) =
901 : {
902 : .path = "ipsec tunnel protect",
903 : .function = ipsec_tun_protect_cmd,
904 : .short_help = "ipsec tunnel protect <interface> input-sa <SA> output-sa <SA> [add|del]",
905 : // this is not MP safe
906 : };
907 : /* *INDENT-ON* */
908 :
909 :
910 : static clib_error_t *
911 0 : ipsec_tun_protect_show (vlib_main_t * vm,
912 : unformat_input_t * input, vlib_cli_command_t * cmd)
913 : {
914 0 : ipsec_tun_protect_walk (ipsec_tun_protect_show_one, vm);
915 :
916 0 : return NULL;
917 : }
918 :
919 : /**
920 : * show IPSEC tunnel protection
921 : */
922 : /* *INDENT-OFF* */
923 285289 : VLIB_CLI_COMMAND (ipsec_tun_protect_show_node, static) =
924 : {
925 : .path = "show ipsec protect",
926 : .function = ipsec_tun_protect_show,
927 : .short_help = "show ipsec protect",
928 : };
929 : /* *INDENT-ON* */
930 :
931 : static int
932 16 : ipsec_tun_protect4_hash_show_one (clib_bihash_kv_8_16_t * kv, void *arg)
933 : {
934 16 : ipsec4_tunnel_kv_t *ikv = (ipsec4_tunnel_kv_t *) kv;
935 16 : vlib_main_t *vm = arg;
936 :
937 16 : vlib_cli_output (vm, " %U", format_ipsec4_tunnel_kv, ikv);
938 :
939 16 : return (BIHASH_WALK_CONTINUE);
940 : }
941 :
942 : static int
943 16 : ipsec_tun_protect6_hash_show_one (clib_bihash_kv_24_16_t * kv, void *arg)
944 : {
945 16 : ipsec6_tunnel_kv_t *ikv = (ipsec6_tunnel_kv_t *) kv;
946 16 : vlib_main_t *vm = arg;
947 :
948 16 : vlib_cli_output (vm, " %U", format_ipsec6_tunnel_kv, ikv);
949 :
950 16 : return (BIHASH_WALK_CONTINUE);
951 : }
952 :
953 : static clib_error_t *
954 2 : ipsec_tun_protect_hash_show (vlib_main_t * vm,
955 : unformat_input_t * input,
956 : vlib_cli_command_t * cmd)
957 : {
958 2 : ipsec_main_t *im = &ipsec_main;
959 :
960 : {
961 2 : vlib_cli_output (vm, "IPv4:");
962 :
963 2 : clib_bihash_foreach_key_value_pair_8_16
964 : (&im->tun4_protect_by_key, ipsec_tun_protect4_hash_show_one, vm);
965 :
966 2 : vlib_cli_output (vm, "IPv6:");
967 :
968 2 : clib_bihash_foreach_key_value_pair_24_16
969 : (&im->tun6_protect_by_key, ipsec_tun_protect6_hash_show_one, vm);
970 : }
971 :
972 2 : return NULL;
973 : }
974 :
975 : /**
976 : * show IPSEC tunnel protection hash tables
977 : */
978 : /* *INDENT-OFF* */
979 285289 : VLIB_CLI_COMMAND (ipsec_tun_protect_hash_show_node, static) =
980 : {
981 : .path = "show ipsec protect-hash",
982 : .function = ipsec_tun_protect_hash_show,
983 : .short_help = "show ipsec protect-hash",
984 : };
985 : /* *INDENT-ON* */
986 :
987 : clib_error_t *
988 575 : ipsec_cli_init (vlib_main_t * vm)
989 : {
990 575 : return 0;
991 : }
992 :
993 52415 : VLIB_INIT_FUNCTION (ipsec_cli_init);
994 :
995 : static clib_error_t *
996 20 : set_async_mode_command_fn (vlib_main_t * vm, unformat_input_t * input,
997 : vlib_cli_command_t * cmd)
998 : {
999 20 : unformat_input_t _line_input, *line_input = &_line_input;
1000 20 : int async_enable = 0;
1001 :
1002 20 : if (!unformat_user (input, unformat_line_input, line_input))
1003 0 : return 0;
1004 :
1005 40 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1006 : {
1007 20 : if (unformat (line_input, "on"))
1008 20 : async_enable = 1;
1009 0 : else if (unformat (line_input, "off"))
1010 0 : async_enable = 0;
1011 : else
1012 0 : return (clib_error_return (0, "unknown input '%U'",
1013 : format_unformat_error, line_input));
1014 : }
1015 :
1016 20 : ipsec_set_async_mode (async_enable);
1017 :
1018 20 : unformat_free (line_input);
1019 20 : return (NULL);
1020 : }
1021 :
1022 : /* *INDENT-OFF* */
1023 285289 : VLIB_CLI_COMMAND (set_async_mode_command, static) = {
1024 : .path = "set ipsec async mode",
1025 : .short_help = "set ipsec async mode on|off",
1026 : .function = set_async_mode_command_fn,
1027 : };
1028 : /* *INDENT-ON* */
1029 :
1030 : /*
1031 : * fd.io coding-style-patch-verification: ON
1032 : *
1033 : * Local Variables:
1034 : * eval: (c-set-style "gnu")
1035 : * End:
1036 : */
|