Add IPSec interface FIB index for TX packet
[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   u8 *tmp = format (0, "%s", mp->name);
721   u8 *data = vec_new (u8, mp->data_len);
722   clib_memcpy (data, mp->data, mp->data_len);
723   error = ikev2_set_profile_auth (vm, tmp, mp->auth_method, data, mp->is_hex);
724   vec_free (tmp);
725   vec_free (data);
726   if (error)
727     rv = VNET_API_ERROR_UNSPECIFIED;
728 #else
729   rv = VNET_API_ERROR_UNIMPLEMENTED;
730 #endif
731
732   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
733 }
734
735 static void
736 vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
737 {
738   vl_api_ikev2_profile_add_del_reply_t *rmp;
739   int rv = 0;
740
741 #if WITH_LIBSSL > 0
742   vlib_main_t *vm = vlib_get_main ();
743   clib_error_t *error;
744   u8 *tmp = format (0, "%s", mp->name);
745   u8 *data = vec_new (u8, mp->data_len);
746   clib_memcpy (data, mp->data, mp->data_len);
747   error = ikev2_set_profile_id (vm, tmp, mp->id_type, data, mp->is_local);
748   vec_free (tmp);
749   vec_free (data);
750   if (error)
751     rv = VNET_API_ERROR_UNSPECIFIED;
752 #else
753   rv = VNET_API_ERROR_UNIMPLEMENTED;
754 #endif
755
756   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_ID_REPLY);
757 }
758
759 static void
760 vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
761 {
762   vl_api_ikev2_profile_set_ts_reply_t *rmp;
763   int rv = 0;
764
765 #if WITH_LIBSSL > 0
766   vlib_main_t *vm = vlib_get_main ();
767   clib_error_t *error;
768   u8 *tmp = format (0, "%s", mp->name);
769   error = ikev2_set_profile_ts (vm, tmp, mp->proto, mp->start_port,
770                                 mp->end_port, (ip4_address_t) mp->start_addr,
771                                 (ip4_address_t) mp->end_addr, mp->is_local);
772   vec_free (tmp);
773   if (error)
774     rv = VNET_API_ERROR_UNSPECIFIED;
775 #else
776   rv = VNET_API_ERROR_UNIMPLEMENTED;
777 #endif
778
779   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_TS_REPLY);
780 }
781
782 static void
783 vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
784 {
785   vl_api_ikev2_profile_set_ts_reply_t *rmp;
786   int rv = 0;
787
788 #if WITH_LIBSSL > 0
789   vlib_main_t *vm = vlib_get_main ();
790   clib_error_t *error;
791
792   error = ikev2_set_local_key (vm, mp->key_file);
793   if (error)
794     rv = VNET_API_ERROR_UNSPECIFIED;
795 #else
796   rv = VNET_API_ERROR_UNIMPLEMENTED;
797 #endif
798
799   REPLY_MACRO (VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
800 }
801
802 static void
803 vl_api_ikev2_set_responder_t_handler (vl_api_ikev2_set_responder_t * mp)
804 {
805   vl_api_ikev2_set_responder_reply_t *rmp;
806   int rv = 0;
807
808 #if WITH_LIBSSL > 0
809   vlib_main_t *vm = vlib_get_main ();
810   clib_error_t *error;
811
812   u8 *tmp = format (0, "%s", mp->name);
813   ip4_address_t ip4;
814   clib_memcpy (&ip4, mp->address, sizeof (ip4));
815
816   error = ikev2_set_profile_responder (vm, tmp, mp->sw_if_index, ip4);
817   vec_free (tmp);
818   if (error)
819     rv = VNET_API_ERROR_UNSPECIFIED;
820 #else
821   rv = VNET_API_ERROR_UNIMPLEMENTED;
822 #endif
823
824   REPLY_MACRO (VL_API_IKEV2_SET_RESPONDER_REPLY);
825 }
826
827 static void
828 vl_api_ikev2_set_ike_transforms_t_handler (vl_api_ikev2_set_ike_transforms_t *
829                                            mp)
830 {
831   vl_api_ikev2_set_ike_transforms_reply_t *rmp;
832   int rv = 0;
833
834 #if WITH_LIBSSL > 0
835   vlib_main_t *vm = vlib_get_main ();
836   clib_error_t *error;
837
838   u8 *tmp = format (0, "%s", mp->name);
839
840   error =
841     ikev2_set_profile_ike_transforms (vm, tmp, mp->crypto_alg, mp->integ_alg,
842                                       mp->dh_group, mp->crypto_key_size);
843   vec_free (tmp);
844   if (error)
845     rv = VNET_API_ERROR_UNSPECIFIED;
846 #else
847   rv = VNET_API_ERROR_UNIMPLEMENTED;
848 #endif
849
850   REPLY_MACRO (VL_API_IKEV2_SET_IKE_TRANSFORMS_REPLY);
851 }
852
853 static void
854 vl_api_ikev2_set_esp_transforms_t_handler (vl_api_ikev2_set_esp_transforms_t *
855                                            mp)
856 {
857   vl_api_ikev2_set_esp_transforms_reply_t *rmp;
858   int rv = 0;
859
860 #if WITH_LIBSSL > 0
861   vlib_main_t *vm = vlib_get_main ();
862   clib_error_t *error;
863
864   u8 *tmp = format (0, "%s", mp->name);
865
866   error =
867     ikev2_set_profile_esp_transforms (vm, tmp, mp->crypto_alg, mp->integ_alg,
868                                       mp->dh_group, mp->crypto_key_size);
869   vec_free (tmp);
870   if (error)
871     rv = VNET_API_ERROR_UNSPECIFIED;
872 #else
873   rv = VNET_API_ERROR_UNIMPLEMENTED;
874 #endif
875
876   REPLY_MACRO (VL_API_IKEV2_SET_ESP_TRANSFORMS_REPLY);
877 }
878
879 static void
880 vl_api_ikev2_set_sa_lifetime_t_handler (vl_api_ikev2_set_sa_lifetime_t * mp)
881 {
882   vl_api_ikev2_set_sa_lifetime_reply_t *rmp;
883   int rv = 0;
884
885 #if WITH_LIBSSL > 0
886   vlib_main_t *vm = vlib_get_main ();
887   clib_error_t *error;
888
889   u8 *tmp = format (0, "%s", mp->name);
890
891   error =
892     ikev2_set_profile_sa_lifetime (vm, tmp, mp->lifetime, mp->lifetime_jitter,
893                                    mp->handover, mp->lifetime_maxdata);
894   vec_free (tmp);
895   if (error)
896     rv = VNET_API_ERROR_UNSPECIFIED;
897 #else
898   rv = VNET_API_ERROR_UNIMPLEMENTED;
899 #endif
900
901   REPLY_MACRO (VL_API_IKEV2_SET_SA_LIFETIME_REPLY);
902 }
903
904 static void
905 vl_api_ikev2_initiate_sa_init_t_handler (vl_api_ikev2_initiate_sa_init_t * mp)
906 {
907   vl_api_ikev2_initiate_sa_init_reply_t *rmp;
908   int rv = 0;
909
910 #if WITH_LIBSSL > 0
911   vlib_main_t *vm = vlib_get_main ();
912   clib_error_t *error;
913
914   u8 *tmp = format (0, "%s", mp->name);
915
916   error = ikev2_initiate_sa_init (vm, tmp);
917   vec_free (tmp);
918   if (error)
919     rv = VNET_API_ERROR_UNSPECIFIED;
920 #else
921   rv = VNET_API_ERROR_UNIMPLEMENTED;
922 #endif
923
924   REPLY_MACRO (VL_API_IKEV2_INITIATE_SA_INIT_REPLY);
925 }
926
927 static void
928 vl_api_ikev2_initiate_del_ike_sa_t_handler (vl_api_ikev2_initiate_del_ike_sa_t
929                                             * mp)
930 {
931   vl_api_ikev2_initiate_del_ike_sa_reply_t *rmp;
932   int rv = 0;
933
934 #if WITH_LIBSSL > 0
935   vlib_main_t *vm = vlib_get_main ();
936   clib_error_t *error;
937
938   error = ikev2_initiate_delete_ike_sa (vm, mp->ispi);
939   if (error)
940     rv = VNET_API_ERROR_UNSPECIFIED;
941 #else
942   rv = VNET_API_ERROR_UNIMPLEMENTED;
943 #endif
944
945   REPLY_MACRO (VL_API_IKEV2_INITIATE_DEL_IKE_SA_REPLY);
946 }
947
948 static void
949   vl_api_ikev2_initiate_del_child_sa_t_handler
950   (vl_api_ikev2_initiate_del_child_sa_t * mp)
951 {
952   vl_api_ikev2_initiate_del_child_sa_reply_t *rmp;
953   int rv = 0;
954
955 #if WITH_LIBSSL > 0
956   vlib_main_t *vm = vlib_get_main ();
957   clib_error_t *error;
958
959   error = ikev2_initiate_delete_child_sa (vm, mp->ispi);
960   if (error)
961     rv = VNET_API_ERROR_UNSPECIFIED;
962 #else
963   rv = VNET_API_ERROR_UNIMPLEMENTED;
964 #endif
965
966   REPLY_MACRO (VL_API_IKEV2_INITIATE_DEL_CHILD_SA_REPLY);
967 }
968
969 static void
970   vl_api_ikev2_initiate_rekey_child_sa_t_handler
971   (vl_api_ikev2_initiate_rekey_child_sa_t * mp)
972 {
973   vl_api_ikev2_initiate_rekey_child_sa_reply_t *rmp;
974   int rv = 0;
975
976 #if WITH_LIBSSL > 0
977   vlib_main_t *vm = vlib_get_main ();
978   clib_error_t *error;
979
980   error = ikev2_initiate_rekey_child_sa (vm, mp->ispi);
981   if (error)
982     rv = VNET_API_ERROR_UNSPECIFIED;
983 #else
984   rv = VNET_API_ERROR_UNIMPLEMENTED;
985 #endif
986
987   REPLY_MACRO (VL_API_IKEV2_INITIATE_REKEY_CHILD_SA_REPLY);
988 }
989
990 /*
991  * ipsec_api_hookup
992  * Add vpe's API message handlers to the table.
993  * vlib has already mapped shared memory and
994  * added the client registration handlers.
995  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
996  */
997 #define vl_msg_name_crc_list
998 #include <vnet/vnet_all_api_h.h>
999 #undef vl_msg_name_crc_list
1000
1001 static void
1002 setup_message_id_table (api_main_t * am)
1003 {
1004 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
1005   foreach_vl_msg_name_crc_ipsec;
1006 #undef _
1007 }
1008
1009 static void
1010 vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp)
1011 {
1012   vl_api_registration_t *rp;
1013   ipsec_main_t *im = &ipsec_main;
1014   u32 context = mp->context;
1015
1016   rp = vl_api_client_index_to_registration (mp->client_index);
1017
1018   if (rp == 0)
1019     {
1020       clib_warning ("Client %d AWOL", mp->client_index);
1021       return;
1022     }
1023
1024   ipsec_ah_backend_t *ab;
1025   ipsec_esp_backend_t *eb;
1026   /* *INDENT-OFF* */
1027   pool_foreach (ab, im->ah_backends, {
1028     vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1029     clib_memset (mp, 0, sizeof (*mp));
1030     mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
1031     mp->context = context;
1032     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (ab->name),
1033               ab->name);
1034     mp->protocol = IPSEC_PROTOCOL_AH;
1035     mp->index = ab - im->ah_backends;
1036     mp->active = mp->index == im->ah_current_backend ? 1 : 0;
1037     vl_api_send_msg (rp, (u8 *)mp);
1038   });
1039   pool_foreach (eb, im->esp_backends, {
1040     vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1041     clib_memset (mp, 0, sizeof (*mp));
1042     mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
1043     mp->context = context;
1044     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (eb->name),
1045               eb->name);
1046     mp->protocol = IPSEC_PROTOCOL_ESP;
1047     mp->index = eb - im->esp_backends;
1048     mp->active = mp->index == im->esp_current_backend ? 1 : 0;
1049     vl_api_send_msg (rp, (u8 *)mp);
1050   });
1051   /* *INDENT-ON* */
1052 }
1053
1054 static void
1055 vl_api_ipsec_select_backend_t_handler (vl_api_ipsec_select_backend_t * mp)
1056 {
1057   ipsec_main_t *im = &ipsec_main;
1058   vl_api_ipsec_select_backend_reply_t *rmp;
1059   int rv = 0;
1060   if (pool_elts (im->sad) > 0)
1061     {
1062       rv = VNET_API_ERROR_INSTANCE_IN_USE;
1063       goto done;
1064     }
1065 #if WITH_LIBSSL > 0
1066   switch (mp->protocol)
1067     {
1068     case IPSEC_PROTOCOL_ESP:
1069       if (pool_is_free_index (im->esp_backends, mp->index))
1070         {
1071           rv = VNET_API_ERROR_INVALID_VALUE;
1072           break;
1073         }
1074       ipsec_select_esp_backend (im, mp->index);
1075       break;
1076     case IPSEC_PROTOCOL_AH:
1077       if (pool_is_free_index (im->ah_backends, mp->index))
1078         {
1079           rv = VNET_API_ERROR_INVALID_VALUE;
1080           break;
1081         }
1082       ipsec_select_ah_backend (im, mp->index);
1083       break;
1084     default:
1085       rv = VNET_API_ERROR_INVALID_VALUE;
1086       break;
1087     }
1088 #else
1089   clib_warning ("unimplemented");       /* FIXME */
1090 #endif
1091 done:
1092   REPLY_MACRO (VL_API_IPSEC_SELECT_BACKEND_REPLY);
1093 }
1094
1095 static clib_error_t *
1096 ipsec_api_hookup (vlib_main_t * vm)
1097 {
1098   api_main_t *am = &api_main;
1099
1100 #define _(N,n)                                                  \
1101     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
1102                            vl_api_##n##_t_handler,              \
1103                            vl_noop_handler,                     \
1104                            vl_api_##n##_t_endian,               \
1105                            vl_api_##n##_t_print,                \
1106                            sizeof(vl_api_##n##_t), 1);
1107   foreach_vpe_api_msg;
1108 #undef _
1109
1110   /*
1111    * Set up the (msg_name, crc, message-id) table
1112    */
1113   setup_message_id_table (am);
1114
1115   return 0;
1116 }
1117
1118 VLIB_API_INIT_FUNCTION (ipsec_api_hookup);
1119
1120 /*
1121  * fd.io coding-style-patch-verification: ON
1122  *
1123  * Local Variables:
1124  * eval: (c-set-style "gnu")
1125  * End:
1126  */