blob: 7ab85d4aefb67a452f835aba90344fbc11be5b78 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * decap.c : IPSec tunnel support
3 *
4 * Copyright (c) 2015 Cisco and/or its affiliates.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <vnet/vnet.h>
19#include <vnet/api_errno.h>
20#include <vnet/ip/ip.h>
21#include <vnet/interface.h>
22
23#include <vnet/ipsec/ipsec.h>
24
25static clib_error_t *
26set_interface_spd_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070027 unformat_input_t * input,
28 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -070029{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070030 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -070031 ipsec_main_t *im = &ipsec_main;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070032 u32 sw_if_index = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070033 u32 spd_id;
34 int is_add = 1;
35
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070036 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -070037 return 0;
38
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070039 if (unformat
40 (line_input, "%U %u", unformat_vnet_sw_interface, im->vnet_main,
41 &sw_if_index, &spd_id))
Ed Warnickecb9cada2015-12-08 15:45:58 -070042 ;
43 else if (unformat (line_input, "del"))
44 is_add = 0;
45 else
46 return clib_error_return (0, "parse error: '%U'",
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070047 format_unformat_error, line_input);
Ed Warnickecb9cada2015-12-08 15:45:58 -070048
49 unformat_free (line_input);
50
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070051 ipsec_set_interface_spd (vm, sw_if_index, spd_id, is_add);
Ed Warnickecb9cada2015-12-08 15:45:58 -070052
53 return 0;
54}
55
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070056/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070057VLIB_CLI_COMMAND (set_interface_spd_command, static) = {
58 .path = "set interface ipsec spd",
59 .short_help =
60 "set interface ipsec spd <int> <id>",
61 .function = set_interface_spd_command_fn,
62};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070063/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070064
65static clib_error_t *
66ipsec_sa_add_del_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070067 unformat_input_t * input,
68 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -070069{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070070 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -070071 ipsec_sa_t sa;
72 int is_add = ~0;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070073 u8 *ck = 0, *ik = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070074
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070075 memset (&sa, 0, sizeof (sa));
Ed Warnickecb9cada2015-12-08 15:45:58 -070076
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070077 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -070078 return 0;
79
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070080 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
81 {
82 if (unformat (line_input, "add %u", &sa.id))
83 is_add = 1;
84 else if (unformat (line_input, "del %u", &sa.id))
85 is_add = 0;
86 else if (unformat (line_input, "spi %u", &sa.spi))
87 ;
88 else if (unformat (line_input, "esp"))
89 sa.protocol = IPSEC_PROTOCOL_ESP;
90 else if (unformat (line_input, "ah"))
91 //sa.protocol = IPSEC_PROTOCOL_AH;
92 return clib_error_return (0, "unsupported security protocol 'AH'");
93 else
94 if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
95 sa.crypto_key_len = vec_len (ck);
96 else
97 if (unformat
98 (line_input, "crypto-alg %U", unformat_ipsec_crypto_alg,
99 &sa.crypto_alg))
100 {
101 if (sa.crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
Radu Nicolau6929ea92016-11-29 11:00:30 +0000102 sa.crypto_alg >= IPSEC_CRYPTO_N_ALG)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700103 return clib_error_return (0, "unsupported crypto-alg: '%U'",
104 format_ipsec_crypto_alg, sa.crypto_alg);
105 }
106 else
107 if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
108 sa.integ_key_len = vec_len (ik);
109 else if (unformat (line_input, "integ-alg %U", unformat_ipsec_integ_alg,
110 &sa.integ_alg))
111 {
Radu Nicolau6929ea92016-11-29 11:00:30 +0000112#if DPDK_CRYPTO==1
113 if (sa.integ_alg < IPSEC_INTEG_ALG_NONE ||
114#else
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700115 if (sa.integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
Radu Nicolau6929ea92016-11-29 11:00:30 +0000116#endif
117 sa.integ_alg >= IPSEC_INTEG_N_ALG)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700118 return clib_error_return (0, "unsupported integ-alg: '%U'",
119 format_ipsec_integ_alg, sa.integ_alg);
120 }
121 else if (unformat (line_input, "tunnel-src %U",
122 unformat_ip4_address, &sa.tunnel_src_addr.ip4))
123 sa.is_tunnel = 1;
124 else if (unformat (line_input, "tunnel-dst %U",
125 unformat_ip4_address, &sa.tunnel_dst_addr.ip4))
126 sa.is_tunnel = 1;
127 else if (unformat (line_input, "tunnel-src %U",
128 unformat_ip6_address, &sa.tunnel_src_addr.ip6))
129 {
130 sa.is_tunnel = 1;
131 sa.is_tunnel_ip6 = 1;
132 }
133 else if (unformat (line_input, "tunnel-dst %U",
134 unformat_ip6_address, &sa.tunnel_dst_addr.ip6))
135 {
136 sa.is_tunnel = 1;
137 sa.is_tunnel_ip6 = 1;
138 }
139 else
140 return clib_error_return (0, "parse error: '%U'",
141 format_unformat_error, line_input);
142 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700143
Radu Nicolau6929ea92016-11-29 11:00:30 +0000144#if DPDK_CRYPTO==1
145 /*Special cases, aes-gcm-128 encryption */
146 if (sa.crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128)
147 {
148 if (sa.integ_alg != IPSEC_INTEG_ALG_NONE
149 && sa.integ_alg != IPSEC_INTEG_ALG_AES_GCM_128)
150 return clib_error_return (0,
151 "unsupported: aes-gcm-128 crypto-alg needs none as integ-alg");
152 else /*set integ-alg internally to aes-gcm-128 */
153 sa.integ_alg = IPSEC_INTEG_ALG_AES_GCM_128;
154 }
155 else if (sa.integ_alg == IPSEC_INTEG_ALG_AES_GCM_128)
156 return clib_error_return (0, "unsupported integ-alg: aes-gcm-128");
157 else if (sa.integ_alg == IPSEC_INTEG_ALG_NONE)
158 return clib_error_return (0, "unsupported integ-alg: none");
159#endif
160
Ed Warnickecb9cada2015-12-08 15:45:58 -0700161 unformat_free (line_input);
162
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700163 if (sa.crypto_key_len > sizeof (sa.crypto_key))
164 sa.crypto_key_len = sizeof (sa.crypto_key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700165
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700166 if (sa.integ_key_len > sizeof (sa.integ_key))
167 sa.integ_key_len = sizeof (sa.integ_key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700168
169 if (ck)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700170 strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700171
172 if (ik)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700173 strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700175 ipsec_add_del_sa (vm, &sa, is_add);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700176
177 return 0;
178}
179
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700180/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700181VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
182 .path = "ipsec sa",
183 .short_help =
184 "ipsec sa [add|del]",
185 .function = ipsec_sa_add_del_command_fn,
186};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700187/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700188
189static clib_error_t *
190ipsec_spd_add_del_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700191 unformat_input_t * input,
192 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700193{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700194 unformat_input_t _line_input, *line_input = &_line_input;
Damjan Marion3f54b182016-08-16 11:27:02 +0200195 u32 spd_id = ~0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196 int is_add = ~0;
197
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700198 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700199 return 0;
200
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700201 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
202 {
203 if (unformat (line_input, "add"))
204 is_add = 1;
205 else if (unformat (line_input, "del"))
206 is_add = 0;
207 else if (unformat (line_input, "%u", &spd_id))
208 ;
209 else
210 return clib_error_return (0, "parse error: '%U'",
211 format_unformat_error, line_input);
212 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700213
214 unformat_free (line_input);
215
Damjan Marion3f54b182016-08-16 11:27:02 +0200216 if (spd_id == ~0)
217 return clib_error_return (0, "please specify SPD ID");
218
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700219 ipsec_add_del_spd (vm, spd_id, is_add);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700220
221 return 0;
222}
223
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700224/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700225VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
226 .path = "ipsec spd",
227 .short_help =
228 "ipsec spd [add|del] <id>",
229 .function = ipsec_spd_add_del_command_fn,
230};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700231/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700232
233
234static clib_error_t *
235ipsec_policy_add_del_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700236 unformat_input_t * input,
237 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700238{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700239 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700240 ipsec_policy_t p;
241 int is_add = 0;
242 int is_ip_any = 1;
243 u32 tmp, tmp2;
244
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700245 memset (&p, 0, sizeof (p));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700246 p.lport.stop = p.rport.stop = ~0;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700247 p.laddr.stop.ip4.as_u32 = p.raddr.stop.ip4.as_u32 = (u32) ~ 0;
248 p.laddr.stop.ip6.as_u64[0] = p.laddr.stop.ip6.as_u64[1] = (u64) ~ 0;
249 p.raddr.stop.ip6.as_u64[0] = p.raddr.stop.ip6.as_u64[1] = (u64) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700250
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700251 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700252 return 0;
253
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700254 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
255 {
256 if (unformat (line_input, "add"))
257 is_add = 1;
258 else if (unformat (line_input, "del"))
259 is_add = 0;
260 else if (unformat (line_input, "spd %u", &p.id))
261 ;
262 else if (unformat (line_input, "inbound"))
263 p.is_outbound = 0;
264 else if (unformat (line_input, "outbound"))
265 p.is_outbound = 1;
266 else if (unformat (line_input, "priority %d", &p.priority))
267 ;
268 else if (unformat (line_input, "protocol %u", &tmp))
269 p.protocol = (u8) tmp;
270 else
271 if (unformat
272 (line_input, "action %U", unformat_ipsec_policy_action,
273 &p.policy))
274 {
275 if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
276 return clib_error_return (0, "unsupported action: 'resolve'");
277 }
278 else if (unformat (line_input, "sa %u", &p.sa_id))
279 ;
280 else if (unformat (line_input, "local-ip-range %U - %U",
281 unformat_ip4_address, &p.laddr.start.ip4,
282 unformat_ip4_address, &p.laddr.stop.ip4))
283 is_ip_any = 0;
284 else if (unformat (line_input, "remote-ip-range %U - %U",
285 unformat_ip4_address, &p.raddr.start.ip4,
286 unformat_ip4_address, &p.raddr.stop.ip4))
287 is_ip_any = 0;
288 else if (unformat (line_input, "local-ip-range %U - %U",
289 unformat_ip6_address, &p.laddr.start.ip6,
290 unformat_ip6_address, &p.laddr.stop.ip6))
291 {
292 p.is_ipv6 = 1;
293 is_ip_any = 0;
294 }
295 else if (unformat (line_input, "remote-ip-range %U - %U",
296 unformat_ip6_address, &p.raddr.start.ip6,
297 unformat_ip6_address, &p.raddr.stop.ip6))
298 {
299 p.is_ipv6 = 1;
300 is_ip_any = 0;
301 }
302 else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
303 {
304 p.lport.start = tmp;
305 p.lport.stop = tmp2;
306 }
307 else
308 if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
309 {
310 p.rport.start = tmp;
311 p.rport.stop = tmp2;
312 }
313 else
314 return clib_error_return (0, "parse error: '%U'",
315 format_unformat_error, line_input);
316 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700317
318 unformat_free (line_input);
319
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700320 ipsec_add_del_policy (vm, &p, is_add);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700321 if (is_ip_any)
322 {
323 p.is_ipv6 = 1;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700324 ipsec_add_del_policy (vm, &p, is_add);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700325 }
326 return 0;
327}
328
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700329/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700330VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
331 .path = "ipsec policy",
332 .short_help =
333 "ipsec policy [add|del] spd <id> priority <n> ",
334 .function = ipsec_policy_add_del_command_fn,
335};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700336/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700337
338static clib_error_t *
339set_ipsec_sa_key_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700340 unformat_input_t * input,
341 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700342{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700343 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700344 ipsec_sa_t sa;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700345 u8 *ck = 0, *ik = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700346
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700347 memset (&sa, 0, sizeof (sa));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700349 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700350 return 0;
351
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700352 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
353 {
354 if (unformat (line_input, "%u", &sa.id))
355 ;
356 else
357 if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
358 sa.crypto_key_len = vec_len (ck);
359 else
360 if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
361 sa.integ_key_len = vec_len (ik);
362 else
363 return clib_error_return (0, "parse error: '%U'",
364 format_unformat_error, line_input);
365 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700366
367 unformat_free (line_input);
368
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700369 if (sa.crypto_key_len > sizeof (sa.crypto_key))
370 sa.crypto_key_len = sizeof (sa.crypto_key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700371
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700372 if (sa.integ_key_len > sizeof (sa.integ_key))
373 sa.integ_key_len = sizeof (sa.integ_key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700374
375 if (ck)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700376 strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700377
378 if (ik)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700379 strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700380
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700381 ipsec_set_sa_key (vm, &sa);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700382
383 return 0;
384}
385
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700386/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700387VLIB_CLI_COMMAND (set_ipsec_sa_key_command, static) = {
388 .path = "set ipsec sa",
389 .short_help =
390 "set ipsec sa <id> crypto-key <key> integ-key <key>",
391 .function = set_ipsec_sa_key_command_fn,
392};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700393/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394
395static clib_error_t *
396show_ipsec_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700397 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700398{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700399 ipsec_spd_t *spd;
400 ipsec_sa_t *sa;
401 ipsec_policy_t *p;
402 ipsec_main_t *im = &ipsec_main;
403 u32 *i;
404 ipsec_tunnel_if_t *t;
405 vnet_hw_interface_t *hi;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700406
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700407 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700408 pool_foreach (sa, im->sad, ({
409 if (sa->id) {
410 vlib_cli_output(vm, "sa %u spi %u mode %s protocol %s", sa->id, sa->spi,
411 sa->is_tunnel ? "tunnel" : "transport",
412 sa->protocol ? "esp" : "ah");
413 if (sa->protocol == IPSEC_PROTOCOL_ESP) {
414 vlib_cli_output(vm, " crypto alg %U%s%U integrity alg %U%s%U",
415 format_ipsec_crypto_alg, sa->crypto_alg,
416 sa->crypto_alg ? " key " : "",
417 format_hex_bytes, sa->crypto_key, sa->crypto_key_len,
418 format_ipsec_integ_alg, sa->integ_alg,
419 sa->integ_alg ? " key " : "",
420 format_hex_bytes, sa->integ_key, sa->integ_key_len);
421 }
422 if (sa->is_tunnel && sa->is_tunnel_ip6) {
423 vlib_cli_output(vm, " tunnel src %U dst %U",
424 format_ip6_address, &sa->tunnel_src_addr.ip6,
425 format_ip6_address, &sa->tunnel_dst_addr.ip6);
426 } else if (sa->is_tunnel) {
427 vlib_cli_output(vm, " tunnel src %U dst %U",
428 format_ip4_address, &sa->tunnel_src_addr.ip4,
429 format_ip4_address, &sa->tunnel_dst_addr.ip4);
430 }
431 }
432 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700433 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700434
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700435 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700436 pool_foreach (spd, im->spds, ({
437 vlib_cli_output(vm, "spd %u", spd->id);
438
439 vlib_cli_output(vm, " outbound policies");
440 vec_foreach(i, spd->ipv4_outbound_policies)
441 {
442 p = pool_elt_at_index(spd->policies, *i);
443 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
444 p->priority,
445 format_ipsec_policy_action, p->policy,
446 p->protocol ?
447 format(0, "%U", format_ip_protocol, p->protocol) :
448 (u8 *) "any",
449 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
450 format(0, " sa %u", p->sa_id) :
451 (u8 *) "");
452 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
453 format_ip4_address, &p->laddr.start.ip4,
454 format_ip4_address, &p->laddr.stop.ip4,
455 p->lport.start, p->lport.stop);
456 vlib_cli_output(vm, " remte addr range %U - %U port range %u - %u",
457 format_ip4_address, &p->raddr.start.ip4,
458 format_ip4_address, &p->raddr.stop.ip4,
459 p->rport.start, p->rport.stop);
460 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
461 p->counter.bytes);
462 };
463 vec_foreach(i, spd->ipv6_outbound_policies)
464 {
465 p = pool_elt_at_index(spd->policies, *i);
466 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
467 p->priority,
468 format_ipsec_policy_action, p->policy,
469 p->protocol ?
470 format(0, "%U", format_ip_protocol, p->protocol) :
471 (u8 *) "any",
472 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
473 format(0, " sa %u", p->sa_id) :
474 (u8 *) "");
475 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
476 format_ip6_address, &p->laddr.start.ip6,
477 format_ip6_address, &p->laddr.stop.ip6,
478 p->lport.start, p->lport.stop);
479 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
480 format_ip6_address, &p->raddr.start.ip6,
481 format_ip6_address, &p->raddr.stop.ip6,
482 p->rport.start, p->rport.stop);
483 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
484 p->counter.bytes);
485 };
486 vlib_cli_output(vm, " inbound policies");
487 vec_foreach(i, spd->ipv4_inbound_protect_policy_indices)
488 {
489 p = pool_elt_at_index(spd->policies, *i);
490 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
491 p->priority,
492 format_ipsec_policy_action, p->policy,
493 p->protocol ?
494 format(0, "%U", format_ip_protocol, p->protocol) :
495 (u8 *) "any",
496 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
497 format(0, " sa %u", p->sa_id) :
498 (u8 *) "");
499 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
500 format_ip4_address, &p->laddr.start.ip4,
501 format_ip4_address, &p->laddr.stop.ip4,
502 p->lport.start, p->lport.stop);
503 vlib_cli_output(vm, " remte addr range %U - %U port range %u - %u",
504 format_ip4_address, &p->raddr.start.ip4,
505 format_ip4_address, &p->raddr.stop.ip4,
506 p->rport.start, p->rport.stop);
507 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
508 p->counter.bytes);
509 };
510 vec_foreach(i, spd->ipv4_inbound_policy_discard_and_bypass_indices)
511 {
512 p = pool_elt_at_index(spd->policies, *i);
513 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
514 p->priority,
515 format_ipsec_policy_action, p->policy,
516 p->protocol ?
517 format(0, "%U", format_ip_protocol, p->protocol) :
518 (u8 *) "any",
519 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
520 format(0, " sa %u", p->sa_id) :
521 (u8 *) "");
522 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
523 format_ip4_address, &p->laddr.start.ip4,
524 format_ip4_address, &p->laddr.stop.ip4,
525 p->lport.start, p->lport.stop);
526 vlib_cli_output(vm, " remte addr range %U - %U port range %u - %u",
527 format_ip4_address, &p->raddr.start.ip4,
528 format_ip4_address, &p->raddr.stop.ip4,
529 p->rport.start, p->rport.stop);
530 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
531 p->counter.bytes);
532 };
533 vec_foreach(i, spd->ipv6_inbound_protect_policy_indices)
534 {
535 p = pool_elt_at_index(spd->policies, *i);
536 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
537 p->priority,
538 format_ipsec_policy_action, p->policy,
539 p->protocol ?
540 format(0, "%U", format_ip_protocol, p->protocol) :
541 (u8 *) "any",
542 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
543 format(0, " sa %u", p->sa_id) :
544 (u8 *) "");
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 vec_foreach(i, spd->ipv6_inbound_policy_discard_and_bypass_indices)
557 {
558 p = pool_elt_at_index(spd->policies, *i);
559 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
560 p->priority,
561 format_ipsec_policy_action, p->policy,
562 p->protocol ?
563 format(0, "%U", format_ip_protocol, p->protocol) :
564 (u8 *) "any",
565 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
566 format(0, " sa %u", p->sa_id) :
567 (u8 *) "");
568 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
569 format_ip6_address, &p->laddr.start.ip6,
570 format_ip6_address, &p->laddr.stop.ip6,
571 p->lport.start, p->lport.stop);
572 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
573 format_ip6_address, &p->raddr.start.ip6,
574 format_ip6_address, &p->raddr.stop.ip6,
575 p->rport.start, p->rport.stop);
576 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
577 p->counter.bytes);
578 };
579 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700580 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700581
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700582 vlib_cli_output (vm, "tunnel interfaces");
583 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700584 pool_foreach (t, im->tunnel_interfaces, ({
Matus Fabian694265d2016-08-10 01:55:36 -0700585 if (t->hw_if_index == ~0)
586 continue;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700587 hi = vnet_get_hw_interface (im->vnet_main, t->hw_if_index);
588 vlib_cli_output(vm, " %s seq", hi->name);
589 sa = pool_elt_at_index(im->sad, t->output_sa_index);
590 vlib_cli_output(vm, " seq %u seq-hi %u esn %u anti-replay %u",
591 sa->seq, sa->seq_hi, sa->use_esn, sa->use_anti_replay);
592 vlib_cli_output(vm, " local-spi %u local-ip %U", sa->spi,
593 format_ip4_address, &sa->tunnel_src_addr.ip4);
594 vlib_cli_output(vm, " local-crypto %U %U",
595 format_ipsec_crypto_alg, sa->crypto_alg,
596 format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
597 vlib_cli_output(vm, " local-integrity %U %U",
598 format_ipsec_integ_alg, sa->integ_alg,
599 format_hex_bytes, sa->integ_key, sa->integ_key_len);
600 sa = pool_elt_at_index(im->sad, t->input_sa_index);
601 vlib_cli_output(vm, " last-seq %u last-seq-hi %u esn %u anti-replay %u window %U",
602 sa->last_seq, sa->last_seq_hi, sa->use_esn,
603 sa->use_anti_replay,
604 format_ipsec_replay_window, sa->replay_window);
605 vlib_cli_output(vm, " remote-spi %u remote-ip %U", sa->spi,
606 format_ip4_address, &sa->tunnel_src_addr.ip4);
607 vlib_cli_output(vm, " remote-crypto %U %U",
608 format_ipsec_crypto_alg, sa->crypto_alg,
609 format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
610 vlib_cli_output(vm, " remote-integrity %U %U",
611 format_ipsec_integ_alg, sa->integ_alg,
612 format_hex_bytes, sa->integ_key, sa->integ_key_len);
613 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700614 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700615 return 0;
616}
617
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700618/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700619VLIB_CLI_COMMAND (show_ipsec_command, static) = {
620 .path = "show ipsec",
621 .short_help = "show ipsec",
622 .function = show_ipsec_command_fn,
623};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700624/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700625
626static clib_error_t *
627clear_ipsec_counters_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700628 unformat_input_t * input,
629 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700630{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700631 ipsec_main_t *im = &ipsec_main;
632 ipsec_spd_t *spd;
633 ipsec_policy_t *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700634
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700635 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700636 pool_foreach (spd, im->spds, ({
637 pool_foreach(p, spd->policies, ({
638 p->counter.packets = p->counter.bytes = 0;
639 }));
640 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700641 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700642
643 return 0;
644}
645
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700646/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700647VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
648 .path = "clear ipsec counters",
649 .short_help = "clear ipsec counters",
650 .function = clear_ipsec_counters_command_fn,
651};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700652/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700653
654static clib_error_t *
655create_ipsec_tunnel_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700656 unformat_input_t * input,
657 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700659 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700660 ipsec_add_del_tunnel_args_t a;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700661 int rv;
662 u32 num_m_args = 0;
Matthew Smith2838a232016-06-21 16:05:09 -0500663
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700664 memset (&a, 0, sizeof (a));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700665 a.is_add = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700666
667 /* Get a line of input. */
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700668 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700669 return 0;
670
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700671 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
672 {
673 if (unformat
674 (line_input, "local-ip %U", unformat_ip4_address, &a.local_ip))
675 num_m_args++;
676 else
677 if (unformat
678 (line_input, "remote-ip %U", unformat_ip4_address, &a.remote_ip))
679 num_m_args++;
680 else if (unformat (line_input, "local-spi %u", &a.local_spi))
681 num_m_args++;
682 else if (unformat (line_input, "remote-spi %u", &a.remote_spi))
683 num_m_args++;
684 else if (unformat (line_input, "del"))
685 a.is_add = 0;
686 else
687 return clib_error_return (0, "unknown input `%U'",
688 format_unformat_error, input);
689 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700690 unformat_free (line_input);
691
692 if (num_m_args < 4)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700693 return clib_error_return (0, "mandatory argument(s) missing");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700694
Matthew Smith2838a232016-06-21 16:05:09 -0500695 rv = ipsec_add_del_tunnel_if (&a);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700696
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700697 switch (rv)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700698 {
699 case 0:
700 break;
701 case VNET_API_ERROR_INVALID_VALUE:
702 if (a.is_add)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700703 return clib_error_return (0,
704 "IPSec tunnel interface already exists...");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700705 else
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700706 return clib_error_return (0, "IPSec tunnel interface not exists...");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700707 default:
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700708 return clib_error_return (0, "ipsec_register_interface returned %d",
709 rv);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700710 }
711
712 return 0;
713}
714
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700715/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700716VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
717 .path = "create ipsec tunnel",
718 .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> remote-ip <addr> remote-spi <spi>",
719 .function = create_ipsec_tunnel_command_fn,
720};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700721/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700722
723static clib_error_t *
724set_interface_key_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700725 unformat_input_t * input,
726 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700727{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700728 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700729 ipsec_main_t *im = &ipsec_main;
730 ipsec_if_set_key_type_t type = IPSEC_IF_SET_KEY_TYPE_NONE;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700731 u32 hw_if_index = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700732 u32 alg;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700733 u8 *key = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700734
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700735 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700736 return 0;
737
738 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
739 {
740 if (unformat (line_input, "%U",
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700741 unformat_vnet_hw_interface, im->vnet_main, &hw_if_index))
742 ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700743 else
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700744 if (unformat
745 (line_input, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
746 type = IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO;
747 else
748 if (unformat
749 (line_input, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
750 type = IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO;
751 else
752 if (unformat
753 (line_input, "local integ %U", unformat_ipsec_integ_alg, &alg))
754 type = IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG;
755 else
756 if (unformat
757 (line_input, "remote integ %U", unformat_ipsec_integ_alg, &alg))
758 type = IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG;
759 else if (unformat (line_input, "%U", unformat_hex_string, &key))
760 ;
761 else
762 return clib_error_return (0, "parse error: '%U'",
763 format_unformat_error, line_input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700764 }
765
766 unformat_free (line_input);
767
768 if (type == IPSEC_IF_SET_KEY_TYPE_NONE)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700769 return clib_error_return (0, "unknown key type");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700770
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700771 if (alg > 0 && vec_len (key) == 0)
772 return clib_error_return (0, "key is not specified");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700773
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700774 if (hw_if_index == (u32) ~ 0)
775 return clib_error_return (0, "interface not specified");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700776
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700777 ipsec_set_interface_key (im->vnet_main, hw_if_index, type, alg, key);
778 vec_free (key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700779
780 return 0;
781}
782
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700783/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700784VLIB_CLI_COMMAND (set_interface_key_command, static) = {
785 .path = "set interface ipsec key",
786 .short_help =
787 "set interface ipsec key <int> <local|remote> <crypto|integ> <key type> <key>",
788 .function = set_interface_key_command_fn,
789};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700790/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700791
Ed Warnickecb9cada2015-12-08 15:45:58 -0700792clib_error_t *
793ipsec_cli_init (vlib_main_t * vm)
794{
795 return 0;
796}
797
798VLIB_INIT_FUNCTION (ipsec_cli_init);
799
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700800
801/*
802 * fd.io coding-style-patch-verification: ON
803 *
804 * Local Variables:
805 * eval: (c-set-style "gnu")
806 * End:
807 */