misc: minimize dependencies on udp.h
[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 uword
251 unformat_ikev2_token (unformat_input_t * input, va_list * va)
252 {
253   u8 **string_return = va_arg (*va, u8 **);
254   const char *token_chars = "a-zA-Z0-9_";
255   if (*string_return)
256     {
257       /* if string_return was already allocated (eg. because of a previous
258        * partial match with a successful unformat_token()), we must free it
259        * before reusing the pointer, otherwise we'll be leaking memory
260        */
261       vec_free (*string_return);
262       *string_return = 0;
263     }
264   return unformat_user (input, unformat_token, token_chars, string_return);
265 }
266
267 static clib_error_t *
268 ikev2_profile_add_del_command_fn (vlib_main_t * vm,
269                                   unformat_input_t * input,
270                                   vlib_cli_command_t * cmd)
271 {
272   vnet_main_t *vnm = vnet_get_main ();
273   unformat_input_t _line_input, *line_input = &_line_input;
274   u8 *name = 0;
275   clib_error_t *r = 0;
276   u32 id_type;
277   u8 *data = 0;
278   u32 tmp1, tmp2, tmp3;
279   u64 tmp4, tmp5;
280   ip_address_t ip, end_addr;
281   u32 responder_sw_if_index = (u32) ~ 0;
282   u32 tun_sw_if_index = (u32) ~ 0;
283   ikev2_transform_encr_type_t crypto_alg;
284   ikev2_transform_integ_type_t integ_alg;
285   ikev2_transform_dh_type_t dh_type;
286
287   if (!unformat_user (input, unformat_line_input, line_input))
288     return 0;
289
290   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
291     {
292       if (unformat (line_input, "add %U", unformat_ikev2_token, &name))
293         {
294           r = ikev2_add_del_profile (vm, name, 1);
295           goto done;
296         }
297       else if (unformat (line_input, "del %U", unformat_ikev2_token, &name))
298         {
299           r = ikev2_add_del_profile (vm, name, 0);
300           goto done;
301         }
302       else if (unformat (line_input, "set %U auth shared-key-mic string %v",
303                          unformat_ikev2_token, &name, &data))
304         {
305           r =
306             ikev2_set_profile_auth (vm, name,
307                                     IKEV2_AUTH_METHOD_SHARED_KEY_MIC, data,
308                                     0);
309           goto done;
310         }
311       else if (unformat (line_input, "set %U auth shared-key-mic hex %U",
312                          unformat_ikev2_token, &name,
313                          unformat_hex_string, &data))
314         {
315           r =
316             ikev2_set_profile_auth (vm, name,
317                                     IKEV2_AUTH_METHOD_SHARED_KEY_MIC, data,
318                                     1);
319           goto done;
320         }
321       else if (unformat (line_input, "set %U auth rsa-sig cert-file %v",
322                          unformat_ikev2_token, &name, &data))
323         {
324           r =
325             ikev2_set_profile_auth (vm, name, IKEV2_AUTH_METHOD_RSA_SIG, data,
326                                     0);
327           goto done;
328         }
329       else if (unformat (line_input, "set %U id local %U %U",
330                          unformat_ikev2_token, &name,
331                          unformat_ikev2_id_type, &id_type,
332                          unformat_ip_address, &ip))
333         {
334           data = vec_new (u8, ip_address_size (&ip));
335           clib_memcpy (data, ip_addr_bytes (&ip), ip_address_size (&ip));
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 0x%U",
341                          unformat_ikev2_token, &name,
342                          unformat_ikev2_id_type, &id_type,
343                          unformat_hex_string, &data))
344         {
345           r =
346             ikev2_set_profile_id (vm, name, (u8) id_type, data, /*local */ 1);
347           goto done;
348         }
349       else if (unformat (line_input, "set %U id local %U %v",
350                          unformat_ikev2_token, &name,
351                          unformat_ikev2_id_type, &id_type, &data))
352         {
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 remote %U %U",
358                          unformat_ikev2_token, &name,
359                          unformat_ikev2_id_type, &id_type,
360                          unformat_ip_address, &ip))
361         {
362           data = vec_new (u8, ip_address_size (&ip));
363           clib_memcpy (data, ip_addr_bytes (&ip), ip_address_size (&ip));
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 0x%U",
369                          unformat_ikev2_token, &name,
370                          unformat_ikev2_id_type, &id_type,
371                          unformat_hex_string, &data))
372         {
373           r = ikev2_set_profile_id (vm, name, (u8) id_type, data,       /*remote */
374                                     0);
375           goto done;
376         }
377       else if (unformat (line_input, "set %U id remote %U %v",
378                          unformat_ikev2_token, &name,
379                          unformat_ikev2_id_type, &id_type, &data))
380         {
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 traffic-selector local "
386                          "ip-range %U - %U port-range %u - %u protocol %u",
387                          unformat_ikev2_token, &name,
388                          unformat_ip_address, &ip,
389                          unformat_ip_address, &end_addr, &tmp1, &tmp2, &tmp3))
390         {
391           r =
392             ikev2_set_profile_ts (vm, name, (u8) tmp3, (u16) tmp1, (u16) tmp2,
393                                   ip, end_addr, /*local */ 1);
394           goto done;
395         }
396       else if (unformat (line_input, "set %U traffic-selector remote "
397                          "ip-range %U - %U port-range %u - %u protocol %u",
398                          unformat_ikev2_token, &name,
399                          unformat_ip_address, &ip,
400                          unformat_ip_address, &end_addr, &tmp1, &tmp2, &tmp3))
401         {
402           r =
403             ikev2_set_profile_ts (vm, name, (u8) tmp3, (u16) tmp1, (u16) tmp2,
404                                   ip, end_addr, /*remote */ 0);
405           goto done;
406         }
407       else if (unformat (line_input, "set %U responder %U %U",
408                          unformat_ikev2_token, &name,
409                          unformat_vnet_sw_interface, vnm,
410                          &responder_sw_if_index, unformat_ip_address, &ip))
411         {
412           r =
413             ikev2_set_profile_responder (vm, name, responder_sw_if_index, ip);
414           goto done;
415         }
416       else if (unformat (line_input, "set %U tunnel %U",
417                          unformat_ikev2_token, &name,
418                          unformat_vnet_sw_interface, vnm, &tun_sw_if_index))
419         {
420           r = ikev2_set_profile_tunnel_interface (vm, name, tun_sw_if_index);
421           goto done;
422         }
423       else
424         if (unformat
425             (line_input,
426              "set %U ike-crypto-alg %U %u ike-integ-alg %U ike-dh %U",
427              unformat_ikev2_token, &name,
428              unformat_ikev2_transform_encr_type, &crypto_alg, &tmp1,
429              unformat_ikev2_transform_integ_type, &integ_alg,
430              unformat_ikev2_transform_dh_type, &dh_type))
431         {
432           r =
433             ikev2_set_profile_ike_transforms (vm, name, crypto_alg, integ_alg,
434                                               dh_type, tmp1);
435           goto done;
436         }
437       else
438         if (unformat
439             (line_input,
440              "set %U ike-crypto-alg %U %u ike-dh %U",
441              unformat_ikev2_token, &name,
442              unformat_ikev2_transform_encr_type, &crypto_alg, &tmp1,
443              unformat_ikev2_transform_dh_type, &dh_type))
444         {
445           r =
446             ikev2_set_profile_ike_transforms (vm, name, crypto_alg,
447                                               IKEV2_TRANSFORM_INTEG_TYPE_NONE,
448                                               dh_type, tmp1);
449           goto done;
450         }
451       else
452         if (unformat
453             (line_input,
454              "set %U esp-crypto-alg %U %u esp-integ-alg %U",
455              unformat_ikev2_token, &name,
456              unformat_ikev2_transform_encr_type, &crypto_alg, &tmp1,
457              unformat_ikev2_transform_integ_type, &integ_alg))
458         {
459           r =
460             ikev2_set_profile_esp_transforms (vm, name, crypto_alg, integ_alg,
461                                               tmp1);
462           goto done;
463         }
464       else if (unformat
465                (line_input,
466                 "set %U esp-crypto-alg %U %u",
467                 unformat_ikev2_token, &name,
468                 unformat_ikev2_transform_encr_type, &crypto_alg, &tmp1))
469         {
470           r =
471             ikev2_set_profile_esp_transforms (vm, name, crypto_alg, 0, tmp1);
472           goto done;
473         }
474       else if (unformat (line_input, "set %U sa-lifetime %lu %u %u %lu",
475                          unformat_ikev2_token, &name,
476                          &tmp4, &tmp1, &tmp2, &tmp5))
477         {
478           r =
479             ikev2_set_profile_sa_lifetime (vm, name, tmp4, tmp1, tmp2, tmp5);
480           goto done;
481         }
482       else if (unformat (line_input, "set %U udp-encap",
483                          unformat_ikev2_token, &name))
484         {
485           r = ikev2_set_profile_udp_encap (vm, name);
486           goto done;
487         }
488       else if (unformat (line_input, "set %U ipsec-over-udp port %u",
489                          unformat_ikev2_token, &name, &tmp1))
490         {
491           int rv = ikev2_set_profile_ipsec_udp_port (vm, name, tmp1, 1);
492           if (rv)
493             r = clib_error_return (0, "Error: %U", format_vnet_api_errno, rv);
494           goto done;
495         }
496       else
497         break;
498     }
499
500   r = clib_error_return (0, "parse error: '%U'",
501                          format_unformat_error, line_input);
502
503 done:
504   vec_free (name);
505   vec_free (data);
506   unformat_free (line_input);
507   return r;
508 }
509
510 /* *INDENT-OFF* */
511 VLIB_CLI_COMMAND (ikev2_profile_add_del_command, static) = {
512     .path = "ikev2 profile",
513     .short_help =
514     "ikev2 profile [add|del] <id>\n"
515     "ikev2 profile set <id> auth [rsa-sig|shared-key-mic] [cert-file|string|hex]"
516     " <data>\n"
517     "ikev2 profile set <id> id <local|remote> <type> <data>\n"
518     "ikev2 profile set <id> tunnel <interface>\n"
519     "ikev2 profile set <id> udp-encap\n"
520     "ikev2 profile set <id> traffic-selector <local|remote> ip-range "
521     "<start-addr> - <end-addr> port-range <start-port> - <end-port> "
522     "protocol <protocol-number>\n"
523     "ikev2 profile set <id> responder <interface> <addr>\n"
524     "ikev2 profile set <id> ike-crypto-alg <crypto alg> <key size> ike-integ-alg <integ alg> ike-dh <dh type>\n"
525     "ikev2 profile set <id> esp-crypto-alg <crypto alg> <key size> "
526       "[esp-integ-alg <integ alg>]\n"
527     "ikev2 profile set <id> sa-lifetime <seconds> <jitter> <handover> <max bytes>",
528     .function = ikev2_profile_add_del_command_fn,
529 };
530 /* *INDENT-ON* */
531
532 static clib_error_t *
533 show_ikev2_profile_command_fn (vlib_main_t * vm,
534                                unformat_input_t * input,
535                                vlib_cli_command_t * cmd)
536 {
537   ikev2_main_t *km = &ikev2_main;
538   ikev2_profile_t *p;
539
540   /* *INDENT-OFF* */
541   pool_foreach (p, km->profiles, ({
542     vlib_cli_output(vm, "profile %v", p->name);
543
544     if (p->auth.data)
545       {
546         if (p->auth.hex)
547           vlib_cli_output(vm, "  auth-method %U auth data 0x%U",
548                           format_ikev2_auth_method, p->auth.method,
549                           format_hex_bytes, p->auth.data, vec_len(p->auth.data));
550         else
551           vlib_cli_output(vm, "  auth-method %U auth data %v",
552                    format_ikev2_auth_method, p->auth.method, p->auth.data);
553       }
554
555     if (p->loc_id.data)
556       {
557         if (p->loc_id.type == IKEV2_ID_TYPE_ID_IPV4_ADDR)
558           vlib_cli_output(vm, "  local id-type %U data %U",
559                           format_ikev2_id_type, p->loc_id.type,
560                           format_ip_address, p->loc_id.data);
561         else if (p->loc_id.type == IKEV2_ID_TYPE_ID_KEY_ID)
562           vlib_cli_output(vm, "  local id-type %U data 0x%U",
563                           format_ikev2_id_type, p->loc_id.type,
564                           format_hex_bytes, p->loc_id.data,
565                           vec_len(p->loc_id.data));
566         else
567           vlib_cli_output(vm, "  local id-type %U data %v",
568                           format_ikev2_id_type, p->loc_id.type, p->loc_id.data);
569       }
570
571     if (p->rem_id.data)
572       {
573         if (p->rem_id.type == IKEV2_ID_TYPE_ID_IPV4_ADDR)
574           vlib_cli_output(vm, "  remote id-type %U data %U",
575                           format_ikev2_id_type, p->rem_id.type,
576                           format_ip_address, p->rem_id.data);
577         else if (p->rem_id.type == IKEV2_ID_TYPE_ID_KEY_ID)
578           vlib_cli_output(vm, "  remote id-type %U data 0x%U",
579                           format_ikev2_id_type, p->rem_id.type,
580                           format_hex_bytes, p->rem_id.data,
581                           vec_len(p->rem_id.data));
582         else
583           vlib_cli_output(vm, "  remote id-type %U data %v",
584                           format_ikev2_id_type, p->rem_id.type, p->rem_id.data);
585       }
586
587     if (!ip_address_is_zero (&p->loc_ts.start_addr))
588       vlib_cli_output(vm, "  local traffic-selector addr %U - %U port %u - %u"
589                       " protocol %u",
590                       format_ip_address, &p->loc_ts.start_addr,
591                       format_ip_address, &p->loc_ts.end_addr,
592                       p->loc_ts.start_port, p->loc_ts.end_port,
593                       p->loc_ts.protocol_id);
594
595     if (!ip_address_is_zero (&p->rem_ts.start_addr))
596       vlib_cli_output(vm, "  remote traffic-selector addr %U - %U port %u - %u"
597                       " protocol %u",
598                       format_ip_address, &p->rem_ts.start_addr,
599                       format_ip_address, &p->rem_ts.end_addr,
600                       p->rem_ts.start_port, p->rem_ts.end_port,
601                       p->rem_ts.protocol_id);
602     if (~0 != p->tun_itf)
603       vlib_cli_output(vm, "  protected tunnel %U",
604                       format_vnet_sw_if_index_name, vnet_get_main(), p->tun_itf);
605     if (~0 != p->responder.sw_if_index)
606       vlib_cli_output(vm, "  responder %U %U",
607                       format_vnet_sw_if_index_name, vnet_get_main(), p->responder.sw_if_index,
608                       format_ip_address, &p->responder.addr);
609     if (p->udp_encap)
610       vlib_cli_output(vm, "  udp-encap");
611
612     if (p->ipsec_over_udp_port != IPSEC_UDP_PORT_NONE)
613       vlib_cli_output(vm, "  ipsec-over-udp port %d", p->ipsec_over_udp_port);
614
615     if (p->ike_ts.crypto_alg || p->ike_ts.integ_alg || p->ike_ts.dh_type || p->ike_ts.crypto_key_size)
616       vlib_cli_output(vm, "  ike-crypto-alg %U %u ike-integ-alg %U ike-dh %U",
617                     format_ikev2_transform_encr_type, p->ike_ts.crypto_alg, p->ike_ts.crypto_key_size,
618                     format_ikev2_transform_integ_type, p->ike_ts.integ_alg,
619                     format_ikev2_transform_dh_type, p->ike_ts.dh_type);
620
621     if (p->esp_ts.crypto_alg || p->esp_ts.integ_alg || p->esp_ts.dh_type)
622       vlib_cli_output(vm, "  esp-crypto-alg %U %u esp-integ-alg %U",
623                     format_ikev2_transform_encr_type, p->esp_ts.crypto_alg, p->esp_ts.crypto_key_size,
624                     format_ikev2_transform_integ_type, p->esp_ts.integ_alg);
625
626     vlib_cli_output(vm, "  lifetime %d jitter %d handover %d maxdata %d",
627                     p->lifetime, p->lifetime_jitter, p->handover, p->lifetime_maxdata);
628   }));
629   /* *INDENT-ON* */
630
631   return 0;
632 }
633
634 /* *INDENT-OFF* */
635 VLIB_CLI_COMMAND (show_ikev2_profile_command, static) = {
636     .path = "show ikev2 profile",
637     .short_help = "show ikev2 profile",
638     .function = show_ikev2_profile_command_fn,
639 };
640 /* *INDENT-ON* */
641
642 static clib_error_t *
643 set_ikev2_liveness_period_fn (vlib_main_t * vm,
644                               unformat_input_t * input,
645                               vlib_cli_command_t * cmd)
646 {
647   unformat_input_t _line_input, *line_input = &_line_input;
648   clib_error_t *r = 0;
649   u32 period = 0, max_retries = 0;
650
651   if (!unformat_user (input, unformat_line_input, line_input))
652     return 0;
653
654   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
655     {
656       if (unformat (line_input, "%d %d", &period, &max_retries))
657         {
658           r = ikev2_set_liveness_params (period, max_retries);
659           goto done;
660         }
661       else
662         break;
663     }
664
665   r = clib_error_return (0, "parse error: '%U'",
666                          format_unformat_error, line_input);
667
668 done:
669   unformat_free (line_input);
670   return r;
671 }
672
673 /* *INDENT-OFF* */
674 VLIB_CLI_COMMAND (set_ikev2_liveness_command, static) = {
675   .path = "ikev2 set liveness",
676   .short_help = "ikev2 set liveness <period> <max-retires>",
677   .function = set_ikev2_liveness_period_fn,
678 };
679 /* *INDENT-ON* */
680
681 static clib_error_t *
682 set_ikev2_local_key_command_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   u8 *data = 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, "%s", &data))
696         {
697           r = ikev2_set_local_key (vm, data);
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   vec_free (data);
709   unformat_free (line_input);
710   return r;
711 }
712
713 /* *INDENT-OFF* */
714 VLIB_CLI_COMMAND (set_ikev2_local_key_command, static) = {
715     .path = "set ikev2 local key",
716     .short_help =
717     "set ikev2 local key <file>",
718     .function = set_ikev2_local_key_command_fn,
719 };
720 /* *INDENT-ON* */
721
722
723 static clib_error_t *
724 ikev2_initiate_command_fn (vlib_main_t * vm,
725                            unformat_input_t * input, vlib_cli_command_t * cmd)
726 {
727   unformat_input_t _line_input, *line_input = &_line_input;
728   clib_error_t *r = 0;
729   u8 *name = 0;
730   u32 tmp1;
731   u64 tmp2;
732
733   if (!unformat_user (input, unformat_line_input, line_input))
734     return 0;
735
736   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
737     {
738       if (unformat (line_input, "sa-init %U", unformat_ikev2_token, &name))
739         {
740           r = ikev2_initiate_sa_init (vm, name);
741           goto done;
742         }
743       else if (unformat (line_input, "del-child-sa %x", &tmp1))
744         {
745           r = ikev2_initiate_delete_child_sa (vm, tmp1);
746           goto done;
747         }
748       else if (unformat (line_input, "del-sa %lx", &tmp2))
749         {
750           r = ikev2_initiate_delete_ike_sa (vm, tmp2);
751           goto done;
752         }
753       else if (unformat (line_input, "rekey-child-sa %x", &tmp1))
754         {
755           r = ikev2_initiate_rekey_child_sa (vm, tmp1);
756           goto done;
757         }
758       else
759         break;
760     }
761
762   r = clib_error_return (0, "parse error: '%U'",
763                          format_unformat_error, line_input);
764
765 done:
766   vec_free (name);
767   unformat_free (line_input);
768   return r;
769 }
770
771 /* *INDENT-OFF* */
772 VLIB_CLI_COMMAND (ikev2_initiate_command, static) = {
773     .path = "ikev2 initiate",
774     .short_help =
775         "ikev2 initiate sa-init <profile id>\n"
776         "ikev2 initiate del-child-sa <child sa ispi>\n"
777         "ikev2 initiate del-sa <sa ispi>\n"
778         "ikev2 initiate rekey-child-sa <profile id> <child sa ispi>\n",
779     .function = ikev2_initiate_command_fn,
780 };
781 /* *INDENT-ON* */
782
783 void
784 ikev2_cli_reference (void)
785 {
786 }
787
788 static clib_error_t *
789 ikev2_set_log_level_command_fn (vlib_main_t * vm,
790                                 unformat_input_t * input,
791                                 vlib_cli_command_t * cmd)
792 {
793   unformat_input_t _line_input, *line_input = &_line_input;
794   u32 log_level = IKEV2_LOG_NONE;
795   clib_error_t *error = 0;
796
797   /* Get a line of input. */
798   if (!unformat_user (input, unformat_line_input, line_input))
799     return 0;
800
801   if (!unformat (line_input, "%d", &log_level))
802     {
803       error = clib_error_return (0, "unknown input '%U'",
804                                  format_unformat_error, line_input);
805       goto done;
806     }
807   int rc = ikev2_set_log_level (log_level);
808   if (rc < 0)
809     error = clib_error_return (0, "setting log level failed!");
810
811 done:
812   unformat_free (line_input);
813   return error;
814 }
815
816 /* *INDENT-OFF* */
817 VLIB_CLI_COMMAND (ikev2_set_log_level_command, static) = {
818   .path = "ikev2 set logging level",
819   .function = ikev2_set_log_level_command_fn,
820   .short_help = "ikev2 set logging level <0-5>",
821 };
822 /* *INDENT-ON* */
823
824 /*
825  * fd.io coding-style-patch-verification: ON
826  *
827  * Local Variables:
828  * eval: (c-set-style "gnu")
829  * End:
830  */