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