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