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