ikev2: add option to disable NAT traversal
[vpp.git] / src / plugins / ikev2 / ikev2_cli.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vlib/vlib.h>
16 #include <vnet/vnet.h>
17 #include <vppinfra/error.h>
18 #include <vnet/ipsec/ipsec_sa.h>
19 #include <plugins/ikev2/ikev2.h>
20 #include <plugins/ikev2/ikev2_priv.h>
21
22 u8 *
23 format_ikev2_id_type_and_data (u8 * s, va_list * args)
24 {
25   ikev2_id_t *id = va_arg (*args, ikev2_id_t *);
26
27   if (id->type == 0 || vec_len (id->data) == 0)
28     return format (s, "none");
29
30   s = format (s, "%U", format_ikev2_id_type, id->type);
31
32   if (id->type == IKEV2_ID_TYPE_ID_FQDN ||
33       id->type == IKEV2_ID_TYPE_ID_RFC822_ADDR)
34     {
35       s = format (s, " %v", id->data);
36     }
37   else
38     {
39       s =
40         format (s, " %U", format_hex_bytes, &id->data,
41                 (uword) (vec_len (id->data)));
42     }
43
44   return s;
45 }
46
47 static u8 *
48 format_ikev2_traffic_selector (u8 * s, va_list * va)
49 {
50   ikev2_ts_t *ts = va_arg (*va, ikev2_ts_t *);
51   u32 index = va_arg (*va, u32);
52
53   s = format (s, "%u type %u protocol_id %u addr "
54               "%U - %U port %u - %u\n",
55               index, ts->ts_type, ts->protocol_id,
56               format_ip_address, &ts->start_addr,
57               format_ip_address, &ts->end_addr,
58               clib_net_to_host_u16 (ts->start_port),
59               clib_net_to_host_u16 (ts->end_port));
60   return s;
61 }
62
63 static u8 *
64 format_ikev2_child_sa (u8 * s, va_list * va)
65 {
66   ikev2_child_sa_t *child = va_arg (*va, ikev2_child_sa_t *);
67   u32 index = va_arg (*va, u32);
68   ikev2_ts_t *ts;
69   ikev2_sa_transform_t *tr;
70   u8 *c = 0;
71
72   u32 indent = format_get_indent (s);
73   indent += 1;
74
75   s = format (s, "child sa %u:", index);
76
77   tr = ikev2_sa_get_td_for_type (child->r_proposals,
78                                  IKEV2_TRANSFORM_TYPE_ENCR);
79   c = format (c, "%U ", format_ikev2_sa_transform, tr);
80
81   tr = ikev2_sa_get_td_for_type (child->r_proposals,
82                                  IKEV2_TRANSFORM_TYPE_INTEG);
83   c = format (c, "%U ", format_ikev2_sa_transform, tr);
84
85   tr = ikev2_sa_get_td_for_type (child->r_proposals,
86                                  IKEV2_TRANSFORM_TYPE_ESN);
87   c = format (c, "%U ", format_ikev2_sa_transform, tr);
88
89   s = format (s, "%v\n", c);
90   vec_free (c);
91
92   s = format (s, "%Uspi(i) %lx spi(r) %lx\n", format_white_space, indent,
93               child->i_proposals ? child->i_proposals[0].spi : 0,
94               child->r_proposals ? child->r_proposals[0].spi : 0);
95
96   s = format (s, "%USK_e  i:%U\n%Ur:%U\n",
97               format_white_space, indent,
98               format_hex_bytes, child->sk_ei, vec_len (child->sk_ei),
99               format_white_space, indent + 6,
100               format_hex_bytes, child->sk_er, vec_len (child->sk_er));
101   if (child->sk_ai)
102     {
103       s = format (s, "%USK_a  i:%U\n%Ur:%U\n",
104                   format_white_space, indent,
105                   format_hex_bytes, child->sk_ai, vec_len (child->sk_ai),
106                   format_white_space, indent + 6,
107                   format_hex_bytes, child->sk_ar, vec_len (child->sk_ar));
108     }
109   s = format (s, "%Utraffic selectors (i):", format_white_space, indent);
110   vec_foreach (ts, child->tsi)
111     s = format (s, "%U", format_ikev2_traffic_selector, ts, ts - child->tsi);
112   s = format (s, "%Utraffic selectors (r):", format_white_space, indent);
113   vec_foreach (ts, child->tsr)
114     s = format (s, "%U", format_ikev2_traffic_selector, ts, ts - child->tsr);
115   return s;
116 }
117
118 static u8 *
119 format_ikev2_sa (u8 * s, va_list * va)
120 {
121   ikev2_sa_t *sa = va_arg (*va, ikev2_sa_t *);
122   int details = va_arg (*va, int);
123   ikev2_sa_transform_t *tr;
124   ikev2_child_sa_t *child;
125   u32 indent = 1;
126
127   s = format (s, "iip %U ispi %lx rip %U rspi %lx",
128               format_ip_address, &sa->iaddr, sa->ispi,
129               format_ip_address, &sa->raddr, sa->rspi);
130   if (!details)
131     return s;
132
133   s = format (s, "\n%U", format_white_space, indent);
134
135   tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR);
136   s = format (s, "%U ", format_ikev2_sa_transform, tr);
137
138   tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_PRF);
139   s = format (s, "%U ", format_ikev2_sa_transform, tr);
140
141   tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_INTEG);
142   s = format (s, "%U ", format_ikev2_sa_transform, tr);
143
144   tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_DH);
145   s = format (s, "%U", format_ikev2_sa_transform, tr);
146
147   s = format (s, "\n%U", format_white_space, indent);
148
149   s = format (s, "nonce i:%U\n%Ur:%U\n",
150               format_hex_bytes, sa->i_nonce, vec_len (sa->i_nonce),
151               format_white_space, indent + 6,
152               format_hex_bytes, sa->r_nonce, vec_len (sa->r_nonce));
153
154   s = format (s, "%USK_d    %U\n", format_white_space, indent,
155               format_hex_bytes, sa->sk_d, vec_len (sa->sk_d));
156   if (sa->sk_ai)
157     {
158       s = format (s, "%USK_a  i:%U\n%Ur:%U\n",
159                   format_white_space, indent,
160                   format_hex_bytes, sa->sk_ai, vec_len (sa->sk_ai),
161                   format_white_space, indent + 6,
162                   format_hex_bytes, sa->sk_ar, vec_len (sa->sk_ar));
163     }
164   s = format (s, "%USK_e  i:%U\n%Ur:%U\n",
165               format_white_space, indent,
166               format_hex_bytes, sa->sk_ei, vec_len (sa->sk_ei),
167               format_white_space, indent + 6,
168               format_hex_bytes, sa->sk_er, vec_len (sa->sk_er));
169   s = format (s, "%USK_p  i:%U\n%Ur:%U\n",
170               format_white_space, indent,
171               format_hex_bytes, sa->sk_pi, vec_len (sa->sk_pi),
172               format_white_space, indent + 6,
173               format_hex_bytes, sa->sk_pr, vec_len (sa->sk_pr));
174
175   s = format (s, "%Uidentifier (i) %U\n",
176               format_white_space, indent,
177               format_ikev2_id_type_and_data, &sa->i_id);
178   s = format (s, "%Uidentifier (r) %U\n",
179               format_white_space, indent,
180               format_ikev2_id_type_and_data, &sa->r_id);
181
182   vec_foreach (child, sa->childs)
183   {
184     s = format (s, "%U%U", format_white_space, indent + 2,
185                 format_ikev2_child_sa, child, child - sa->childs);
186   }
187
188   return s;
189 }
190
191 static clib_error_t *
192 show_ikev2_sa_command_fn (vlib_main_t * vm,
193                           unformat_input_t * input, vlib_cli_command_t * cmd)
194 {
195   unformat_input_t _line_input, *line_input = &_line_input;
196   ikev2_main_t *km = &ikev2_main;
197   ikev2_main_per_thread_data_t *tkm;
198   ikev2_sa_t *sa;
199   u64 rspi;
200   u8 *s = 0;
201   int details = 0, show_one = 0;
202
203   if (unformat_user (input, unformat_line_input, line_input))
204     {
205       while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
206         {
207           if (unformat (line_input, "rspi %lx", &rspi))
208             {
209               show_one = 1;
210             }
211           else if (unformat (line_input, "details"))
212             details = 1;
213           else
214             break;
215         }
216       unformat_free (line_input);
217     }
218
219   vec_foreach (tkm, km->per_thread_data)
220   {
221     /* *INDENT-OFF* */
222     pool_foreach (sa, tkm->sas, ({
223       if (show_one)
224         {
225           if (sa->rspi == rspi)
226             {
227               s = format (s, "%U\n", format_ikev2_sa, sa, 1);
228               break;
229             }
230         }
231       else
232         s = format (s, "%U\n", format_ikev2_sa, sa, details);
233     }));
234     /* *INDENT-ON* */
235   }
236
237   vlib_cli_output (vm, "%v", s);
238   vec_free (s);
239   return 0;
240 }
241
242 /* *INDENT-OFF* */
243 VLIB_CLI_COMMAND (show_ikev2_sa_command, static) = {
244     .path = "show ikev2 sa",
245     .short_help = "show ikev2 sa [rspi <rspi>] [details]",
246     .function = show_ikev2_sa_command_fn,
247 };
248 /* *INDENT-ON* */
249
250 static clib_error_t *
251 ikev2_disable_dpd_command_fn (vlib_main_t * vm,
252                               unformat_input_t * input,
253                               vlib_cli_command_t * cmd)
254 {
255   ikev2_disable_dpd ();
256   return 0;
257 }
258
259 /* *INDENT-OFF* */
260 VLIB_CLI_COMMAND (ikev2_cli_disable_dpd_command, static) = {
261   .path = "ikev2 dpd disable",
262   .short_help = "ikev2 dpd disable",
263   .function = ikev2_disable_dpd_command_fn,
264 };
265 /* *INDENT-ON* */
266
267 static uword
268 unformat_ikev2_token (unformat_input_t * input, va_list * va)
269 {
270   u8 **string_return = va_arg (*va, u8 **);
271   const char *token_chars = "a-zA-Z0-9_";
272   if (*string_return)
273     {
274       /* if string_return was already allocated (eg. because of a previous
275        * partial match with a successful unformat_token()), we must free it
276        * before reusing the pointer, otherwise we'll be leaking memory
277        */
278       vec_free (*string_return);
279       *string_return = 0;
280     }
281   return unformat_user (input, unformat_token, token_chars, string_return);
282 }
283
284 static clib_error_t *
285 ikev2_profile_add_del_command_fn (vlib_main_t * vm,
286                                   unformat_input_t * input,
287                                   vlib_cli_command_t * cmd)
288 {
289   vnet_main_t *vnm = vnet_get_main ();
290   unformat_input_t _line_input, *line_input = &_line_input;
291   u8 *name = 0;
292   clib_error_t *r = 0;
293   u32 id_type;
294   u8 *data = 0;
295   u32 tmp1, tmp2, tmp3;
296   u64 tmp4, tmp5;
297   ip_address_t ip, end_addr;
298   u32 responder_sw_if_index = (u32) ~ 0;
299   u32 tun_sw_if_index = (u32) ~ 0;
300   ikev2_transform_encr_type_t crypto_alg;
301   ikev2_transform_integ_type_t integ_alg;
302   ikev2_transform_dh_type_t dh_type;
303
304   if (!unformat_user (input, unformat_line_input, line_input))
305     return 0;
306
307   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
308     {
309       if (unformat (line_input, "add %U", unformat_ikev2_token, &name))
310         {
311           r = ikev2_add_del_profile (vm, name, 1);
312           goto done;
313         }
314       else if (unformat (line_input, "del %U", unformat_ikev2_token, &name))
315         {
316           r = ikev2_add_del_profile (vm, name, 0);
317           goto done;
318         }
319       else if (unformat (line_input, "set %U auth shared-key-mic string %v",
320                          unformat_ikev2_token, &name, &data))
321         {
322           r =
323             ikev2_set_profile_auth (vm, name,
324                                     IKEV2_AUTH_METHOD_SHARED_KEY_MIC, data,
325                                     0);
326           goto done;
327         }
328       else if (unformat (line_input, "set %U auth shared-key-mic hex %U",
329                          unformat_ikev2_token, &name,
330                          unformat_hex_string, &data))
331         {
332           r =
333             ikev2_set_profile_auth (vm, name,
334                                     IKEV2_AUTH_METHOD_SHARED_KEY_MIC, data,
335                                     1);
336           goto done;
337         }
338       else if (unformat (line_input, "set %U auth rsa-sig cert-file %v",
339                          unformat_ikev2_token, &name, &data))
340         {
341           r =
342             ikev2_set_profile_auth (vm, name, IKEV2_AUTH_METHOD_RSA_SIG, data,
343                                     0);
344           goto done;
345         }
346       else if (unformat (line_input, "set %U id local %U %U",
347                          unformat_ikev2_token, &name,
348                          unformat_ikev2_id_type, &id_type,
349                          unformat_ip_address, &ip))
350         {
351           data = vec_new (u8, ip_address_size (&ip));
352           clib_memcpy (data, ip_addr_bytes (&ip), ip_address_size (&ip));
353           r =
354             ikev2_set_profile_id (vm, name, (u8) id_type, data, /*local */ 1);
355           goto done;
356         }
357       else if (unformat (line_input, "set %U id local %U 0x%U",
358                          unformat_ikev2_token, &name,
359                          unformat_ikev2_id_type, &id_type,
360                          unformat_hex_string, &data))
361         {
362           r =
363             ikev2_set_profile_id (vm, name, (u8) id_type, data, /*local */ 1);
364           goto done;
365         }
366       else if (unformat (line_input, "set %U id local %U %v",
367                          unformat_ikev2_token, &name,
368                          unformat_ikev2_id_type, &id_type, &data))
369         {
370           r =
371             ikev2_set_profile_id (vm, name, (u8) id_type, data, /*local */ 1);
372           goto done;
373         }
374       else if (unformat (line_input, "set %U id remote %U %U",
375                          unformat_ikev2_token, &name,
376                          unformat_ikev2_id_type, &id_type,
377                          unformat_ip_address, &ip))
378         {
379           data = vec_new (u8, ip_address_size (&ip));
380           clib_memcpy (data, ip_addr_bytes (&ip), ip_address_size (&ip));
381           r = ikev2_set_profile_id (vm, name, (u8) id_type, data,       /*remote */
382                                     0);
383           goto done;
384         }
385       else if (unformat (line_input, "set %U id remote %U 0x%U",
386                          unformat_ikev2_token, &name,
387                          unformat_ikev2_id_type, &id_type,
388                          unformat_hex_string, &data))
389         {
390           r = ikev2_set_profile_id (vm, name, (u8) id_type, data,       /*remote */
391                                     0);
392           goto done;
393         }
394       else if (unformat (line_input, "set %U id remote %U %v",
395                          unformat_ikev2_token, &name,
396                          unformat_ikev2_id_type, &id_type, &data))
397         {
398           r = ikev2_set_profile_id (vm, name, (u8) id_type, data,       /*remote */
399                                     0);
400           goto done;
401         }
402       else if (unformat (line_input, "set %U traffic-selector local "
403                          "ip-range %U - %U port-range %u - %u protocol %u",
404                          unformat_ikev2_token, &name,
405                          unformat_ip_address, &ip,
406                          unformat_ip_address, &end_addr, &tmp1, &tmp2, &tmp3))
407         {
408           r =
409             ikev2_set_profile_ts (vm, name, (u8) tmp3, (u16) tmp1, (u16) tmp2,
410                                   ip, end_addr, /*local */ 1);
411           goto done;
412         }
413       else if (unformat (line_input, "set %U traffic-selector remote "
414                          "ip-range %U - %U port-range %u - %u protocol %u",
415                          unformat_ikev2_token, &name,
416                          unformat_ip_address, &ip,
417                          unformat_ip_address, &end_addr, &tmp1, &tmp2, &tmp3))
418         {
419           r =
420             ikev2_set_profile_ts (vm, name, (u8) tmp3, (u16) tmp1, (u16) tmp2,
421                                   ip, end_addr, /*remote */ 0);
422           goto done;
423         }
424       else if (unformat (line_input, "set %U responder %U %U",
425                          unformat_ikev2_token, &name,
426                          unformat_vnet_sw_interface, vnm,
427                          &responder_sw_if_index, unformat_ip_address, &ip))
428         {
429           r =
430             ikev2_set_profile_responder (vm, name, responder_sw_if_index, ip);
431           goto done;
432         }
433       else if (unformat (line_input, "set %U tunnel %U",
434                          unformat_ikev2_token, &name,
435                          unformat_vnet_sw_interface, vnm, &tun_sw_if_index))
436         {
437           r = ikev2_set_profile_tunnel_interface (vm, name, tun_sw_if_index);
438           goto done;
439         }
440       else
441         if (unformat
442             (line_input,
443              "set %U ike-crypto-alg %U %u ike-integ-alg %U ike-dh %U",
444              unformat_ikev2_token, &name,
445              unformat_ikev2_transform_encr_type, &crypto_alg, &tmp1,
446              unformat_ikev2_transform_integ_type, &integ_alg,
447              unformat_ikev2_transform_dh_type, &dh_type))
448         {
449           r =
450             ikev2_set_profile_ike_transforms (vm, name, crypto_alg, integ_alg,
451                                               dh_type, tmp1);
452           goto done;
453         }
454       else
455         if (unformat
456             (line_input,
457              "set %U ike-crypto-alg %U %u ike-dh %U",
458              unformat_ikev2_token, &name,
459              unformat_ikev2_transform_encr_type, &crypto_alg, &tmp1,
460              unformat_ikev2_transform_dh_type, &dh_type))
461         {
462           r =
463             ikev2_set_profile_ike_transforms (vm, name, crypto_alg,
464                                               IKEV2_TRANSFORM_INTEG_TYPE_NONE,
465                                               dh_type, tmp1);
466           goto done;
467         }
468       else
469         if (unformat
470             (line_input,
471              "set %U esp-crypto-alg %U %u esp-integ-alg %U",
472              unformat_ikev2_token, &name,
473              unformat_ikev2_transform_encr_type, &crypto_alg, &tmp1,
474              unformat_ikev2_transform_integ_type, &integ_alg))
475         {
476           r =
477             ikev2_set_profile_esp_transforms (vm, name, crypto_alg, integ_alg,
478                                               tmp1);
479           goto done;
480         }
481       else if (unformat
482                (line_input,
483                 "set %U esp-crypto-alg %U %u",
484                 unformat_ikev2_token, &name,
485                 unformat_ikev2_transform_encr_type, &crypto_alg, &tmp1))
486         {
487           r =
488             ikev2_set_profile_esp_transforms (vm, name, crypto_alg, 0, tmp1);
489           goto done;
490         }
491       else if (unformat (line_input, "set %U sa-lifetime %lu %u %u %lu",
492                          unformat_ikev2_token, &name,
493                          &tmp4, &tmp1, &tmp2, &tmp5))
494         {
495           r =
496             ikev2_set_profile_sa_lifetime (vm, name, tmp4, tmp1, tmp2, tmp5);
497           goto done;
498         }
499       else if (unformat (line_input, "set %U udp-encap",
500                          unformat_ikev2_token, &name))
501         {
502           r = ikev2_set_profile_udp_encap (vm, name);
503           goto done;
504         }
505       else if (unformat (line_input, "set %U ipsec-over-udp port %u",
506                          unformat_ikev2_token, &name, &tmp1))
507         {
508           int rv = ikev2_set_profile_ipsec_udp_port (vm, name, tmp1, 1);
509           if (rv)
510             r = clib_error_return (0, "Error: %U", format_vnet_api_errno, rv);
511           goto done;
512         }
513       else if (unformat (line_input, "set %U disable natt",
514                          unformat_ikev2_token, &name))
515         {
516           r = ikev2_profile_natt_disable (name);
517           goto done;
518         }
519       else
520         break;
521     }
522
523   r = clib_error_return (0, "parse error: '%U'",
524                          format_unformat_error, line_input);
525
526 done:
527   vec_free (name);
528   vec_free (data);
529   unformat_free (line_input);
530   return r;
531 }
532
533 /* *INDENT-OFF* */
534 VLIB_CLI_COMMAND (ikev2_profile_add_del_command, static) = {
535     .path = "ikev2 profile",
536     .short_help =
537     "ikev2 profile [add|del] <id>\n"
538     "ikev2 profile set <id> auth [rsa-sig|shared-key-mic] [cert-file|string|hex]"
539     " <data>\n"
540     "ikev2 profile set <id> id <local|remote> <type> <data>\n"
541     "ikev2 profile set <id> tunnel <interface>\n"
542     "ikev2 profile set <id> udp-encap\n"
543     "ikev2 profile set <id> traffic-selector <local|remote> ip-range "
544     "<start-addr> - <end-addr> port-range <start-port> - <end-port> "
545     "protocol <protocol-number>\n"
546     "ikev2 profile set <id> responder <interface> <addr>\n"
547     "ikev2 profile set <id> ike-crypto-alg <crypto alg> <key size> ike-integ-alg <integ alg> ike-dh <dh type>\n"
548     "ikev2 profile set <id> esp-crypto-alg <crypto alg> <key size> "
549       "[esp-integ-alg <integ alg>]\n"
550     "ikev2 profile set <id> sa-lifetime <seconds> <jitter> <handover> <max bytes>"
551     "ikev2 profile set <id> disable natt\n",
552     .function = ikev2_profile_add_del_command_fn,
553 };
554 /* *INDENT-ON* */
555
556 static clib_error_t *
557 show_ikev2_profile_command_fn (vlib_main_t * vm,
558                                unformat_input_t * input,
559                                vlib_cli_command_t * cmd)
560 {
561   ikev2_main_t *km = &ikev2_main;
562   ikev2_profile_t *p;
563
564   /* *INDENT-OFF* */
565   pool_foreach (p, km->profiles, ({
566     vlib_cli_output(vm, "profile %v", p->name);
567
568     if (p->auth.data)
569       {
570         if (p->auth.hex)
571           vlib_cli_output(vm, "  auth-method %U auth data 0x%U",
572                           format_ikev2_auth_method, p->auth.method,
573                           format_hex_bytes, p->auth.data, vec_len(p->auth.data));
574         else
575           vlib_cli_output(vm, "  auth-method %U auth data %v",
576                    format_ikev2_auth_method, p->auth.method, p->auth.data);
577       }
578
579     if (p->loc_id.data)
580       {
581         if (p->loc_id.type == IKEV2_ID_TYPE_ID_IPV4_ADDR)
582           vlib_cli_output(vm, "  local id-type %U data %U",
583                           format_ikev2_id_type, p->loc_id.type,
584                           format_ip_address, p->loc_id.data);
585         else if (p->loc_id.type == IKEV2_ID_TYPE_ID_KEY_ID)
586           vlib_cli_output(vm, "  local id-type %U data 0x%U",
587                           format_ikev2_id_type, p->loc_id.type,
588                           format_hex_bytes, p->loc_id.data,
589                           vec_len(p->loc_id.data));
590         else
591           vlib_cli_output(vm, "  local id-type %U data %v",
592                           format_ikev2_id_type, p->loc_id.type, p->loc_id.data);
593       }
594
595     if (p->rem_id.data)
596       {
597         if (p->rem_id.type == IKEV2_ID_TYPE_ID_IPV4_ADDR)
598           vlib_cli_output(vm, "  remote id-type %U data %U",
599                           format_ikev2_id_type, p->rem_id.type,
600                           format_ip_address, p->rem_id.data);
601         else if (p->rem_id.type == IKEV2_ID_TYPE_ID_KEY_ID)
602           vlib_cli_output(vm, "  remote id-type %U data 0x%U",
603                           format_ikev2_id_type, p->rem_id.type,
604                           format_hex_bytes, p->rem_id.data,
605                           vec_len(p->rem_id.data));
606         else
607           vlib_cli_output(vm, "  remote id-type %U data %v",
608                           format_ikev2_id_type, p->rem_id.type, p->rem_id.data);
609       }
610
611     if (!ip_address_is_zero (&p->loc_ts.start_addr))
612       vlib_cli_output(vm, "  local traffic-selector addr %U - %U port %u - %u"
613                       " protocol %u",
614                       format_ip_address, &p->loc_ts.start_addr,
615                       format_ip_address, &p->loc_ts.end_addr,
616                       p->loc_ts.start_port, p->loc_ts.end_port,
617                       p->loc_ts.protocol_id);
618
619     if (!ip_address_is_zero (&p->rem_ts.start_addr))
620       vlib_cli_output(vm, "  remote traffic-selector addr %U - %U port %u - %u"
621                       " protocol %u",
622                       format_ip_address, &p->rem_ts.start_addr,
623                       format_ip_address, &p->rem_ts.end_addr,
624                       p->rem_ts.start_port, p->rem_ts.end_port,
625                       p->rem_ts.protocol_id);
626     if (~0 != p->tun_itf)
627       vlib_cli_output(vm, "  protected tunnel %U",
628                       format_vnet_sw_if_index_name, vnet_get_main(), p->tun_itf);
629     if (~0 != p->responder.sw_if_index)
630       vlib_cli_output(vm, "  responder %U %U",
631                       format_vnet_sw_if_index_name, vnet_get_main(), p->responder.sw_if_index,
632                       format_ip_address, &p->responder.addr);
633     if (p->udp_encap)
634       vlib_cli_output(vm, "  udp-encap");
635
636     if (p->natt_disabled)
637       vlib_cli_output(vm, "  NAT-T disabled");
638
639     if (p->ipsec_over_udp_port != IPSEC_UDP_PORT_NONE)
640       vlib_cli_output(vm, "  ipsec-over-udp port %d", p->ipsec_over_udp_port);
641
642     if (p->ike_ts.crypto_alg || p->ike_ts.integ_alg || p->ike_ts.dh_type || p->ike_ts.crypto_key_size)
643       vlib_cli_output(vm, "  ike-crypto-alg %U %u ike-integ-alg %U ike-dh %U",
644                     format_ikev2_transform_encr_type, p->ike_ts.crypto_alg, p->ike_ts.crypto_key_size,
645                     format_ikev2_transform_integ_type, p->ike_ts.integ_alg,
646                     format_ikev2_transform_dh_type, p->ike_ts.dh_type);
647
648     if (p->esp_ts.crypto_alg || p->esp_ts.integ_alg || p->esp_ts.dh_type)
649       vlib_cli_output(vm, "  esp-crypto-alg %U %u esp-integ-alg %U",
650                     format_ikev2_transform_encr_type, p->esp_ts.crypto_alg, p->esp_ts.crypto_key_size,
651                     format_ikev2_transform_integ_type, p->esp_ts.integ_alg);
652
653     vlib_cli_output(vm, "  lifetime %d jitter %d handover %d maxdata %d",
654                     p->lifetime, p->lifetime_jitter, p->handover, p->lifetime_maxdata);
655   }));
656   /* *INDENT-ON* */
657
658   return 0;
659 }
660
661 /* *INDENT-OFF* */
662 VLIB_CLI_COMMAND (show_ikev2_profile_command, static) = {
663     .path = "show ikev2 profile",
664     .short_help = "show ikev2 profile",
665     .function = show_ikev2_profile_command_fn,
666 };
667 /* *INDENT-ON* */
668
669 static clib_error_t *
670 set_ikev2_liveness_period_fn (vlib_main_t * vm,
671                               unformat_input_t * input,
672                               vlib_cli_command_t * cmd)
673 {
674   unformat_input_t _line_input, *line_input = &_line_input;
675   clib_error_t *r = 0;
676   u32 period = 0, max_retries = 0;
677
678   if (!unformat_user (input, unformat_line_input, line_input))
679     return 0;
680
681   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
682     {
683       if (unformat (line_input, "%d %d", &period, &max_retries))
684         {
685           r = ikev2_set_liveness_params (period, max_retries);
686           goto done;
687         }
688       else
689         break;
690     }
691
692   r = clib_error_return (0, "parse error: '%U'",
693                          format_unformat_error, line_input);
694
695 done:
696   unformat_free (line_input);
697   return r;
698 }
699
700 /* *INDENT-OFF* */
701 VLIB_CLI_COMMAND (set_ikev2_liveness_command, static) = {
702   .path = "ikev2 set liveness",
703   .short_help = "ikev2 set liveness <period> <max-retires>",
704   .function = set_ikev2_liveness_period_fn,
705 };
706 /* *INDENT-ON* */
707
708 static clib_error_t *
709 set_ikev2_local_key_command_fn (vlib_main_t * vm,
710                                 unformat_input_t * input,
711                                 vlib_cli_command_t * cmd)
712 {
713   unformat_input_t _line_input, *line_input = &_line_input;
714   clib_error_t *r = 0;
715   u8 *data = 0;
716
717   if (!unformat_user (input, unformat_line_input, line_input))
718     return 0;
719
720   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
721     {
722       if (unformat (line_input, "%s", &data))
723         {
724           r = ikev2_set_local_key (vm, data);
725           goto done;
726         }
727       else
728         break;
729     }
730
731   r = clib_error_return (0, "parse error: '%U'",
732                          format_unformat_error, line_input);
733
734 done:
735   vec_free (data);
736   unformat_free (line_input);
737   return r;
738 }
739
740 /* *INDENT-OFF* */
741 VLIB_CLI_COMMAND (set_ikev2_local_key_command, static) = {
742     .path = "set ikev2 local key",
743     .short_help =
744     "set ikev2 local key <file>",
745     .function = set_ikev2_local_key_command_fn,
746 };
747 /* *INDENT-ON* */
748
749
750 static clib_error_t *
751 ikev2_initiate_command_fn (vlib_main_t * vm,
752                            unformat_input_t * input, vlib_cli_command_t * cmd)
753 {
754   unformat_input_t _line_input, *line_input = &_line_input;
755   clib_error_t *r = 0;
756   u8 *name = 0;
757   u32 tmp1;
758   u64 tmp2;
759
760   if (!unformat_user (input, unformat_line_input, line_input))
761     return 0;
762
763   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
764     {
765       if (unformat (line_input, "sa-init %U", unformat_ikev2_token, &name))
766         {
767           r = ikev2_initiate_sa_init (vm, name);
768           goto done;
769         }
770       else if (unformat (line_input, "del-child-sa %x", &tmp1))
771         {
772           r = ikev2_initiate_delete_child_sa (vm, tmp1);
773           goto done;
774         }
775       else if (unformat (line_input, "del-sa %lx", &tmp2))
776         {
777           r = ikev2_initiate_delete_ike_sa (vm, tmp2);
778           goto done;
779         }
780       else if (unformat (line_input, "rekey-child-sa %x", &tmp1))
781         {
782           r = ikev2_initiate_rekey_child_sa (vm, tmp1);
783           goto done;
784         }
785       else
786         break;
787     }
788
789   r = clib_error_return (0, "parse error: '%U'",
790                          format_unformat_error, line_input);
791
792 done:
793   vec_free (name);
794   unformat_free (line_input);
795   return r;
796 }
797
798 /* *INDENT-OFF* */
799 VLIB_CLI_COMMAND (ikev2_initiate_command, static) = {
800     .path = "ikev2 initiate",
801     .short_help =
802         "ikev2 initiate sa-init <profile id>\n"
803         "ikev2 initiate del-child-sa <child sa ispi>\n"
804         "ikev2 initiate del-sa <sa ispi>\n"
805         "ikev2 initiate rekey-child-sa <child sa ispi>\n",
806     .function = ikev2_initiate_command_fn,
807 };
808 /* *INDENT-ON* */
809
810 void
811 ikev2_cli_reference (void)
812 {
813 }
814
815 static clib_error_t *
816 ikev2_set_log_level_command_fn (vlib_main_t * vm,
817                                 unformat_input_t * input,
818                                 vlib_cli_command_t * cmd)
819 {
820   unformat_input_t _line_input, *line_input = &_line_input;
821   u32 log_level = IKEV2_LOG_NONE;
822   clib_error_t *error = 0;
823
824   /* Get a line of input. */
825   if (!unformat_user (input, unformat_line_input, line_input))
826     return 0;
827
828   if (!unformat (line_input, "%d", &log_level))
829     {
830       error = clib_error_return (0, "unknown input '%U'",
831                                  format_unformat_error, line_input);
832       goto done;
833     }
834   int rc = ikev2_set_log_level (log_level);
835   if (rc < 0)
836     error = clib_error_return (0, "setting log level failed!");
837
838 done:
839   unformat_free (line_input);
840   return error;
841 }
842
843 /* *INDENT-OFF* */
844 VLIB_CLI_COMMAND (ikev2_set_log_level_command, static) = {
845   .path = "ikev2 set logging level",
846   .function = ikev2_set_log_level_command_fn,
847   .short_help = "ikev2 set logging level <0-5>",
848 };
849 /* *INDENT-ON* */
850
851 /*
852  * fd.io coding-style-patch-verification: ON
853  *
854  * Local Variables:
855  * eval: (c-set-style "gnu")
856  * End:
857  */