ipsec: Tunnel SA DSCP behaviour
[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/ipsec/ipsec_types_api.h>
28 #include <vnet/tunnel/tunnel_types_api.h>
29 #include <vnet/fib/fib.h>
30 #include <vnet/ipip/ipip.h>
31 #include <vnet/tunnel/tunnel_types_api.h>
32
33 #include <vnet/vnet_msg_enum.h>
34
35 #if WITH_LIBSSL > 0
36 #include <vnet/ipsec/ipsec.h>
37 #include <vnet/ipsec/ipsec_tun.h>
38 #include <vnet/ipsec/ipsec_itf.h>
39 #endif /* IPSEC */
40
41 #define vl_typedefs             /* define message structures */
42 #include <vnet/vnet_all_api_h.h>
43 #undef vl_typedefs
44
45 #define vl_endianfun            /* define message structures */
46 #include <vnet/vnet_all_api_h.h>
47 #undef vl_endianfun
48
49 /* instantiate all the print functions we know about */
50 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
51 #define vl_printfun
52 #include <vnet/vnet_all_api_h.h>
53 #undef vl_printfun
54
55 #include <vlibapi/api_helper_macros.h>
56
57 #define foreach_vpe_api_msg                                     \
58 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del)                         \
59 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd)     \
60 _(IPSEC_SPD_ENTRY_ADD_DEL, ipsec_spd_entry_add_del)             \
61 _(IPSEC_SAD_ENTRY_ADD_DEL, ipsec_sad_entry_add_del)             \
62 _(IPSEC_SAD_ENTRY_ADD_DEL_V2, ipsec_sad_entry_add_del_v2)       \
63 _(IPSEC_SA_DUMP, ipsec_sa_dump)                                 \
64 _(IPSEC_SA_V2_DUMP, ipsec_sa_v2_dump)                           \
65 _(IPSEC_SPDS_DUMP, ipsec_spds_dump)                             \
66 _(IPSEC_SPD_DUMP, ipsec_spd_dump)                               \
67 _(IPSEC_SPD_INTERFACE_DUMP, ipsec_spd_interface_dump)           \
68 _(IPSEC_ITF_CREATE, ipsec_itf_create)                           \
69 _(IPSEC_ITF_DELETE, ipsec_itf_delete)                           \
70 _(IPSEC_ITF_DUMP, ipsec_itf_dump)                               \
71 _(IPSEC_TUNNEL_IF_ADD_DEL, ipsec_tunnel_if_add_del)             \
72 _(IPSEC_TUNNEL_IF_SET_SA, ipsec_tunnel_if_set_sa)               \
73 _(IPSEC_SELECT_BACKEND, ipsec_select_backend)                   \
74 _(IPSEC_BACKEND_DUMP, ipsec_backend_dump)                       \
75 _(IPSEC_TUNNEL_PROTECT_UPDATE, ipsec_tunnel_protect_update)     \
76 _(IPSEC_TUNNEL_PROTECT_DEL, ipsec_tunnel_protect_del)           \
77 _(IPSEC_TUNNEL_PROTECT_DUMP, ipsec_tunnel_protect_dump)         \
78 _(IPSEC_SET_ASYNC_MODE, ipsec_set_async_mode)
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_tunnel_protect_update_t_handler
123   (vl_api_ipsec_tunnel_protect_update_t * mp)
124 {
125   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
126   vl_api_ipsec_tunnel_protect_update_reply_t *rmp;
127   u32 sw_if_index, ii, *sa_ins = NULL;
128   ip_address_t nh;
129   int rv;
130
131   sw_if_index = ntohl (mp->tunnel.sw_if_index);
132
133   VALIDATE_SW_IF_INDEX (&(mp->tunnel));
134
135 #if WITH_LIBSSL > 0
136
137   for (ii = 0; ii < mp->tunnel.n_sa_in; ii++)
138     vec_add1 (sa_ins, ntohl (mp->tunnel.sa_in[ii]));
139
140   ip_address_decode2 (&mp->tunnel.nh, &nh);
141
142   rv = ipsec_tun_protect_update (sw_if_index, &nh,
143                                  ntohl (mp->tunnel.sa_out), sa_ins);
144 #else
145   rv = VNET_API_ERROR_UNIMPLEMENTED;
146 #endif
147
148   BAD_SW_IF_INDEX_LABEL;
149
150   REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_UPDATE_REPLY);
151 }
152
153 static void vl_api_ipsec_tunnel_protect_del_t_handler
154   (vl_api_ipsec_tunnel_protect_del_t * mp)
155 {
156   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
157   vl_api_ipsec_tunnel_protect_del_reply_t *rmp;
158   ip_address_t nh;
159   u32 sw_if_index;
160   int rv;
161
162   sw_if_index = ntohl (mp->sw_if_index);
163
164   VALIDATE_SW_IF_INDEX (mp);
165
166 #if WITH_LIBSSL > 0
167   ip_address_decode2 (&mp->nh, &nh);
168   rv = ipsec_tun_protect_del (sw_if_index, &nh);
169 #else
170   rv = VNET_API_ERROR_UNIMPLEMENTED;
171 #endif
172
173   BAD_SW_IF_INDEX_LABEL;
174
175   REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_DEL_REPLY);
176 }
177
178 typedef struct ipsec_dump_walk_ctx_t_
179 {
180   vl_api_registration_t *reg;
181   u32 context;
182 } ipsec_dump_walk_ctx_t;
183
184 static walk_rc_t
185 send_ipsec_tunnel_protect_details (index_t itpi, void *arg)
186 {
187   ipsec_dump_walk_ctx_t *ctx = arg;
188   vl_api_ipsec_tunnel_protect_details_t *mp;
189   ipsec_tun_protect_t *itp;
190   u32 ii = 0;
191   ipsec_sa_t *sa;
192
193   itp = ipsec_tun_protect_get (itpi);
194
195   mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (u32) * itp->itp_n_sa_in));
196   clib_memset (mp, 0, sizeof (*mp));
197   mp->_vl_msg_id = ntohs (VL_API_IPSEC_TUNNEL_PROTECT_DETAILS);
198   mp->context = ctx->context;
199
200   mp->tun.sw_if_index = htonl (itp->itp_sw_if_index);
201   ip_address_encode2 (itp->itp_key, &mp->tun.nh);
202
203   sa = ipsec_sa_get (itp->itp_out_sa);
204   mp->tun.sa_out = htonl (sa->id);
205   mp->tun.n_sa_in = itp->itp_n_sa_in;
206   /* *INDENT-OFF* */
207   FOR_EACH_IPSEC_PROTECT_INPUT_SA(itp, sa,
208   ({
209     mp->tun.sa_in[ii++] = htonl (sa->id);
210   }));
211   /* *INDENT-ON* */
212
213   vl_api_send_msg (ctx->reg, (u8 *) mp);
214
215   return (WALK_CONTINUE);
216 }
217
218 static void
219 vl_api_ipsec_tunnel_protect_dump_t_handler (vl_api_ipsec_tunnel_protect_dump_t
220                                             * mp)
221 {
222   vl_api_registration_t *reg;
223   u32 sw_if_index;
224
225 #if WITH_LIBSSL > 0
226   reg = vl_api_client_index_to_registration (mp->client_index);
227   if (!reg)
228     return;
229
230   ipsec_dump_walk_ctx_t ctx = {
231     .reg = reg,
232     .context = mp->context,
233   };
234
235   sw_if_index = ntohl (mp->sw_if_index);
236
237   if (~0 == sw_if_index)
238     {
239       ipsec_tun_protect_walk (send_ipsec_tunnel_protect_details, &ctx);
240     }
241   else
242     {
243       ipsec_tun_protect_walk_itf (sw_if_index,
244                                   send_ipsec_tunnel_protect_details, &ctx);
245     }
246 #else
247   clib_warning ("unimplemented");
248 #endif
249 }
250
251 static int
252 ipsec_spd_action_decode (vl_api_ipsec_spd_action_t in,
253                          ipsec_policy_action_t * out)
254 {
255   in = clib_net_to_host_u32 (in);
256
257   switch (in)
258     {
259 #define _(v,f,s) case IPSEC_API_SPD_ACTION_##f: \
260       *out = IPSEC_POLICY_ACTION_##f;              \
261       return (0);
262       foreach_ipsec_policy_action
263 #undef _
264     }
265   return (VNET_API_ERROR_UNIMPLEMENTED);
266 }
267
268 static void vl_api_ipsec_spd_entry_add_del_t_handler
269   (vl_api_ipsec_spd_entry_add_del_t * mp)
270 {
271   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
272   vl_api_ipsec_spd_entry_add_del_reply_t *rmp;
273   ip46_type_t itype;
274   u32 stat_index;
275   int rv;
276
277   stat_index = ~0;
278
279 #if WITH_LIBSSL > 0
280   ipsec_policy_t p;
281
282   clib_memset (&p, 0, sizeof (p));
283
284   p.id = ntohl (mp->entry.spd_id);
285   p.priority = ntohl (mp->entry.priority);
286
287   itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start);
288   ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop);
289   ip_address_decode (&mp->entry.local_address_start, &p.laddr.start);
290   ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop);
291
292   p.is_ipv6 = (itype == IP46_TYPE_IP6);
293
294   p.protocol = mp->entry.protocol;
295   p.rport.start = ntohs (mp->entry.remote_port_start);
296   p.rport.stop = ntohs (mp->entry.remote_port_stop);
297   p.lport.start = ntohs (mp->entry.local_port_start);
298   p.lport.stop = ntohs (mp->entry.local_port_stop);
299
300   rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
301
302   if (rv)
303     goto out;
304
305   /* policy action resolve unsupported */
306   if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
307     {
308       clib_warning ("unsupported action: 'resolve'");
309       rv = VNET_API_ERROR_UNIMPLEMENTED;
310       goto out;
311     }
312   p.sa_id = ntohl (mp->entry.sa_id);
313   rv =
314     ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy,
315                           &p.type);
316   if (rv)
317     goto out;
318
319   rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index);
320   if (rv)
321     goto out;
322
323 #else
324   rv = VNET_API_ERROR_UNIMPLEMENTED;
325   goto out;
326 #endif
327
328 out:
329   /* *INDENT-OFF* */
330   REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY,
331   ({
332     rmp->stat_index = ntohl(stat_index);
333   }));
334   /* *INDENT-ON* */
335 }
336
337 static void vl_api_ipsec_sad_entry_add_del_t_handler
338   (vl_api_ipsec_sad_entry_add_del_t * mp)
339 {
340   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
341   vl_api_ipsec_sad_entry_add_del_reply_t *rmp;
342   ip46_address_t tun_src = { }, tun_dst =
343   {
344   };
345   ipsec_key_t crypto_key, integ_key;
346   ipsec_crypto_alg_t crypto_alg;
347   ipsec_integ_alg_t integ_alg;
348   ipsec_protocol_t proto;
349   ipsec_sa_flags_t flags;
350   u32 id, spi, sa_index = ~0;
351   int rv;
352
353 #if WITH_LIBSSL > 0
354
355   id = ntohl (mp->entry.sad_id);
356   spi = ntohl (mp->entry.spi);
357
358   rv = ipsec_proto_decode (mp->entry.protocol, &proto);
359
360   if (rv)
361     goto out;
362
363   rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
364
365   if (rv)
366     goto out;
367
368   rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
369
370   if (rv)
371     goto out;
372
373   ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
374   ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
375
376   flags = ipsec_sa_flags_decode (mp->entry.flags);
377
378   ip_address_decode (&mp->entry.tunnel_src, &tun_src);
379   ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
380
381   if (mp->is_add)
382     rv = ipsec_sa_add_and_lock (id, spi, proto,
383                                 crypto_alg, &crypto_key,
384                                 integ_alg, &integ_key, flags,
385                                 0, mp->entry.salt, &tun_src, &tun_dst,
386                                 TUNNEL_ENCAP_DECAP_FLAG_NONE,
387                                 IP_DSCP_CS0,
388                                 &sa_index,
389                                 htons (mp->entry.udp_src_port),
390                                 htons (mp->entry.udp_dst_port));
391   else
392     rv = ipsec_sa_unlock_id (id);
393
394 #else
395   rv = VNET_API_ERROR_UNIMPLEMENTED;
396 #endif
397
398 out:
399   /* *INDENT-OFF* */
400   REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_REPLY,
401   {
402     rmp->stat_index = htonl (sa_index);
403   });
404   /* *INDENT-ON* */
405 }
406
407 static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
408   (vl_api_ipsec_sad_entry_add_del_v2_t * mp)
409 {
410   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
411   vl_api_ipsec_sad_entry_add_del_v2_reply_t *rmp;
412   ip46_address_t tun_src = { }, tun_dst =
413   {
414   };
415   tunnel_encap_decap_flags_t tunnel_flags;
416   ipsec_key_t crypto_key, integ_key;
417   ipsec_crypto_alg_t crypto_alg;
418   ipsec_integ_alg_t integ_alg;
419   ipsec_protocol_t proto;
420   ipsec_sa_flags_t flags;
421   u32 id, spi, sa_index = ~0;
422   int rv;
423
424 #if WITH_LIBSSL > 0
425
426   id = ntohl (mp->entry.sad_id);
427   spi = ntohl (mp->entry.spi);
428
429   rv = ipsec_proto_decode (mp->entry.protocol, &proto);
430
431   if (rv)
432     goto out;
433
434   rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
435
436   if (rv)
437     goto out;
438
439   rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
440
441   if (rv)
442     goto out;
443
444   rv =
445     tunnel_encap_decap_flags_decode (mp->entry.tunnel_flags, &tunnel_flags);
446
447   if (rv)
448     goto out;
449
450   ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
451   ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
452
453   flags = ipsec_sa_flags_decode (mp->entry.flags);
454
455   ip_address_decode (&mp->entry.tunnel_src, &tun_src);
456   ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
457
458   if (mp->is_add)
459     rv = ipsec_sa_add_and_lock (id, spi, proto,
460                                 crypto_alg, &crypto_key,
461                                 integ_alg, &integ_key, flags,
462                                 0, mp->entry.salt, &tun_src, &tun_dst,
463                                 tunnel_flags,
464                                 ip_dscp_decode (mp->entry.dscp),
465                                 &sa_index,
466                                 htons (mp->entry.udp_src_port),
467                                 htons (mp->entry.udp_dst_port));
468   else
469     rv = ipsec_sa_unlock_id (id);
470
471 #else
472   rv = VNET_API_ERROR_UNIMPLEMENTED;
473 #endif
474
475 out:
476   /* *INDENT-OFF* */
477   REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_V2_REPLY,
478   {
479     rmp->stat_index = htonl (sa_index);
480   });
481   /* *INDENT-ON* */
482 }
483
484 static void
485 send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg,
486                          u32 context)
487 {
488   vl_api_ipsec_spds_details_t *mp;
489   u32 n_policies = 0;
490
491   mp = vl_msg_api_alloc (sizeof (*mp));
492   clib_memset (mp, 0, sizeof (*mp));
493   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPDS_DETAILS);
494   mp->context = context;
495
496   mp->spd_id = htonl (spd->id);
497 #define _(s, n) n_policies += vec_len (spd->policies[IPSEC_SPD_POLICY_##s]);
498   foreach_ipsec_spd_policy_type
499 #undef _
500     mp->npolicies = htonl (n_policies);
501
502   vl_api_send_msg (reg, (u8 *) mp);
503 }
504
505 static void
506 vl_api_ipsec_spds_dump_t_handler (vl_api_ipsec_spds_dump_t * mp)
507 {
508   vl_api_registration_t *reg;
509   ipsec_main_t *im = &ipsec_main;
510   ipsec_spd_t *spd;
511 #if WITH_LIBSSL > 0
512   reg = vl_api_client_index_to_registration (mp->client_index);
513   if (!reg)
514     return;
515
516   /* *INDENT-OFF* */
517   pool_foreach (spd, im->spds, ({
518     send_ipsec_spds_details (spd, reg, mp->context);
519   }));
520   /* *INDENT-ON* */
521 #else
522   clib_warning ("unimplemented");
523 #endif
524 }
525
526 vl_api_ipsec_spd_action_t
527 ipsec_spd_action_encode (ipsec_policy_action_t in)
528 {
529   vl_api_ipsec_spd_action_t out = IPSEC_API_SPD_ACTION_BYPASS;
530
531   switch (in)
532     {
533 #define _(v,f,s) case IPSEC_POLICY_ACTION_##f: \
534       out = IPSEC_API_SPD_ACTION_##f;          \
535       break;
536       foreach_ipsec_policy_action
537 #undef _
538     }
539   return (clib_host_to_net_u32 (out));
540 }
541
542 static void
543 send_ipsec_spd_details (ipsec_policy_t * p, vl_api_registration_t * reg,
544                         u32 context)
545 {
546   vl_api_ipsec_spd_details_t *mp;
547
548   mp = vl_msg_api_alloc (sizeof (*mp));
549   clib_memset (mp, 0, sizeof (*mp));
550   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
551   mp->context = context;
552
553   mp->entry.spd_id = htonl (p->id);
554   mp->entry.priority = htonl (p->priority);
555   mp->entry.is_outbound = ((p->type == IPSEC_SPD_POLICY_IP6_OUTBOUND) ||
556                            (p->type == IPSEC_SPD_POLICY_IP4_OUTBOUND));
557
558   ip_address_encode (&p->laddr.start, IP46_TYPE_ANY,
559                      &mp->entry.local_address_start);
560   ip_address_encode (&p->laddr.stop, IP46_TYPE_ANY,
561                      &mp->entry.local_address_stop);
562   ip_address_encode (&p->raddr.start, IP46_TYPE_ANY,
563                      &mp->entry.remote_address_start);
564   ip_address_encode (&p->raddr.stop, IP46_TYPE_ANY,
565                      &mp->entry.remote_address_stop);
566   mp->entry.local_port_start = htons (p->lport.start);
567   mp->entry.local_port_stop = htons (p->lport.stop);
568   mp->entry.remote_port_start = htons (p->rport.start);
569   mp->entry.remote_port_stop = htons (p->rport.stop);
570   mp->entry.protocol = p->protocol;
571   mp->entry.policy = ipsec_spd_action_encode (p->policy);
572   mp->entry.sa_id = htonl (p->sa_id);
573
574   vl_api_send_msg (reg, (u8 *) mp);
575 }
576
577 static void
578 vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
579 {
580   vl_api_registration_t *reg;
581   ipsec_main_t *im = &ipsec_main;
582   ipsec_spd_policy_type_t ptype;
583   ipsec_policy_t *policy;
584   ipsec_spd_t *spd;
585   uword *p;
586   u32 spd_index, *ii;
587 #if WITH_LIBSSL > 0
588   reg = vl_api_client_index_to_registration (mp->client_index);
589   if (!reg)
590     return;
591
592   p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
593   if (!p)
594     return;
595
596   spd_index = p[0];
597   spd = pool_elt_at_index (im->spds, spd_index);
598
599   /* *INDENT-OFF* */
600   FOR_EACH_IPSEC_SPD_POLICY_TYPE(ptype) {
601     vec_foreach(ii, spd->policies[ptype])
602       {
603         policy = pool_elt_at_index(im->policies, *ii);
604
605         if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
606           send_ipsec_spd_details (policy, reg, mp->context);
607       }
608   }
609   /* *INDENT-ON* */
610 #else
611   clib_warning ("unimplemented");
612 #endif
613 }
614
615 static void
616 send_ipsec_spd_interface_details (vl_api_registration_t * reg, u32 spd_index,
617                                   u32 sw_if_index, u32 context)
618 {
619   vl_api_ipsec_spd_interface_details_t *mp;
620
621   mp = vl_msg_api_alloc (sizeof (*mp));
622   clib_memset (mp, 0, sizeof (*mp));
623   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_INTERFACE_DETAILS);
624   mp->context = context;
625
626   mp->spd_index = htonl (spd_index);
627   mp->sw_if_index = htonl (sw_if_index);
628
629   vl_api_send_msg (reg, (u8 *) mp);
630 }
631
632 static void
633 vl_api_ipsec_spd_interface_dump_t_handler (vl_api_ipsec_spd_interface_dump_t *
634                                            mp)
635 {
636   ipsec_main_t *im = &ipsec_main;
637   vl_api_registration_t *reg;
638   u32 k, v, spd_index;
639
640 #if WITH_LIBSSL > 0
641   reg = vl_api_client_index_to_registration (mp->client_index);
642   if (!reg)
643     return;
644
645   if (mp->spd_index_valid)
646     {
647       spd_index = ntohl (mp->spd_index);
648       /* *INDENT-OFF* */
649       hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
650         if (v == spd_index)
651           send_ipsec_spd_interface_details(reg, v, k, mp->context);
652       }));
653       /* *INDENT-ON* */
654     }
655   else
656     {
657       /* *INDENT-OFF* */
658       hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
659         send_ipsec_spd_interface_details(reg, v, k, mp->context);
660       }));
661       /* *INDENT-ON* */
662     }
663
664 #else
665   clib_warning ("unimplemented");
666 #endif
667 }
668
669 static u32
670 ipsec_tun_mk_input_sa_id (u32 ti)
671 {
672   return (0x80000000 | ti);
673 }
674
675 static u32
676 ipsec_tun_mk_output_sa_id (u32 ti)
677 {
678   return (0xc0000000 | ti);
679 }
680
681 static void
682 vl_api_ipsec_tunnel_if_add_del_t_handler (vl_api_ipsec_tunnel_if_add_del_t *
683                                           mp)
684 {
685   vl_api_ipsec_tunnel_if_add_del_reply_t *rmp;
686   u32 sw_if_index = ~0;
687   int rv;
688
689 #if WITH_LIBSSL > 0
690   ip46_address_t local_ip = ip46_address_initializer;
691   ip46_address_t remote_ip = ip46_address_initializer;
692   ipsec_key_t crypto_key, integ_key;
693   ipsec_sa_flags_t flags;
694   ip46_type_t local_ip_type, remote_ip_type;
695   ipip_transport_t transport;
696   u32 fib_index;
697
698   local_ip_type = ip_address_decode (&mp->local_ip, &local_ip);
699   remote_ip_type = ip_address_decode (&mp->remote_ip, &remote_ip);
700   transport = (IP46_TYPE_IP6 == local_ip_type ?
701                IPIP_TRANSPORT_IP6 : IPIP_TRANSPORT_IP4);
702
703   if (local_ip_type != remote_ip_type)
704     {
705       rv = VNET_API_ERROR_INVALID_VALUE;
706       goto done;
707     }
708
709   flags = IPSEC_SA_FLAG_NONE;
710
711   if (mp->udp_encap)
712     flags |= IPSEC_SA_FLAG_UDP_ENCAP;
713   if (mp->esn)
714     flags |= IPSEC_SA_FLAG_USE_ESN;
715   if (mp->anti_replay)
716     flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY;
717
718   ipsec_mk_key (&crypto_key, mp->remote_crypto_key,
719                 mp->remote_crypto_key_len);
720   ipsec_mk_key (&integ_key, mp->remote_integ_key, mp->remote_integ_key_len);
721   ipsec_mk_key (&crypto_key, mp->local_crypto_key, mp->local_crypto_key_len);
722   ipsec_mk_key (&integ_key, mp->local_integ_key, mp->local_integ_key_len);
723
724   fib_index =
725     fib_table_find (fib_proto_from_ip46 (local_ip_type),
726                     ntohl (mp->tx_table_id));
727
728   if (~0 == fib_index)
729     {
730       rv = VNET_API_ERROR_NO_SUCH_FIB;
731       goto done;
732     }
733
734   if (mp->is_add)
735     {
736       // remote = input, local = output
737       /* create an ip-ip tunnel, then the two SA, then bind them */
738       rv = ipip_add_tunnel (transport,
739                             (mp->renumber ? ntohl (mp->show_instance) : ~0),
740                             &local_ip,
741                             &remote_ip, fib_index,
742                             TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
743                             TUNNEL_MODE_P2P, &sw_if_index);
744
745       if (rv)
746         goto done;
747
748       rv = ipsec_sa_add_and_lock (ipsec_tun_mk_input_sa_id (sw_if_index),
749                                   ntohl (mp->remote_spi),
750                                   IPSEC_PROTOCOL_ESP,
751                                   mp->crypto_alg,
752                                   &crypto_key,
753                                   mp->integ_alg,
754                                   &integ_key,
755                                   (flags | IPSEC_SA_FLAG_IS_INBOUND),
756                                   ntohl (mp->tx_table_id),
757                                   mp->salt, &remote_ip, &local_ip,
758                                   TUNNEL_ENCAP_DECAP_FLAG_NONE,
759                                   IP_DSCP_CS0, NULL,
760                                   IPSEC_UDP_PORT_NONE, IPSEC_UDP_PORT_NONE);
761
762       if (rv)
763         goto done;
764
765       rv = ipsec_sa_add_and_lock (ipsec_tun_mk_output_sa_id (sw_if_index),
766                                   ntohl (mp->local_spi),
767                                   IPSEC_PROTOCOL_ESP,
768                                   mp->crypto_alg,
769                                   &crypto_key,
770                                   mp->integ_alg,
771                                   &integ_key,
772                                   flags,
773                                   ntohl (mp->tx_table_id),
774                                   mp->salt, &local_ip, &remote_ip,
775                                   TUNNEL_ENCAP_DECAP_FLAG_NONE,
776                                   IP_DSCP_CS0, NULL,
777                                   IPSEC_UDP_PORT_NONE, IPSEC_UDP_PORT_NONE);
778
779       if (rv)
780         goto done;
781
782       rv = ipsec_tun_protect_update_one (sw_if_index, NULL,
783                                          ipsec_tun_mk_output_sa_id
784                                          (sw_if_index),
785                                          ipsec_tun_mk_input_sa_id
786                                          (sw_if_index));
787       if (rv)
788         goto done;
789
790       /* the SAs are locked as a result of being used for proection,
791        * they cannot be removed from the API, since they cannot be refered
792        * to by the API. unlock them now, so that if the tunnel is rekeyed
793        * they-ll disapper
794        */
795       ipsec_sa_unlock_id (ipsec_tun_mk_input_sa_id (sw_if_index));
796       ipsec_sa_unlock_id (ipsec_tun_mk_output_sa_id (sw_if_index));
797     }
798   else
799     {
800       /* *INDENT-OFF* */
801       ipip_tunnel_key_t key = {
802         .transport = transport,
803         .fib_index = fib_index,
804         .src = local_ip,
805         .dst = remote_ip
806       };
807       /* *INDENT-ON* */
808
809       ipip_tunnel_t *t = ipip_tunnel_db_find (&key);
810
811       if (NULL != t)
812         {
813           rv = ipsec_tun_protect_del (t->sw_if_index, NULL);
814           ipip_del_tunnel (t->sw_if_index);
815         }
816       else
817         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
818     }
819
820 #else
821   rv = VNET_API_ERROR_UNIMPLEMENTED;
822 #endif
823 done:
824   /* *INDENT-OFF* */
825   REPLY_MACRO2 (VL_API_IPSEC_TUNNEL_IF_ADD_DEL_REPLY,
826   ({
827     rmp->sw_if_index = htonl (sw_if_index);
828   }));
829   /* *INDENT-ON* */
830 }
831
832 static void
833 vl_api_ipsec_itf_create_t_handler (vl_api_ipsec_itf_create_t * mp)
834 {
835   vl_api_ipsec_itf_create_reply_t *rmp;
836   tunnel_mode_t mode;
837   u32 sw_if_index = ~0;
838   int rv;
839
840   rv = tunnel_mode_decode (mp->itf.mode, &mode);
841
842   if (!rv)
843     rv = ipsec_itf_create (ntohl (mp->itf.user_instance), mode, &sw_if_index);
844
845   /* *INDENT-OFF* */
846   REPLY_MACRO2 (VL_API_IPSEC_ITF_CREATE_REPLY,
847   ({
848     rmp->sw_if_index = htonl (sw_if_index);
849   }));
850   /* *INDENT-ON* */
851 }
852
853 static void
854 vl_api_ipsec_itf_delete_t_handler (vl_api_ipsec_itf_delete_t * mp)
855 {
856   vl_api_ipsec_itf_delete_reply_t *rmp;
857   int rv;
858
859   rv = ipsec_itf_delete (ntohl (mp->sw_if_index));
860
861   REPLY_MACRO (VL_API_IPSEC_ITF_DELETE_REPLY);
862 }
863
864 static void
865 vl_api_ipsec_itf_dump_t_handler (vl_api_ipsec_itf_dump_t * mp)
866 {
867 }
868
869 typedef struct ipsec_sa_dump_match_ctx_t_
870 {
871   index_t sai;
872   u32 sw_if_index;
873 } ipsec_sa_dump_match_ctx_t;
874
875 static walk_rc_t
876 ipsec_sa_dump_match_sa (index_t itpi, void *arg)
877 {
878   ipsec_sa_dump_match_ctx_t *ctx = arg;
879   ipsec_tun_protect_t *itp;
880   index_t sai;
881
882   itp = ipsec_tun_protect_get (itpi);
883
884   if (itp->itp_out_sa == ctx->sai)
885     {
886       ctx->sw_if_index = itp->itp_sw_if_index;
887       return (WALK_STOP);
888     }
889   /* *INDENT-OFF* */
890   FOR_EACH_IPSEC_PROTECT_INPUT_SAI (itp, sai,
891   ({
892     if (sai == ctx->sai)
893       {
894         ctx->sw_if_index = itp->itp_sw_if_index;
895         return (WALK_STOP);
896       }
897   }));
898   /* *INDENT-OFF* */
899
900   return (WALK_CONTINUE);
901 }
902
903 static walk_rc_t
904 send_ipsec_sa_details (ipsec_sa_t * sa, void *arg)
905 {
906   ipsec_dump_walk_ctx_t *ctx = arg;
907   vl_api_ipsec_sa_details_t *mp;
908   ipsec_main_t *im = &ipsec_main;
909
910   mp = vl_msg_api_alloc (sizeof (*mp));
911   clib_memset (mp, 0, sizeof (*mp));
912   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_DETAILS);
913   mp->context = ctx->context;
914
915   mp->entry.sad_id = htonl (sa->id);
916   mp->entry.spi = htonl (sa->spi);
917   mp->entry.protocol = ipsec_proto_encode (sa->protocol);
918   mp->entry.tx_table_id =
919     htonl (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
920
921   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
922   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
923
924   mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
925   ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
926
927   mp->entry.flags = ipsec_sad_flags_encode (sa);
928   mp->entry.salt = clib_host_to_net_u32 (sa->salt);
929
930   if (ipsec_sa_is_set_IS_PROTECT (sa))
931     {
932       ipsec_sa_dump_match_ctx_t ctx = {
933         .sai = sa - im->sad,
934         .sw_if_index = ~0,
935       };
936       ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
937
938       mp->sw_if_index = htonl (ctx.sw_if_index);
939     }
940   else
941     mp->sw_if_index = ~0;
942
943   if (ipsec_sa_is_set_IS_TUNNEL (sa))
944     {
945       ip_address_encode (&sa->tunnel_src_addr, IP46_TYPE_ANY,
946                          &mp->entry.tunnel_src);
947       ip_address_encode (&sa->tunnel_dst_addr, IP46_TYPE_ANY,
948                          &mp->entry.tunnel_dst);
949     }
950   if (ipsec_sa_is_set_UDP_ENCAP (sa))
951     {
952       mp->entry.udp_src_port = sa->udp_hdr.src_port;
953       mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
954     }
955
956   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
957   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
958   if (ipsec_sa_is_set_USE_ESN (sa))
959     {
960       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
961       mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
962     }
963   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
964     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
965
966   mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
967
968   vl_api_send_msg (ctx->reg, (u8 *) mp);
969
970   return (WALK_CONTINUE);
971 }
972
973 static void
974 vl_api_ipsec_sa_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
975 {
976   vl_api_registration_t *reg;
977
978 #if WITH_LIBSSL > 0
979   reg = vl_api_client_index_to_registration (mp->client_index);
980   if (!reg)
981     return;
982
983   ipsec_dump_walk_ctx_t ctx = {
984     .reg = reg,
985     .context = mp->context,
986   };
987
988   ipsec_sa_walk (send_ipsec_sa_details, &ctx);
989
990 #else
991   clib_warning ("unimplemented");
992 #endif
993 }
994
995 static walk_rc_t
996 send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg)
997 {
998   ipsec_dump_walk_ctx_t *ctx = arg;
999   vl_api_ipsec_sa_v2_details_t *mp;
1000   ipsec_main_t *im = &ipsec_main;
1001
1002   mp = vl_msg_api_alloc (sizeof (*mp));
1003   clib_memset (mp, 0, sizeof (*mp));
1004   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_V2_DETAILS);
1005   mp->context = ctx->context;
1006
1007   mp->entry.sad_id = htonl (sa->id);
1008   mp->entry.spi = htonl (sa->spi);
1009   mp->entry.protocol = ipsec_proto_encode (sa->protocol);
1010   mp->entry.tx_table_id =
1011     htonl (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
1012
1013   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
1014   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
1015
1016   mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
1017   ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
1018
1019   mp->entry.flags = ipsec_sad_flags_encode (sa);
1020   mp->entry.salt = clib_host_to_net_u32 (sa->salt);
1021
1022   if (ipsec_sa_is_set_IS_PROTECT (sa))
1023     {
1024       ipsec_sa_dump_match_ctx_t ctx = {
1025         .sai = sa - im->sad,
1026         .sw_if_index = ~0,
1027       };
1028       ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
1029
1030       mp->sw_if_index = htonl (ctx.sw_if_index);
1031     }
1032   else
1033     mp->sw_if_index = ~0;
1034
1035   if (ipsec_sa_is_set_IS_TUNNEL (sa))
1036     {
1037       ip_address_encode (&sa->tunnel_src_addr, IP46_TYPE_ANY,
1038                          &mp->entry.tunnel_src);
1039       ip_address_encode (&sa->tunnel_dst_addr, IP46_TYPE_ANY,
1040                          &mp->entry.tunnel_dst);
1041     }
1042   if (ipsec_sa_is_set_UDP_ENCAP (sa))
1043     {
1044       mp->entry.udp_src_port = sa->udp_hdr.src_port;
1045       mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
1046     }
1047
1048   mp->entry.tunnel_flags = tunnel_encap_decap_flags_encode (sa->tunnel_flags);
1049   mp->entry.dscp = ip_dscp_encode (sa->dscp);
1050
1051   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
1052   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
1053   if (ipsec_sa_is_set_USE_ESN (sa))
1054     {
1055       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1056       mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
1057     }
1058   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
1059     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
1060
1061   mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
1062
1063   vl_api_send_msg (ctx->reg, (u8 *) mp);
1064
1065   return (WALK_CONTINUE);
1066 }
1067
1068 static void
1069 vl_api_ipsec_sa_v2_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
1070 {
1071   vl_api_registration_t *reg;
1072
1073 #if WITH_LIBSSL > 0
1074   reg = vl_api_client_index_to_registration (mp->client_index);
1075   if (!reg)
1076     return;
1077
1078   ipsec_dump_walk_ctx_t ctx = {
1079     .reg = reg,
1080     .context = mp->context,
1081   };
1082
1083   ipsec_sa_walk (send_ipsec_sa_v2_details, &ctx);
1084
1085 #else
1086   clib_warning ("unimplemented");
1087 #endif
1088 }
1089
1090 static void
1091 vl_api_ipsec_tunnel_if_set_sa_t_handler (vl_api_ipsec_tunnel_if_set_sa_t * mp)
1092 {
1093   vl_api_ipsec_tunnel_if_set_sa_reply_t *rmp;
1094   int rv;
1095
1096 #if WITH_LIBSSL > 0
1097   VALIDATE_SW_IF_INDEX(mp);
1098
1099   if (mp->is_outbound)
1100     rv = ipsec_tun_protect_update_out (ntohl (mp->sw_if_index), NULL,
1101                                        ntohl (mp->sa_id));
1102   else
1103     rv = ipsec_tun_protect_update_in (ntohl (mp->sw_if_index), NULL,
1104                                        ntohl (mp->sa_id));
1105
1106 #else
1107   clib_warning ("unimplemented");
1108 #endif
1109
1110   BAD_SW_IF_INDEX_LABEL;
1111
1112   REPLY_MACRO (VL_API_IPSEC_TUNNEL_IF_SET_SA_REPLY);
1113 }
1114
1115 static void
1116 vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp)
1117 {
1118   vl_api_registration_t *rp;
1119   ipsec_main_t *im = &ipsec_main;
1120   u32 context = mp->context;
1121
1122   rp = vl_api_client_index_to_registration (mp->client_index);
1123
1124   if (rp == 0)
1125     {
1126       clib_warning ("Client %d AWOL", mp->client_index);
1127       return;
1128     }
1129
1130   ipsec_ah_backend_t *ab;
1131   ipsec_esp_backend_t *eb;
1132   /* *INDENT-OFF* */
1133   pool_foreach (ab, im->ah_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 (ab->name),
1139               ab->name);
1140     mp->protocol = ntohl (IPSEC_API_PROTO_AH);
1141     mp->index = ab - im->ah_backends;
1142     mp->active = mp->index == im->ah_current_backend ? 1 : 0;
1143     vl_api_send_msg (rp, (u8 *)mp);
1144   });
1145   pool_foreach (eb, im->esp_backends, {
1146     vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1147     clib_memset (mp, 0, sizeof (*mp));
1148     mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
1149     mp->context = context;
1150     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (eb->name),
1151               eb->name);
1152     mp->protocol = ntohl (IPSEC_API_PROTO_ESP);
1153     mp->index = eb - im->esp_backends;
1154     mp->active = mp->index == im->esp_current_backend ? 1 : 0;
1155     vl_api_send_msg (rp, (u8 *)mp);
1156   });
1157   /* *INDENT-ON* */
1158 }
1159
1160 static void
1161 vl_api_ipsec_select_backend_t_handler (vl_api_ipsec_select_backend_t * mp)
1162 {
1163   ipsec_main_t *im = &ipsec_main;
1164   vl_api_ipsec_select_backend_reply_t *rmp;
1165   ipsec_protocol_t protocol;
1166   int rv = 0;
1167   if (pool_elts (im->sad) > 0)
1168     {
1169       rv = VNET_API_ERROR_INSTANCE_IN_USE;
1170       goto done;
1171     }
1172
1173   rv = ipsec_proto_decode (mp->protocol, &protocol);
1174
1175   if (rv)
1176     goto done;
1177
1178 #if WITH_LIBSSL > 0
1179   switch (protocol)
1180     {
1181     case IPSEC_PROTOCOL_ESP:
1182       rv = ipsec_select_esp_backend (im, mp->index);
1183       break;
1184     case IPSEC_PROTOCOL_AH:
1185       rv = ipsec_select_ah_backend (im, mp->index);
1186       break;
1187     default:
1188       rv = VNET_API_ERROR_INVALID_PROTOCOL;
1189       break;
1190     }
1191 #else
1192   clib_warning ("unimplemented");       /* FIXME */
1193 #endif
1194 done:
1195   REPLY_MACRO (VL_API_IPSEC_SELECT_BACKEND_REPLY);
1196 }
1197
1198 static void
1199 vl_api_ipsec_set_async_mode_t_handler (vl_api_ipsec_set_async_mode_t * mp)
1200 {
1201   vl_api_ipsec_set_async_mode_reply_t *rmp;
1202   int rv = 0;
1203
1204   vnet_crypto_request_async_mode (mp->async_enable);
1205   ipsec_set_async_mode (mp->async_enable);
1206
1207   REPLY_MACRO (VL_API_IPSEC_SET_ASYNC_MODE_REPLY);
1208 }
1209
1210 /*
1211  * ipsec_api_hookup
1212  * Add vpe's API message handlers to the table.
1213  * vlib has already mapped shared memory and
1214  * added the client registration handlers.
1215  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
1216  */
1217 #define vl_msg_name_crc_list
1218 #include <vnet/vnet_all_api_h.h>
1219 #undef vl_msg_name_crc_list
1220
1221 static void
1222 setup_message_id_table (api_main_t * am)
1223 {
1224 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
1225   foreach_vl_msg_name_crc_ipsec;
1226 #undef _
1227 }
1228
1229 static clib_error_t *
1230 ipsec_api_hookup (vlib_main_t * vm)
1231 {
1232   api_main_t *am = vlibapi_get_main ();
1233
1234 #define _(N,n)                                                  \
1235     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
1236                            vl_api_##n##_t_handler,              \
1237                            vl_noop_handler,                     \
1238                            vl_api_##n##_t_endian,               \
1239                            vl_api_##n##_t_print,                \
1240                            sizeof(vl_api_##n##_t), 1);
1241   foreach_vpe_api_msg;
1242 #undef _
1243
1244   /*
1245    * Set up the (msg_name, crc, message-id) table
1246    */
1247   setup_message_id_table (am);
1248
1249   return 0;
1250 }
1251
1252 VLIB_API_INIT_FUNCTION (ipsec_api_hookup);
1253
1254 /*
1255  * fd.io coding-style-patch-verification: ON
1256  *
1257  * Local Variables:
1258  * eval: (c-set-style "gnu")
1259  * End:
1260  */