blob: 3c1e26f22c001c634ec0090b5bf9196f6c65e1e6 [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{
Sergio Gonzalez Monroyd04b60b2017-01-20 15:35:23 +000070 ipsec_main_t *im = &ipsec_main;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070071 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -070072 ipsec_sa_t sa;
73 int is_add = ~0;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070074 u8 *ck = 0, *ik = 0;
Sergio Gonzalez Monroyd04b60b2017-01-20 15:35:23 +000075 clib_error_t *err = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070076
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070077 memset (&sa, 0, sizeof (sa));
Ed Warnickecb9cada2015-12-08 15:45:58 -070078
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070079 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -070080 return 0;
81
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070082 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
83 {
84 if (unformat (line_input, "add %u", &sa.id))
85 is_add = 1;
86 else if (unformat (line_input, "del %u", &sa.id))
87 is_add = 0;
88 else if (unformat (line_input, "spi %u", &sa.spi))
89 ;
90 else if (unformat (line_input, "esp"))
91 sa.protocol = IPSEC_PROTOCOL_ESP;
92 else if (unformat (line_input, "ah"))
93 //sa.protocol = IPSEC_PROTOCOL_AH;
94 return clib_error_return (0, "unsupported security protocol 'AH'");
95 else
96 if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
97 sa.crypto_key_len = vec_len (ck);
98 else
99 if (unformat
100 (line_input, "crypto-alg %U", unformat_ipsec_crypto_alg,
101 &sa.crypto_alg))
102 {
103 if (sa.crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
Radu Nicolau6929ea92016-11-29 11:00:30 +0000104 sa.crypto_alg >= IPSEC_CRYPTO_N_ALG)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700105 return clib_error_return (0, "unsupported crypto-alg: '%U'",
106 format_ipsec_crypto_alg, sa.crypto_alg);
107 }
108 else
109 if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
110 sa.integ_key_len = vec_len (ik);
111 else if (unformat (line_input, "integ-alg %U", unformat_ipsec_integ_alg,
112 &sa.integ_alg))
113 {
114 if (sa.integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
Radu Nicolau6929ea92016-11-29 11:00:30 +0000115 sa.integ_alg >= IPSEC_INTEG_N_ALG)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700116 return clib_error_return (0, "unsupported integ-alg: '%U'",
117 format_ipsec_integ_alg, sa.integ_alg);
118 }
119 else if (unformat (line_input, "tunnel-src %U",
120 unformat_ip4_address, &sa.tunnel_src_addr.ip4))
121 sa.is_tunnel = 1;
122 else if (unformat (line_input, "tunnel-dst %U",
123 unformat_ip4_address, &sa.tunnel_dst_addr.ip4))
124 sa.is_tunnel = 1;
125 else if (unformat (line_input, "tunnel-src %U",
126 unformat_ip6_address, &sa.tunnel_src_addr.ip6))
127 {
128 sa.is_tunnel = 1;
129 sa.is_tunnel_ip6 = 1;
130 }
131 else if (unformat (line_input, "tunnel-dst %U",
132 unformat_ip6_address, &sa.tunnel_dst_addr.ip6))
133 {
134 sa.is_tunnel = 1;
135 sa.is_tunnel_ip6 = 1;
136 }
137 else
138 return clib_error_return (0, "parse error: '%U'",
139 format_unformat_error, line_input);
140 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700141
142 unformat_free (line_input);
143
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700144 if (sa.crypto_key_len > sizeof (sa.crypto_key))
145 sa.crypto_key_len = sizeof (sa.crypto_key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700146
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700147 if (sa.integ_key_len > sizeof (sa.integ_key))
148 sa.integ_key_len = sizeof (sa.integ_key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700149
150 if (ck)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700151 strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700152
153 if (ik)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700154 strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700155
Sergio Gonzalez Monroyd04b60b2017-01-20 15:35:23 +0000156 if (is_add)
157 {
158 ASSERT (im->cb.check_support_cb);
159 err = im->cb.check_support_cb (&sa);
160 if (err)
161 return err;
162 }
163
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700164 ipsec_add_del_sa (vm, &sa, is_add);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700165
166 return 0;
167}
168
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700169/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700170VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
171 .path = "ipsec sa",
172 .short_help =
173 "ipsec sa [add|del]",
174 .function = ipsec_sa_add_del_command_fn,
175};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700176/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700177
178static clib_error_t *
179ipsec_spd_add_del_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700180 unformat_input_t * input,
181 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700182{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700183 unformat_input_t _line_input, *line_input = &_line_input;
Damjan Marion3f54b182016-08-16 11:27:02 +0200184 u32 spd_id = ~0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700185 int is_add = ~0;
186
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700187 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700188 return 0;
189
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700190 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
191 {
192 if (unformat (line_input, "add"))
193 is_add = 1;
194 else if (unformat (line_input, "del"))
195 is_add = 0;
196 else if (unformat (line_input, "%u", &spd_id))
197 ;
198 else
199 return clib_error_return (0, "parse error: '%U'",
200 format_unformat_error, line_input);
201 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700202
203 unformat_free (line_input);
204
Damjan Marion3f54b182016-08-16 11:27:02 +0200205 if (spd_id == ~0)
206 return clib_error_return (0, "please specify SPD ID");
207
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700208 ipsec_add_del_spd (vm, spd_id, is_add);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700209
210 return 0;
211}
212
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700213/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700214VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
215 .path = "ipsec spd",
216 .short_help =
217 "ipsec spd [add|del] <id>",
218 .function = ipsec_spd_add_del_command_fn,
219};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700220/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700221
222
223static clib_error_t *
224ipsec_policy_add_del_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700225 unformat_input_t * input,
226 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700227{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700228 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229 ipsec_policy_t p;
230 int is_add = 0;
231 int is_ip_any = 1;
232 u32 tmp, tmp2;
233
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700234 memset (&p, 0, sizeof (p));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700235 p.lport.stop = p.rport.stop = ~0;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700236 p.laddr.stop.ip4.as_u32 = p.raddr.stop.ip4.as_u32 = (u32) ~ 0;
237 p.laddr.stop.ip6.as_u64[0] = p.laddr.stop.ip6.as_u64[1] = (u64) ~ 0;
238 p.raddr.stop.ip6.as_u64[0] = p.raddr.stop.ip6.as_u64[1] = (u64) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700239
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700240 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241 return 0;
242
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700243 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
244 {
245 if (unformat (line_input, "add"))
246 is_add = 1;
247 else if (unformat (line_input, "del"))
248 is_add = 0;
249 else if (unformat (line_input, "spd %u", &p.id))
250 ;
251 else if (unformat (line_input, "inbound"))
252 p.is_outbound = 0;
253 else if (unformat (line_input, "outbound"))
254 p.is_outbound = 1;
255 else if (unformat (line_input, "priority %d", &p.priority))
256 ;
257 else if (unformat (line_input, "protocol %u", &tmp))
258 p.protocol = (u8) tmp;
259 else
260 if (unformat
261 (line_input, "action %U", unformat_ipsec_policy_action,
262 &p.policy))
263 {
264 if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
265 return clib_error_return (0, "unsupported action: 'resolve'");
266 }
267 else if (unformat (line_input, "sa %u", &p.sa_id))
268 ;
269 else if (unformat (line_input, "local-ip-range %U - %U",
270 unformat_ip4_address, &p.laddr.start.ip4,
271 unformat_ip4_address, &p.laddr.stop.ip4))
272 is_ip_any = 0;
273 else if (unformat (line_input, "remote-ip-range %U - %U",
274 unformat_ip4_address, &p.raddr.start.ip4,
275 unformat_ip4_address, &p.raddr.stop.ip4))
276 is_ip_any = 0;
277 else if (unformat (line_input, "local-ip-range %U - %U",
278 unformat_ip6_address, &p.laddr.start.ip6,
279 unformat_ip6_address, &p.laddr.stop.ip6))
280 {
281 p.is_ipv6 = 1;
282 is_ip_any = 0;
283 }
284 else if (unformat (line_input, "remote-ip-range %U - %U",
285 unformat_ip6_address, &p.raddr.start.ip6,
286 unformat_ip6_address, &p.raddr.stop.ip6))
287 {
288 p.is_ipv6 = 1;
289 is_ip_any = 0;
290 }
291 else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
292 {
293 p.lport.start = tmp;
294 p.lport.stop = tmp2;
295 }
296 else
297 if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
298 {
299 p.rport.start = tmp;
300 p.rport.stop = tmp2;
301 }
302 else
303 return clib_error_return (0, "parse error: '%U'",
304 format_unformat_error, line_input);
305 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700306
307 unformat_free (line_input);
308
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700309 ipsec_add_del_policy (vm, &p, is_add);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700310 if (is_ip_any)
311 {
312 p.is_ipv6 = 1;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700313 ipsec_add_del_policy (vm, &p, is_add);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700314 }
315 return 0;
316}
317
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700318/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700319VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
320 .path = "ipsec policy",
321 .short_help =
322 "ipsec policy [add|del] spd <id> priority <n> ",
323 .function = ipsec_policy_add_del_command_fn,
324};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700325/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700326
327static clib_error_t *
328set_ipsec_sa_key_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700329 unformat_input_t * input,
330 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700331{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700332 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700333 ipsec_sa_t sa;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700334 u8 *ck = 0, *ik = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700335
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700336 memset (&sa, 0, sizeof (sa));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700337
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700338 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700339 return 0;
340
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700341 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
342 {
343 if (unformat (line_input, "%u", &sa.id))
344 ;
345 else
346 if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
347 sa.crypto_key_len = vec_len (ck);
348 else
349 if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
350 sa.integ_key_len = vec_len (ik);
351 else
352 return clib_error_return (0, "parse error: '%U'",
353 format_unformat_error, line_input);
354 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700355
356 unformat_free (line_input);
357
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700358 if (sa.crypto_key_len > sizeof (sa.crypto_key))
359 sa.crypto_key_len = sizeof (sa.crypto_key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700360
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700361 if (sa.integ_key_len > sizeof (sa.integ_key))
362 sa.integ_key_len = sizeof (sa.integ_key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700363
364 if (ck)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700365 strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700366
367 if (ik)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700368 strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700369
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700370 ipsec_set_sa_key (vm, &sa);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700371
372 return 0;
373}
374
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700375/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700376VLIB_CLI_COMMAND (set_ipsec_sa_key_command, static) = {
377 .path = "set ipsec sa",
378 .short_help =
379 "set ipsec sa <id> crypto-key <key> integ-key <key>",
380 .function = set_ipsec_sa_key_command_fn,
381};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700382/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700383
384static clib_error_t *
385show_ipsec_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700386 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700387{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700388 ipsec_spd_t *spd;
389 ipsec_sa_t *sa;
390 ipsec_policy_t *p;
391 ipsec_main_t *im = &ipsec_main;
392 u32 *i;
393 ipsec_tunnel_if_t *t;
394 vnet_hw_interface_t *hi;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700395
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700396 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700397 pool_foreach (sa, im->sad, ({
398 if (sa->id) {
399 vlib_cli_output(vm, "sa %u spi %u mode %s protocol %s", sa->id, sa->spi,
400 sa->is_tunnel ? "tunnel" : "transport",
401 sa->protocol ? "esp" : "ah");
402 if (sa->protocol == IPSEC_PROTOCOL_ESP) {
403 vlib_cli_output(vm, " crypto alg %U%s%U integrity alg %U%s%U",
404 format_ipsec_crypto_alg, sa->crypto_alg,
405 sa->crypto_alg ? " key " : "",
406 format_hex_bytes, sa->crypto_key, sa->crypto_key_len,
407 format_ipsec_integ_alg, sa->integ_alg,
408 sa->integ_alg ? " key " : "",
409 format_hex_bytes, sa->integ_key, sa->integ_key_len);
410 }
411 if (sa->is_tunnel && sa->is_tunnel_ip6) {
412 vlib_cli_output(vm, " tunnel src %U dst %U",
413 format_ip6_address, &sa->tunnel_src_addr.ip6,
414 format_ip6_address, &sa->tunnel_dst_addr.ip6);
415 } else if (sa->is_tunnel) {
416 vlib_cli_output(vm, " tunnel src %U dst %U",
417 format_ip4_address, &sa->tunnel_src_addr.ip4,
418 format_ip4_address, &sa->tunnel_dst_addr.ip4);
419 }
420 }
421 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700422 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700423
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700424 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700425 pool_foreach (spd, im->spds, ({
426 vlib_cli_output(vm, "spd %u", spd->id);
427
428 vlib_cli_output(vm, " outbound policies");
429 vec_foreach(i, spd->ipv4_outbound_policies)
430 {
431 p = pool_elt_at_index(spd->policies, *i);
432 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
433 p->priority,
434 format_ipsec_policy_action, p->policy,
435 p->protocol ?
436 format(0, "%U", format_ip_protocol, p->protocol) :
437 (u8 *) "any",
438 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
439 format(0, " sa %u", p->sa_id) :
440 (u8 *) "");
441 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
442 format_ip4_address, &p->laddr.start.ip4,
443 format_ip4_address, &p->laddr.stop.ip4,
444 p->lport.start, p->lport.stop);
445 vlib_cli_output(vm, " remte addr range %U - %U port range %u - %u",
446 format_ip4_address, &p->raddr.start.ip4,
447 format_ip4_address, &p->raddr.stop.ip4,
448 p->rport.start, p->rport.stop);
449 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
450 p->counter.bytes);
451 };
452 vec_foreach(i, spd->ipv6_outbound_policies)
453 {
454 p = pool_elt_at_index(spd->policies, *i);
455 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
456 p->priority,
457 format_ipsec_policy_action, p->policy,
458 p->protocol ?
459 format(0, "%U", format_ip_protocol, p->protocol) :
460 (u8 *) "any",
461 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
462 format(0, " sa %u", p->sa_id) :
463 (u8 *) "");
464 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
465 format_ip6_address, &p->laddr.start.ip6,
466 format_ip6_address, &p->laddr.stop.ip6,
467 p->lport.start, p->lport.stop);
468 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
469 format_ip6_address, &p->raddr.start.ip6,
470 format_ip6_address, &p->raddr.stop.ip6,
471 p->rport.start, p->rport.stop);
472 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
473 p->counter.bytes);
474 };
475 vlib_cli_output(vm, " inbound policies");
476 vec_foreach(i, spd->ipv4_inbound_protect_policy_indices)
477 {
478 p = pool_elt_at_index(spd->policies, *i);
479 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
480 p->priority,
481 format_ipsec_policy_action, p->policy,
482 p->protocol ?
483 format(0, "%U", format_ip_protocol, p->protocol) :
484 (u8 *) "any",
485 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
486 format(0, " sa %u", p->sa_id) :
487 (u8 *) "");
488 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
489 format_ip4_address, &p->laddr.start.ip4,
490 format_ip4_address, &p->laddr.stop.ip4,
491 p->lport.start, p->lport.stop);
492 vlib_cli_output(vm, " remte addr range %U - %U port range %u - %u",
493 format_ip4_address, &p->raddr.start.ip4,
494 format_ip4_address, &p->raddr.stop.ip4,
495 p->rport.start, p->rport.stop);
496 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
497 p->counter.bytes);
498 };
499 vec_foreach(i, spd->ipv4_inbound_policy_discard_and_bypass_indices)
500 {
501 p = pool_elt_at_index(spd->policies, *i);
502 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
503 p->priority,
504 format_ipsec_policy_action, p->policy,
505 p->protocol ?
506 format(0, "%U", format_ip_protocol, p->protocol) :
507 (u8 *) "any",
508 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
509 format(0, " sa %u", p->sa_id) :
510 (u8 *) "");
511 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
512 format_ip4_address, &p->laddr.start.ip4,
513 format_ip4_address, &p->laddr.stop.ip4,
514 p->lport.start, p->lport.stop);
515 vlib_cli_output(vm, " remte addr range %U - %U port range %u - %u",
516 format_ip4_address, &p->raddr.start.ip4,
517 format_ip4_address, &p->raddr.stop.ip4,
518 p->rport.start, p->rport.stop);
519 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
520 p->counter.bytes);
521 };
522 vec_foreach(i, spd->ipv6_inbound_protect_policy_indices)
523 {
524 p = pool_elt_at_index(spd->policies, *i);
525 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
526 p->priority,
527 format_ipsec_policy_action, p->policy,
528 p->protocol ?
529 format(0, "%U", format_ip_protocol, p->protocol) :
530 (u8 *) "any",
531 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
532 format(0, " sa %u", p->sa_id) :
533 (u8 *) "");
534 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
535 format_ip6_address, &p->laddr.start.ip6,
536 format_ip6_address, &p->laddr.stop.ip6,
537 p->lport.start, p->lport.stop);
538 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
539 format_ip6_address, &p->raddr.start.ip6,
540 format_ip6_address, &p->raddr.stop.ip6,
541 p->rport.start, p->rport.stop);
542 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
543 p->counter.bytes);
544 };
545 vec_foreach(i, spd->ipv6_inbound_policy_discard_and_bypass_indices)
546 {
547 p = pool_elt_at_index(spd->policies, *i);
548 vlib_cli_output(vm, " priority %d action %U protocol %s%s",
549 p->priority,
550 format_ipsec_policy_action, p->policy,
551 p->protocol ?
552 format(0, "%U", format_ip_protocol, p->protocol) :
553 (u8 *) "any",
554 p->policy == IPSEC_POLICY_ACTION_PROTECT ?
555 format(0, " sa %u", p->sa_id) :
556 (u8 *) "");
557 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
558 format_ip6_address, &p->laddr.start.ip6,
559 format_ip6_address, &p->laddr.stop.ip6,
560 p->lport.start, p->lport.stop);
561 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
562 format_ip6_address, &p->raddr.start.ip6,
563 format_ip6_address, &p->raddr.stop.ip6,
564 p->rport.start, p->rport.stop);
565 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
566 p->counter.bytes);
567 };
568 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700569 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700570
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700571 vlib_cli_output (vm, "tunnel interfaces");
572 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700573 pool_foreach (t, im->tunnel_interfaces, ({
Matus Fabian694265d2016-08-10 01:55:36 -0700574 if (t->hw_if_index == ~0)
575 continue;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700576 hi = vnet_get_hw_interface (im->vnet_main, t->hw_if_index);
577 vlib_cli_output(vm, " %s seq", hi->name);
578 sa = pool_elt_at_index(im->sad, t->output_sa_index);
579 vlib_cli_output(vm, " seq %u seq-hi %u esn %u anti-replay %u",
580 sa->seq, sa->seq_hi, sa->use_esn, sa->use_anti_replay);
581 vlib_cli_output(vm, " local-spi %u local-ip %U", sa->spi,
582 format_ip4_address, &sa->tunnel_src_addr.ip4);
583 vlib_cli_output(vm, " local-crypto %U %U",
584 format_ipsec_crypto_alg, sa->crypto_alg,
585 format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
586 vlib_cli_output(vm, " local-integrity %U %U",
587 format_ipsec_integ_alg, sa->integ_alg,
588 format_hex_bytes, sa->integ_key, sa->integ_key_len);
589 sa = pool_elt_at_index(im->sad, t->input_sa_index);
590 vlib_cli_output(vm, " last-seq %u last-seq-hi %u esn %u anti-replay %u window %U",
591 sa->last_seq, sa->last_seq_hi, sa->use_esn,
592 sa->use_anti_replay,
593 format_ipsec_replay_window, sa->replay_window);
594 vlib_cli_output(vm, " remote-spi %u remote-ip %U", sa->spi,
595 format_ip4_address, &sa->tunnel_src_addr.ip4);
596 vlib_cli_output(vm, " remote-crypto %U %U",
597 format_ipsec_crypto_alg, sa->crypto_alg,
598 format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
599 vlib_cli_output(vm, " remote-integrity %U %U",
600 format_ipsec_integ_alg, sa->integ_alg,
601 format_hex_bytes, sa->integ_key, sa->integ_key_len);
602 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700603 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700604 return 0;
605}
606
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700607/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700608VLIB_CLI_COMMAND (show_ipsec_command, static) = {
609 .path = "show ipsec",
610 .short_help = "show ipsec",
611 .function = show_ipsec_command_fn,
612};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700613/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700614
615static clib_error_t *
616clear_ipsec_counters_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700617 unformat_input_t * input,
618 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700619{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700620 ipsec_main_t *im = &ipsec_main;
621 ipsec_spd_t *spd;
622 ipsec_policy_t *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700623
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700624 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700625 pool_foreach (spd, im->spds, ({
626 pool_foreach(p, spd->policies, ({
627 p->counter.packets = p->counter.bytes = 0;
628 }));
629 }));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700630 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700631
632 return 0;
633}
634
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700635/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700636VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
637 .path = "clear ipsec counters",
638 .short_help = "clear ipsec counters",
639 .function = clear_ipsec_counters_command_fn,
640};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700641/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700642
643static clib_error_t *
644create_ipsec_tunnel_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700645 unformat_input_t * input,
646 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700647{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700648 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700649 ipsec_add_del_tunnel_args_t a;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700650 int rv;
651 u32 num_m_args = 0;
Matthew Smith2838a232016-06-21 16:05:09 -0500652
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700653 memset (&a, 0, sizeof (a));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700654 a.is_add = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700655
656 /* Get a line of input. */
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700657 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658 return 0;
659
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700660 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
661 {
662 if (unformat
663 (line_input, "local-ip %U", unformat_ip4_address, &a.local_ip))
664 num_m_args++;
665 else
666 if (unformat
667 (line_input, "remote-ip %U", unformat_ip4_address, &a.remote_ip))
668 num_m_args++;
669 else if (unformat (line_input, "local-spi %u", &a.local_spi))
670 num_m_args++;
671 else if (unformat (line_input, "remote-spi %u", &a.remote_spi))
672 num_m_args++;
673 else if (unformat (line_input, "del"))
674 a.is_add = 0;
675 else
676 return clib_error_return (0, "unknown input `%U'",
677 format_unformat_error, input);
678 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700679 unformat_free (line_input);
680
681 if (num_m_args < 4)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700682 return clib_error_return (0, "mandatory argument(s) missing");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700683
Matthew Smith2838a232016-06-21 16:05:09 -0500684 rv = ipsec_add_del_tunnel_if (&a);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700685
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700686 switch (rv)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700687 {
688 case 0:
689 break;
690 case VNET_API_ERROR_INVALID_VALUE:
691 if (a.is_add)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700692 return clib_error_return (0,
693 "IPSec tunnel interface already exists...");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700694 else
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700695 return clib_error_return (0, "IPSec tunnel interface not exists...");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700696 default:
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700697 return clib_error_return (0, "ipsec_register_interface returned %d",
698 rv);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700699 }
700
701 return 0;
702}
703
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700704/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700705VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
706 .path = "create ipsec tunnel",
707 .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> remote-ip <addr> remote-spi <spi>",
708 .function = create_ipsec_tunnel_command_fn,
709};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700710/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700711
712static clib_error_t *
713set_interface_key_command_fn (vlib_main_t * vm,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700714 unformat_input_t * input,
715 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700716{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700717 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700718 ipsec_main_t *im = &ipsec_main;
719 ipsec_if_set_key_type_t type = IPSEC_IF_SET_KEY_TYPE_NONE;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700720 u32 hw_if_index = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700721 u32 alg;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700722 u8 *key = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700723
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700724 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700725 return 0;
726
727 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
728 {
729 if (unformat (line_input, "%U",
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700730 unformat_vnet_hw_interface, im->vnet_main, &hw_if_index))
731 ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700732 else
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700733 if (unformat
734 (line_input, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
735 type = IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO;
736 else
737 if (unformat
738 (line_input, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
739 type = IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO;
740 else
741 if (unformat
742 (line_input, "local integ %U", unformat_ipsec_integ_alg, &alg))
743 type = IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG;
744 else
745 if (unformat
746 (line_input, "remote integ %U", unformat_ipsec_integ_alg, &alg))
747 type = IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG;
748 else if (unformat (line_input, "%U", unformat_hex_string, &key))
749 ;
750 else
751 return clib_error_return (0, "parse error: '%U'",
752 format_unformat_error, line_input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700753 }
754
755 unformat_free (line_input);
756
757 if (type == IPSEC_IF_SET_KEY_TYPE_NONE)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700758 return clib_error_return (0, "unknown key type");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700759
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700760 if (alg > 0 && vec_len (key) == 0)
761 return clib_error_return (0, "key is not specified");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700762
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700763 if (hw_if_index == (u32) ~ 0)
764 return clib_error_return (0, "interface not specified");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700765
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700766 ipsec_set_interface_key (im->vnet_main, hw_if_index, type, alg, key);
767 vec_free (key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700768
769 return 0;
770}
771
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700772/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700773VLIB_CLI_COMMAND (set_interface_key_command, static) = {
774 .path = "set interface ipsec key",
775 .short_help =
776 "set interface ipsec key <int> <local|remote> <crypto|integ> <key type> <key>",
777 .function = set_interface_key_command_fn,
778};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700779/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700780
Ed Warnickecb9cada2015-12-08 15:45:58 -0700781clib_error_t *
782ipsec_cli_init (vlib_main_t * vm)
783{
784 return 0;
785}
786
787VLIB_INIT_FUNCTION (ipsec_cli_init);
788
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700789
790/*
791 * fd.io coding-style-patch-verification: ON
792 *
793 * Local Variables:
794 * eval: (c-set-style "gnu")
795 * End:
796 */