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