fix data_length in IpSec API call (VPP-1548)
[vpp.git] / src / vnet / ipsec / ipsec_api.c
1 /*
2  *------------------------------------------------------------------
3  * ipsec_api.c - ipsec api
4  *
5  * Copyright (c) 2016 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <vnet/vnet.h>
21 #include <vlibmemory/api.h>
22
23 #include <vnet/interface.h>
24 #include <vnet/api_errno.h>
25 #include <vnet/ip/ip.h>
26 #include <vnet/fib/fib.h>
27
28 #include <vnet/vnet_msg_enum.h>
29
30 #if WITH_LIBSSL > 0
31 #include <vnet/ipsec/ipsec.h>
32 #include <vnet/ipsec/ikev2.h>
33 #endif /* IPSEC */
34
35 #define vl_typedefs             /* define message structures */
36 #include <vnet/vnet_all_api_h.h>
37 #undef vl_typedefs
38
39 #define vl_endianfun            /* define message structures */
40 #include <vnet/vnet_all_api_h.h>
41 #undef vl_endianfun
42
43 /* instantiate all the print functions we know about */
44 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
45 #define vl_printfun
46 #include <vnet/vnet_all_api_h.h>
47 #undef vl_printfun
48
49 #include <vlibapi/api_helper_macros.h>
50
51 #define foreach_vpe_api_msg                                     \
52 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del)                         \
53 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd)     \
54 _(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry)             \
55 _(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry)             \
56 _(IPSEC_SA_SET_KEY, ipsec_sa_set_key)                           \
57 _(IPSEC_SA_DUMP, ipsec_sa_dump)                                 \
58 _(IPSEC_SPDS_DUMP, ipsec_spds_dump)                             \
59 _(IPSEC_SPD_DUMP, ipsec_spd_dump)                               \
60 _(IPSEC_SPD_INTERFACE_DUMP, ipsec_spd_interface_dump)           \
61 _(IPSEC_TUNNEL_IF_ADD_DEL, ipsec_tunnel_if_add_del)             \
62 _(IPSEC_TUNNEL_IF_SET_KEY, ipsec_tunnel_if_set_key)             \
63 _(IPSEC_TUNNEL_IF_SET_SA, ipsec_tunnel_if_set_sa)               \
64 _(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del)                 \
65 _(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth)               \
66 _(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id)                   \
67 _(IKEV2_PROFILE_SET_TS, ikev2_profile_set_ts)                   \
68 _(IKEV2_SET_LOCAL_KEY, ikev2_set_local_key)                     \
69 _(IKEV2_SET_RESPONDER, ikev2_set_responder)                     \
70 _(IKEV2_SET_IKE_TRANSFORMS, ikev2_set_ike_transforms)           \
71 _(IKEV2_SET_ESP_TRANSFORMS, ikev2_set_esp_transforms)           \
72 _(IKEV2_SET_SA_LIFETIME, ikev2_set_sa_lifetime)                 \
73 _(IKEV2_INITIATE_SA_INIT, ikev2_initiate_sa_init)               \
74 _(IKEV2_INITIATE_DEL_IKE_SA, ikev2_initiate_del_ike_sa)         \
75 _(IKEV2_INITIATE_DEL_CHILD_SA, ikev2_initiate_del_child_sa)     \
76 _(IKEV2_INITIATE_REKEY_CHILD_SA, ikev2_initiate_rekey_child_sa) \
77 _(IPSEC_SELECT_BACKEND, ipsec_select_backend)                   \
78 _(IPSEC_BACKEND_DUMP, ipsec_backend_dump)
79
80 static void
81 vl_api_ipsec_spd_add_del_t_handler (vl_api_ipsec_spd_add_del_t * mp)
82 {
83 #if WITH_LIBSSL == 0
84   clib_warning ("unimplemented");
85 #else
86
87   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
88   vl_api_ipsec_spd_add_del_reply_t *rmp;
89   int rv;
90
91   rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
92
93   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
94 #endif
95 }
96
97 static void vl_api_ipsec_interface_add_del_spd_t_handler
98   (vl_api_ipsec_interface_add_del_spd_t * mp)
99 {
100   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
101   vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
102   int rv;
103   u32 sw_if_index __attribute__ ((unused));
104   u32 spd_id __attribute__ ((unused));
105
106   sw_if_index = ntohl (mp->sw_if_index);
107   spd_id = ntohl (mp->spd_id);
108
109   VALIDATE_SW_IF_INDEX (mp);
110
111 #if WITH_LIBSSL > 0
112   rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
113 #else
114   rv = VNET_API_ERROR_UNIMPLEMENTED;
115 #endif
116
117   BAD_SW_IF_INDEX_LABEL;
118
119   REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
120 }
121
122 static void vl_api_ipsec_spd_add_del_entry_t_handler
123   (vl_api_ipsec_spd_add_del_entry_t * mp)
124 {
125   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
126   vl_api_ipsec_spd_add_del_entry_reply_t *rmp;
127   int rv;
128
129 #if WITH_LIBSSL > 0
130   ipsec_policy_t p;
131
132   clib_memset (&p, 0, sizeof (p));
133
134   p.id = ntohl (mp->spd_id);
135   p.priority = ntohl (mp->priority);
136   p.is_outbound = mp->is_outbound;
137   p.is_ipv6 = mp->is_ipv6;
138
139   if (mp->is_ipv6 || mp->is_ip_any)
140     {
141       clib_memcpy (&p.raddr.start, mp->remote_address_start, 16);
142       clib_memcpy (&p.raddr.stop, mp->remote_address_stop, 16);
143       clib_memcpy (&p.laddr.start, mp->local_address_start, 16);
144       clib_memcpy (&p.laddr.stop, mp->local_address_stop, 16);
145     }
146   else
147     {
148       clib_memcpy (&p.raddr.start.ip4.data, mp->remote_address_start, 4);
149       clib_memcpy (&p.raddr.stop.ip4.data, mp->remote_address_stop, 4);
150       clib_memcpy (&p.laddr.start.ip4.data, mp->local_address_start, 4);
151       clib_memcpy (&p.laddr.stop.ip4.data, mp->local_address_stop, 4);
152     }
153   p.protocol = mp->protocol;
154   p.rport.start = ntohs (mp->remote_port_start);
155   p.rport.stop = ntohs (mp->remote_port_stop);
156   p.lport.start = ntohs (mp->local_port_start);
157   p.lport.stop = ntohs (mp->local_port_stop);
158   /* policy action resolve unsupported */
159   if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE)
160     {
161       clib_warning ("unsupported action: 'resolve'");
162       rv = VNET_API_ERROR_UNIMPLEMENTED;
163       goto out;
164     }
165   p.policy = mp->policy;
166   p.sa_id = ntohl (mp->sa_id);
167
168   rv = ipsec_add_del_policy (vm, &p, mp->is_add);
169   if (rv)
170     goto out;
171
172   if (mp->is_ip_any)
173     {
174       p.is_ipv6 = 1;
175       rv = ipsec_add_del_policy (vm, &p, mp->is_add);
176     }
177 #else
178   rv = VNET_API_ERROR_UNIMPLEMENTED;
179   goto out;
180 #endif
181
182 out:
183   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
184 }
185
186 static void vl_api_ipsec_sad_add_del_entry_t_handler
187   (vl_api_ipsec_sad_add_del_entry_t * mp)
188 {
189   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
190   vl_api_ipsec_sad_add_del_entry_reply_t *rmp;
191   int rv;
192 #if WITH_LIBSSL > 0
193   ipsec_main_t *im = &ipsec_main;
194   ipsec_sa_t sa;
195
196   clib_memset (&sa, 0, sizeof (sa));
197
198   sa.id = ntohl (mp->sad_id);
199   sa.spi = ntohl (mp->spi);
200   sa.protocol = mp->protocol;
201   /* check for unsupported crypto-alg */
202   if (mp->crypto_algorithm >= IPSEC_CRYPTO_N_ALG)
203     {
204       clib_warning ("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
205                     mp->crypto_algorithm);
206       rv = VNET_API_ERROR_UNIMPLEMENTED;
207       goto out;
208     }
209   sa.crypto_alg = mp->crypto_algorithm;
210   sa.crypto_key_len = mp->crypto_key_length;
211   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
212   /* check for unsupported integ-alg */
213   if (mp->integrity_algorithm >= IPSEC_INTEG_N_ALG)
214     {
215       clib_warning ("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
216                     mp->integrity_algorithm);
217       rv = VNET_API_ERROR_UNIMPLEMENTED;
218       goto out;
219     }
220
221   sa.integ_alg = mp->integrity_algorithm;
222   sa.integ_key_len = mp->integrity_key_length;
223   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
224   sa.use_esn = mp->use_extended_sequence_number;
225   sa.is_tunnel = mp->is_tunnel;
226   sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
227   sa.udp_encap = mp->udp_encap;
228   if (sa.is_tunnel_ip6)
229     {
230       clib_memcpy (&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
231       clib_memcpy (&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
232     }
233   else
234     {
235       clib_memcpy (&sa.tunnel_src_addr.ip4.data, mp->tunnel_src_address, 4);
236       clib_memcpy (&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4);
237     }
238   sa.use_anti_replay = mp->use_anti_replay;
239
240   clib_error_t *err = ipsec_check_support_cb (im, &sa);
241   if (err)
242     {
243       clib_warning ("%s", err->what);
244       rv = VNET_API_ERROR_UNIMPLEMENTED;
245       goto out;
246     }
247
248   rv = ipsec_add_del_sa (vm, &sa, mp->is_add);
249 #else
250   rv = VNET_API_ERROR_UNIMPLEMENTED;
251   goto out;
252 #endif
253
254 out:
255   REPLY_MACRO (VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
256 }
257
258 static void
259 send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg,
260                          u32 context)
261 {
262   vl_api_ipsec_spds_details_t *mp;
263
264   mp = vl_msg_api_alloc (sizeof (*mp));
265   clib_memset (mp, 0, sizeof (*mp));
266   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPDS_DETAILS);
267   mp->context = context;
268
269   mp->spd_id = htonl (spd->id);
270   mp->npolicies = htonl (pool_len (spd->policies));
271
272   vl_api_send_msg (reg, (u8 *) mp);
273 }
274
275 static void
276 vl_api_ipsec_spds_dump_t_handler (vl_api_ipsec_spds_dump_t * mp)
277 {
278   vl_api_registration_t *reg;
279   ipsec_main_t *im = &ipsec_main;
280   ipsec_spd_t *spd;
281 #if WITH_LIBSSL > 0
282   reg = vl_api_client_index_to_registration (mp->client_index);
283   if (!reg)
284     return;
285
286   /* *INDENT-OFF* */
287   pool_foreach (spd, im->spds, ({
288     send_ipsec_spds_details (spd, reg, mp->context);
289   }));
290   /* *INDENT-ON* */
291 #else
292   clib_warning ("unimplemented");
293 #endif
294 }
295
296 static void
297 send_ipsec_spd_details (ipsec_policy_t * p, vl_api_registration_t * reg,
298                         u32 context)
299 {
300   vl_api_ipsec_spd_details_t *mp;
301
302   mp = vl_msg_api_alloc (sizeof (*mp));
303   clib_memset (mp, 0, sizeof (*mp));
304   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
305   mp->context = context;
306
307   mp->spd_id = htonl (p->id);
308   mp->priority = htonl (p->priority);
309   mp->is_outbound = p->is_outbound;
310   mp->is_ipv6 = p->is_ipv6;
311   if (p->is_ipv6)
312     {
313       memcpy (mp->local_start_addr, &p->laddr.start.ip6, 16);
314       memcpy (mp->local_stop_addr, &p->laddr.stop.ip6, 16);
315       memcpy (mp->remote_start_addr, &p->raddr.start.ip6, 16);
316       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip6, 16);
317     }
318   else
319     {
320       memcpy (mp->local_start_addr, &p->laddr.start.ip4, 4);
321       memcpy (mp->local_stop_addr, &p->laddr.stop.ip4, 4);
322       memcpy (mp->remote_start_addr, &p->raddr.start.ip4, 4);
323       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip4, 4);
324     }
325   mp->local_start_port = htons (p->lport.start);
326   mp->local_stop_port = htons (p->lport.stop);
327   mp->remote_start_port = htons (p->rport.start);
328   mp->remote_stop_port = htons (p->rport.stop);
329   mp->protocol = p->protocol;
330   mp->policy = p->policy;
331   mp->sa_id = htonl (p->sa_id);
332   mp->bytes = clib_host_to_net_u64 (p->counter.bytes);
333   mp->packets = clib_host_to_net_u64 (p->counter.packets);
334
335   vl_api_send_msg (reg, (u8 *) mp);
336 }
337
338 static void
339 vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
340 {
341   vl_api_registration_t *reg;
342   ipsec_main_t *im = &ipsec_main;
343   ipsec_policy_t *policy;
344   ipsec_spd_t *spd;
345   uword *p;
346   u32 spd_index;
347 #if WITH_LIBSSL > 0
348   reg = vl_api_client_index_to_registration (mp->client_index);
349   if (!reg)
350     return;
351
352   p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
353   if (!p)
354     return;
355
356   spd_index = p[0];
357   spd = pool_elt_at_index (im->spds, spd_index);
358
359   /* *INDENT-OFF* */
360   pool_foreach (policy, spd->policies,
361   ({
362     if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
363       send_ipsec_spd_details (policy, reg,
364                               mp->context);}
365     ));
366   /* *INDENT-ON* */
367 #else
368   clib_warning ("unimplemented");
369 #endif
370 }
371
372 static void
373 send_ipsec_spd_interface_details (vl_api_registration_t * reg, u32 spd_index,
374                                   u32 sw_if_index, u32 context)
375 {
376   vl_api_ipsec_spd_interface_details_t *mp;
377
378   mp = vl_msg_api_alloc (sizeof (*mp));
379   clib_memset (mp, 0, sizeof (*mp));
380   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_INTERFACE_DETAILS);
381   mp->context = context;
382
383   mp->spd_index = htonl (spd_index);
384   mp->sw_if_index = htonl (sw_if_index);
385
386   vl_api_send_msg (reg, (u8 *) mp);
387 }
388
389 static void
390 vl_api_ipsec_spd_interface_dump_t_handler (vl_api_ipsec_spd_interface_dump_t *
391                                            mp)
392 {
393   ipsec_main_t *im = &ipsec_main;
394   vl_api_registration_t *reg;
395   u32 k, v, spd_index;
396
397 #if WITH_LIBSSL > 0
398   reg = vl_api_client_index_to_registration (mp->client_index);
399   if (!reg)
400     return;
401
402   if (mp->spd_index_valid)
403     {
404       spd_index = ntohl (mp->spd_index);
405       /* *INDENT-OFF* */
406       hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
407         if (v == spd_index)
408           send_ipsec_spd_interface_details(reg, v, k, mp->context);
409       }));
410       /* *INDENT-ON* */
411     }
412   else
413     {
414       /* *INDENT-OFF* */
415       hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
416         send_ipsec_spd_interface_details(reg, v, k, mp->context);
417       }));
418       /* *INDENT-ON* */
419     }
420
421 #else
422   clib_warning ("unimplemented");
423 #endif
424 }
425
426 static void
427 vl_api_ipsec_sa_set_key_t_handler (vl_api_ipsec_sa_set_key_t * mp)
428 {
429   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
430   vl_api_ipsec_sa_set_key_reply_t *rmp;
431   int rv;
432 #if WITH_LIBSSL > 0
433   ipsec_sa_t sa;
434   sa.id = ntohl (mp->sa_id);
435   sa.crypto_key_len = mp->crypto_key_length;
436   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
437   sa.integ_key_len = mp->integrity_key_length;
438   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
439
440   rv = ipsec_set_sa_key (vm, &sa);
441 #else
442   rv = VNET_API_ERROR_UNIMPLEMENTED;
443 #endif
444
445   REPLY_MACRO (VL_API_IPSEC_SA_SET_KEY_REPLY);
446 }
447
448 static void
449 vl_api_ipsec_tunnel_if_add_del_t_handler (vl_api_ipsec_tunnel_if_add_del_t *
450                                           mp)
451 {
452   vl_api_ipsec_tunnel_if_add_del_reply_t *rmp;
453   ipsec_main_t *im = &ipsec_main;
454   vnet_main_t *vnm = im->vnet_main;
455   u32 sw_if_index = ~0;
456   int rv;
457
458 #if WITH_LIBSSL > 0
459   ipsec_add_del_tunnel_args_t tun;
460
461   clib_memset (&tun, 0, sizeof (ipsec_add_del_tunnel_args_t));
462
463   tun.is_add = mp->is_add;
464   tun.esn = mp->esn;
465   tun.anti_replay = mp->anti_replay;
466   tun.local_spi = ntohl (mp->local_spi);
467   tun.remote_spi = ntohl (mp->remote_spi);
468   tun.crypto_alg = mp->crypto_alg;
469   tun.local_crypto_key_len = mp->local_crypto_key_len;
470   tun.remote_crypto_key_len = mp->remote_crypto_key_len;
471   tun.integ_alg = mp->integ_alg;
472   tun.local_integ_key_len = mp->local_integ_key_len;
473   tun.remote_integ_key_len = mp->remote_integ_key_len;
474   tun.udp_encap = mp->udp_encap;
475   tun.tx_table_id = ntohl (mp->tx_table_id);
476   memcpy (&tun.local_ip, mp->local_ip, 4);
477   memcpy (&tun.remote_ip, mp->remote_ip, 4);
478   memcpy (&tun.local_crypto_key, &mp->local_crypto_key,
479           mp->local_crypto_key_len);
480   memcpy (&tun.remote_crypto_key, &mp->remote_crypto_key,
481           mp->remote_crypto_key_len);
482   memcpy (&tun.local_integ_key, &mp->local_integ_key,
483           mp->local_integ_key_len);
484   memcpy (&tun.remote_integ_key, &mp->remote_integ_key,
485           mp->remote_integ_key_len);
486   tun.renumber = mp->renumber;
487   tun.show_instance = ntohl (mp->show_instance);
488
489   rv = ipsec_add_del_tunnel_if_internal (vnm, &tun, &sw_if_index);
490
491 #else
492   rv = VNET_API_ERROR_UNIMPLEMENTED;
493 #endif
494
495   REPLY_MACRO2 (VL_API_IPSEC_TUNNEL_IF_ADD_DEL_REPLY, (
496                                                         {
497                                                         rmp->sw_if_index =
498                                                         htonl (sw_if_index);
499                                                         }));
500 }
501
502 static void
503 send_ipsec_sa_details (ipsec_sa_t * sa, vl_api_registration_t * reg,
504                        u32 context, u32 sw_if_index)
505 {
506   vl_api_ipsec_sa_details_t *mp;
507
508   mp = vl_msg_api_alloc (sizeof (*mp));
509   clib_memset (mp, 0, sizeof (*mp));
510   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_DETAILS);
511   mp->context = context;
512
513   mp->sa_id = htonl (sa->id);
514   mp->sw_if_index = htonl (sw_if_index);
515
516   mp->spi = htonl (sa->spi);
517   mp->protocol = sa->protocol;
518
519   mp->crypto_alg = sa->crypto_alg;
520   mp->crypto_key_len = sa->crypto_key_len;
521   memcpy (mp->crypto_key, sa->crypto_key, sa->crypto_key_len);
522
523   mp->integ_alg = sa->integ_alg;
524   mp->integ_key_len = sa->integ_key_len;
525   memcpy (mp->integ_key, sa->integ_key, sa->integ_key_len);
526
527   mp->use_esn = sa->use_esn;
528   mp->use_anti_replay = sa->use_anti_replay;
529
530   mp->is_tunnel = sa->is_tunnel;
531   mp->is_tunnel_ip6 = sa->is_tunnel_ip6;
532
533   if (sa->is_tunnel)
534     {
535       if (sa->is_tunnel_ip6)
536         {
537           memcpy (mp->tunnel_src_addr, &sa->tunnel_src_addr.ip6, 16);
538           memcpy (mp->tunnel_dst_addr, &sa->tunnel_dst_addr.ip6, 16);
539         }
540       else
541         {
542           memcpy (mp->tunnel_src_addr, &sa->tunnel_src_addr.ip4, 4);
543           memcpy (mp->tunnel_dst_addr, &sa->tunnel_dst_addr.ip4, 4);
544         }
545     }
546
547   mp->salt = clib_host_to_net_u32 (sa->salt);
548   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
549   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
550   if (sa->use_esn)
551     {
552       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
553       mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
554     }
555   if (sa->use_anti_replay)
556     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
557   mp->total_data_size = clib_host_to_net_u64 (sa->total_data_size);
558   mp->udp_encap = sa->udp_encap;
559
560   mp->tx_table_id =
561     htonl (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
562
563   vl_api_send_msg (reg, (u8 *) mp);
564 }
565
566
567 static void
568 vl_api_ipsec_sa_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
569 {
570   vl_api_registration_t *reg;
571   ipsec_main_t *im = &ipsec_main;
572   vnet_main_t *vnm = im->vnet_main;
573   ipsec_sa_t *sa;
574   ipsec_tunnel_if_t *t;
575   u32 *sa_index_to_tun_if_index = 0;
576
577 #if WITH_LIBSSL > 0
578   reg = vl_api_client_index_to_registration (mp->client_index);
579   if (!reg || pool_elts (im->sad) == 0)
580     return;
581
582   vec_validate_init_empty (sa_index_to_tun_if_index, vec_len (im->sad) - 1,
583                            ~0);
584
585   /* *INDENT-OFF* */
586   pool_foreach (t, im->tunnel_interfaces,
587   ({
588     vnet_hw_interface_t *hi;
589     u32 sw_if_index = ~0;
590
591     hi = vnet_get_hw_interface (vnm, t->hw_if_index);
592     sw_if_index = hi->sw_if_index;
593     sa_index_to_tun_if_index[t->input_sa_index] = sw_if_index;
594     sa_index_to_tun_if_index[t->output_sa_index] = sw_if_index;
595   }));
596
597   pool_foreach (sa, im->sad,
598   ({
599     if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == sa->id)
600       send_ipsec_sa_details (sa, reg, mp->context,
601                              sa_index_to_tun_if_index[sa - im->sad]);
602   }));
603   /* *INDENT-ON* */
604
605   vec_free (sa_index_to_tun_if_index);
606 #else
607   clib_warning ("unimplemented");
608 #endif
609 }
610
611
612 static void
613 vl_api_ipsec_tunnel_if_set_key_t_handler (vl_api_ipsec_tunnel_if_set_key_t *
614                                           mp)
615 {
616   vl_api_ipsec_tunnel_if_set_key_reply_t *rmp;
617   ipsec_main_t *im = &ipsec_main;
618   vnet_main_t *vnm = im->vnet_main;
619   vnet_sw_interface_t *sw;
620   u8 *key = 0;
621   int rv;
622
623 #if WITH_LIBSSL > 0
624   sw = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
625
626   switch (mp->key_type)
627     {
628     case IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO:
629     case IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO:
630       if (mp->alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
631           mp->alg >= IPSEC_CRYPTO_N_ALG)
632         {
633           rv = VNET_API_ERROR_UNIMPLEMENTED;
634           goto out;
635         }
636       break;
637     case IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG:
638     case IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG:
639       if (mp->alg >= IPSEC_INTEG_N_ALG)
640         {
641           rv = VNET_API_ERROR_UNIMPLEMENTED;
642           goto out;
643         }
644       break;
645     case IPSEC_IF_SET_KEY_TYPE_NONE:
646     default:
647       rv = VNET_API_ERROR_UNIMPLEMENTED;
648       goto out;
649       break;
650     }
651
652   key = vec_new (u8, mp->key_len);
653   clib_memcpy (key, mp->key, mp->key_len);
654
655   rv = ipsec_set_interface_key (vnm, sw->hw_if_index, mp->key_type, mp->alg,
656                                 key);
657   vec_free (key);
658 #else
659   clib_warning ("unimplemented");
660 #endif
661
662 out:
663   REPLY_MACRO (VL_API_IPSEC_TUNNEL_IF_SET_KEY_REPLY);
664 }
665
666
667 static void
668 vl_api_ipsec_tunnel_if_set_sa_t_handler (vl_api_ipsec_tunnel_if_set_sa_t * mp)
669 {
670   vl_api_ipsec_tunnel_if_set_sa_reply_t *rmp;
671   ipsec_main_t *im = &ipsec_main;
672   vnet_main_t *vnm = im->vnet_main;
673   vnet_sw_interface_t *sw;
674   int rv;
675
676 #if WITH_LIBSSL > 0
677   sw = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
678
679   rv = ipsec_set_interface_sa (vnm, sw->hw_if_index, ntohl (mp->sa_id),
680                                mp->is_outbound);
681 #else
682   clib_warning ("unimplemented");
683 #endif
684
685   REPLY_MACRO (VL_API_IPSEC_TUNNEL_IF_SET_SA_REPLY);
686 }
687
688
689 static void
690 vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
691 {
692   vl_api_ikev2_profile_add_del_reply_t *rmp;
693   int rv = 0;
694
695 #if WITH_LIBSSL > 0
696   vlib_main_t *vm = vlib_get_main ();
697   clib_error_t *error;
698   u8 *tmp = format (0, "%s", mp->name);
699   error = ikev2_add_del_profile (vm, tmp, mp->is_add);
700   vec_free (tmp);
701   if (error)
702     rv = VNET_API_ERROR_UNSPECIFIED;
703 #else
704   rv = VNET_API_ERROR_UNIMPLEMENTED;
705 #endif
706
707   REPLY_MACRO (VL_API_IKEV2_PROFILE_ADD_DEL_REPLY);
708 }
709
710 static void
711   vl_api_ikev2_profile_set_auth_t_handler
712   (vl_api_ikev2_profile_set_auth_t * mp)
713 {
714   vl_api_ikev2_profile_set_auth_reply_t *rmp;
715   int rv = 0;
716
717 #if WITH_LIBSSL > 0
718   vlib_main_t *vm = vlib_get_main ();
719   clib_error_t *error;
720   int data_len = ntohl (mp->data_len);
721   u8 *tmp = format (0, "%s", mp->name);
722   u8 *data = vec_new (u8, data_len);
723   clib_memcpy (data, mp->data, data_len);
724   error = ikev2_set_profile_auth (vm, tmp, mp->auth_method, data, mp->is_hex);
725   vec_free (tmp);
726   vec_free (data);
727   if (error)
728     rv = VNET_API_ERROR_UNSPECIFIED;
729 #else
730   rv = VNET_API_ERROR_UNIMPLEMENTED;
731 #endif
732
733   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
734 }
735
736 static void
737 vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
738 {
739   vl_api_ikev2_profile_add_del_reply_t *rmp;
740   int rv = 0;
741
742 #if WITH_LIBSSL > 0
743   vlib_main_t *vm = vlib_get_main ();
744   clib_error_t *error;
745   u8 *tmp = format (0, "%s", mp->name);
746   int data_len = ntohl (mp->data_len);
747   u8 *data = vec_new (u8, data_len);
748   clib_memcpy (data, mp->data, data_len);
749   error = ikev2_set_profile_id (vm, tmp, mp->id_type, data, mp->is_local);
750   vec_free (tmp);
751   vec_free (data);
752   if (error)
753     rv = VNET_API_ERROR_UNSPECIFIED;
754 #else
755   rv = VNET_API_ERROR_UNIMPLEMENTED;
756 #endif
757
758   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_ID_REPLY);
759 }
760
761 static void
762 vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
763 {
764   vl_api_ikev2_profile_set_ts_reply_t *rmp;
765   int rv = 0;
766
767 #if WITH_LIBSSL > 0
768   vlib_main_t *vm = vlib_get_main ();
769   clib_error_t *error;
770   u8 *tmp = format (0, "%s", mp->name);
771   error = ikev2_set_profile_ts (vm, tmp, mp->proto, mp->start_port,
772                                 mp->end_port, (ip4_address_t) mp->start_addr,
773                                 (ip4_address_t) mp->end_addr, mp->is_local);
774   vec_free (tmp);
775   if (error)
776     rv = VNET_API_ERROR_UNSPECIFIED;
777 #else
778   rv = VNET_API_ERROR_UNIMPLEMENTED;
779 #endif
780
781   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_TS_REPLY);
782 }
783
784 static void
785 vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
786 {
787   vl_api_ikev2_profile_set_ts_reply_t *rmp;
788   int rv = 0;
789
790 #if WITH_LIBSSL > 0
791   vlib_main_t *vm = vlib_get_main ();
792   clib_error_t *error;
793
794   error = ikev2_set_local_key (vm, mp->key_file);
795   if (error)
796     rv = VNET_API_ERROR_UNSPECIFIED;
797 #else
798   rv = VNET_API_ERROR_UNIMPLEMENTED;
799 #endif
800
801   REPLY_MACRO (VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
802 }
803
804 static void
805 vl_api_ikev2_set_responder_t_handler (vl_api_ikev2_set_responder_t * mp)
806 {
807   vl_api_ikev2_set_responder_reply_t *rmp;
808   int rv = 0;
809
810 #if WITH_LIBSSL > 0
811   vlib_main_t *vm = vlib_get_main ();
812   clib_error_t *error;
813
814   u8 *tmp = format (0, "%s", mp->name);
815   ip4_address_t ip4;
816   clib_memcpy (&ip4, mp->address, sizeof (ip4));
817
818   error = ikev2_set_profile_responder (vm, tmp, mp->sw_if_index, ip4);
819   vec_free (tmp);
820   if (error)
821     rv = VNET_API_ERROR_UNSPECIFIED;
822 #else
823   rv = VNET_API_ERROR_UNIMPLEMENTED;
824 #endif
825
826   REPLY_MACRO (VL_API_IKEV2_SET_RESPONDER_REPLY);
827 }
828
829 static void
830 vl_api_ikev2_set_ike_transforms_t_handler (vl_api_ikev2_set_ike_transforms_t *
831                                            mp)
832 {
833   vl_api_ikev2_set_ike_transforms_reply_t *rmp;
834   int rv = 0;
835
836 #if WITH_LIBSSL > 0
837   vlib_main_t *vm = vlib_get_main ();
838   clib_error_t *error;
839
840   u8 *tmp = format (0, "%s", mp->name);
841
842   error =
843     ikev2_set_profile_ike_transforms (vm, tmp, mp->crypto_alg, mp->integ_alg,
844                                       mp->dh_group, mp->crypto_key_size);
845   vec_free (tmp);
846   if (error)
847     rv = VNET_API_ERROR_UNSPECIFIED;
848 #else
849   rv = VNET_API_ERROR_UNIMPLEMENTED;
850 #endif
851
852   REPLY_MACRO (VL_API_IKEV2_SET_IKE_TRANSFORMS_REPLY);
853 }
854
855 static void
856 vl_api_ikev2_set_esp_transforms_t_handler (vl_api_ikev2_set_esp_transforms_t *
857                                            mp)
858 {
859   vl_api_ikev2_set_esp_transforms_reply_t *rmp;
860   int rv = 0;
861
862 #if WITH_LIBSSL > 0
863   vlib_main_t *vm = vlib_get_main ();
864   clib_error_t *error;
865
866   u8 *tmp = format (0, "%s", mp->name);
867
868   error =
869     ikev2_set_profile_esp_transforms (vm, tmp, mp->crypto_alg, mp->integ_alg,
870                                       mp->dh_group, mp->crypto_key_size);
871   vec_free (tmp);
872   if (error)
873     rv = VNET_API_ERROR_UNSPECIFIED;
874 #else
875   rv = VNET_API_ERROR_UNIMPLEMENTED;
876 #endif
877
878   REPLY_MACRO (VL_API_IKEV2_SET_ESP_TRANSFORMS_REPLY);
879 }
880
881 static void
882 vl_api_ikev2_set_sa_lifetime_t_handler (vl_api_ikev2_set_sa_lifetime_t * mp)
883 {
884   vl_api_ikev2_set_sa_lifetime_reply_t *rmp;
885   int rv = 0;
886
887 #if WITH_LIBSSL > 0
888   vlib_main_t *vm = vlib_get_main ();
889   clib_error_t *error;
890
891   u8 *tmp = format (0, "%s", mp->name);
892
893   error =
894     ikev2_set_profile_sa_lifetime (vm, tmp, mp->lifetime, mp->lifetime_jitter,
895                                    mp->handover, mp->lifetime_maxdata);
896   vec_free (tmp);
897   if (error)
898     rv = VNET_API_ERROR_UNSPECIFIED;
899 #else
900   rv = VNET_API_ERROR_UNIMPLEMENTED;
901 #endif
902
903   REPLY_MACRO (VL_API_IKEV2_SET_SA_LIFETIME_REPLY);
904 }
905
906 static void
907 vl_api_ikev2_initiate_sa_init_t_handler (vl_api_ikev2_initiate_sa_init_t * mp)
908 {
909   vl_api_ikev2_initiate_sa_init_reply_t *rmp;
910   int rv = 0;
911
912 #if WITH_LIBSSL > 0
913   vlib_main_t *vm = vlib_get_main ();
914   clib_error_t *error;
915
916   u8 *tmp = format (0, "%s", mp->name);
917
918   error = ikev2_initiate_sa_init (vm, tmp);
919   vec_free (tmp);
920   if (error)
921     rv = VNET_API_ERROR_UNSPECIFIED;
922 #else
923   rv = VNET_API_ERROR_UNIMPLEMENTED;
924 #endif
925
926   REPLY_MACRO (VL_API_IKEV2_INITIATE_SA_INIT_REPLY);
927 }
928
929 static void
930 vl_api_ikev2_initiate_del_ike_sa_t_handler (vl_api_ikev2_initiate_del_ike_sa_t
931                                             * mp)
932 {
933   vl_api_ikev2_initiate_del_ike_sa_reply_t *rmp;
934   int rv = 0;
935
936 #if WITH_LIBSSL > 0
937   vlib_main_t *vm = vlib_get_main ();
938   clib_error_t *error;
939
940   error = ikev2_initiate_delete_ike_sa (vm, mp->ispi);
941   if (error)
942     rv = VNET_API_ERROR_UNSPECIFIED;
943 #else
944   rv = VNET_API_ERROR_UNIMPLEMENTED;
945 #endif
946
947   REPLY_MACRO (VL_API_IKEV2_INITIATE_DEL_IKE_SA_REPLY);
948 }
949
950 static void
951   vl_api_ikev2_initiate_del_child_sa_t_handler
952   (vl_api_ikev2_initiate_del_child_sa_t * mp)
953 {
954   vl_api_ikev2_initiate_del_child_sa_reply_t *rmp;
955   int rv = 0;
956
957 #if WITH_LIBSSL > 0
958   vlib_main_t *vm = vlib_get_main ();
959   clib_error_t *error;
960
961   error = ikev2_initiate_delete_child_sa (vm, mp->ispi);
962   if (error)
963     rv = VNET_API_ERROR_UNSPECIFIED;
964 #else
965   rv = VNET_API_ERROR_UNIMPLEMENTED;
966 #endif
967
968   REPLY_MACRO (VL_API_IKEV2_INITIATE_DEL_CHILD_SA_REPLY);
969 }
970
971 static void
972   vl_api_ikev2_initiate_rekey_child_sa_t_handler
973   (vl_api_ikev2_initiate_rekey_child_sa_t * mp)
974 {
975   vl_api_ikev2_initiate_rekey_child_sa_reply_t *rmp;
976   int rv = 0;
977
978 #if WITH_LIBSSL > 0
979   vlib_main_t *vm = vlib_get_main ();
980   clib_error_t *error;
981
982   error = ikev2_initiate_rekey_child_sa (vm, mp->ispi);
983   if (error)
984     rv = VNET_API_ERROR_UNSPECIFIED;
985 #else
986   rv = VNET_API_ERROR_UNIMPLEMENTED;
987 #endif
988
989   REPLY_MACRO (VL_API_IKEV2_INITIATE_REKEY_CHILD_SA_REPLY);
990 }
991
992 /*
993  * ipsec_api_hookup
994  * Add vpe's API message handlers to the table.
995  * vlib has already mapped shared memory and
996  * added the client registration handlers.
997  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
998  */
999 #define vl_msg_name_crc_list
1000 #include <vnet/vnet_all_api_h.h>
1001 #undef vl_msg_name_crc_list
1002
1003 static void
1004 setup_message_id_table (api_main_t * am)
1005 {
1006 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
1007   foreach_vl_msg_name_crc_ipsec;
1008 #undef _
1009 }
1010
1011 static void
1012 vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp)
1013 {
1014   vl_api_registration_t *rp;
1015   ipsec_main_t *im = &ipsec_main;
1016   u32 context = mp->context;
1017
1018   rp = vl_api_client_index_to_registration (mp->client_index);
1019
1020   if (rp == 0)
1021     {
1022       clib_warning ("Client %d AWOL", mp->client_index);
1023       return;
1024     }
1025
1026   ipsec_ah_backend_t *ab;
1027   ipsec_esp_backend_t *eb;
1028   /* *INDENT-OFF* */
1029   pool_foreach (ab, im->ah_backends, {
1030     vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1031     clib_memset (mp, 0, sizeof (*mp));
1032     mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
1033     mp->context = context;
1034     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (ab->name),
1035               ab->name);
1036     mp->protocol = IPSEC_PROTOCOL_AH;
1037     mp->index = ab - im->ah_backends;
1038     mp->active = mp->index == im->ah_current_backend ? 1 : 0;
1039     vl_api_send_msg (rp, (u8 *)mp);
1040   });
1041   pool_foreach (eb, im->esp_backends, {
1042     vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1043     clib_memset (mp, 0, sizeof (*mp));
1044     mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
1045     mp->context = context;
1046     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (eb->name),
1047               eb->name);
1048     mp->protocol = IPSEC_PROTOCOL_ESP;
1049     mp->index = eb - im->esp_backends;
1050     mp->active = mp->index == im->esp_current_backend ? 1 : 0;
1051     vl_api_send_msg (rp, (u8 *)mp);
1052   });
1053   /* *INDENT-ON* */
1054 }
1055
1056 static void
1057 vl_api_ipsec_select_backend_t_handler (vl_api_ipsec_select_backend_t * mp)
1058 {
1059   ipsec_main_t *im = &ipsec_main;
1060   vl_api_ipsec_select_backend_reply_t *rmp;
1061   int rv = 0;
1062   if (pool_elts (im->sad) > 0)
1063     {
1064       rv = VNET_API_ERROR_INSTANCE_IN_USE;
1065       goto done;
1066     }
1067 #if WITH_LIBSSL > 0
1068   switch (mp->protocol)
1069     {
1070     case IPSEC_PROTOCOL_ESP:
1071       if (pool_is_free_index (im->esp_backends, mp->index))
1072         {
1073           rv = VNET_API_ERROR_INVALID_VALUE;
1074           break;
1075         }
1076       ipsec_select_esp_backend (im, mp->index);
1077       break;
1078     case IPSEC_PROTOCOL_AH:
1079       if (pool_is_free_index (im->ah_backends, mp->index))
1080         {
1081           rv = VNET_API_ERROR_INVALID_VALUE;
1082           break;
1083         }
1084       ipsec_select_ah_backend (im, mp->index);
1085       break;
1086     default:
1087       rv = VNET_API_ERROR_INVALID_VALUE;
1088       break;
1089     }
1090 #else
1091   clib_warning ("unimplemented");       /* FIXME */
1092 #endif
1093 done:
1094   REPLY_MACRO (VL_API_IPSEC_SELECT_BACKEND_REPLY);
1095 }
1096
1097 static clib_error_t *
1098 ipsec_api_hookup (vlib_main_t * vm)
1099 {
1100   api_main_t *am = &api_main;
1101
1102 #define _(N,n)                                                  \
1103     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
1104                            vl_api_##n##_t_handler,              \
1105                            vl_noop_handler,                     \
1106                            vl_api_##n##_t_endian,               \
1107                            vl_api_##n##_t_print,                \
1108                            sizeof(vl_api_##n##_t), 1);
1109   foreach_vpe_api_msg;
1110 #undef _
1111
1112   /*
1113    * Set up the (msg_name, crc, message-id) table
1114    */
1115   setup_message_id_table (am);
1116
1117   return 0;
1118 }
1119
1120 VLIB_API_INIT_FUNCTION (ipsec_api_hookup);
1121
1122 /*
1123  * fd.io coding-style-patch-verification: ON
1124  *
1125  * Local Variables:
1126  * eval: (c-set-style "gnu")
1127  * End:
1128  */