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