ipsec: manually binding an SA to a worker
[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 #include <vnet/ipsec/ipsec.h>
33 #include <vnet/ipsec/ipsec_tun.h>
34 #include <vnet/ipsec/ipsec_itf.h>
35
36 #include <vnet/format_fns.h>
37 #include <vnet/ipsec/ipsec.api_enum.h>
38 #include <vnet/ipsec/ipsec.api_types.h>
39
40 #define REPLY_MSG_ID_BASE ipsec_main.msg_id_base
41 #include <vlibapi/api_helper_macros.h>
42
43 static void
44 vl_api_ipsec_spd_add_del_t_handler (vl_api_ipsec_spd_add_del_t * mp)
45 {
46   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
47   vl_api_ipsec_spd_add_del_reply_t *rmp;
48   int rv;
49
50   rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
51
52   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
53 }
54
55 static void vl_api_ipsec_interface_add_del_spd_t_handler
56   (vl_api_ipsec_interface_add_del_spd_t * mp)
57 {
58   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
59   vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
60   int rv;
61   u32 sw_if_index __attribute__ ((unused));
62   u32 spd_id __attribute__ ((unused));
63
64   sw_if_index = ntohl (mp->sw_if_index);
65   spd_id = ntohl (mp->spd_id);
66
67   VALIDATE_SW_IF_INDEX (mp);
68
69   rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
70
71   BAD_SW_IF_INDEX_LABEL;
72
73   REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
74 }
75
76 static void vl_api_ipsec_tunnel_protect_update_t_handler
77   (vl_api_ipsec_tunnel_protect_update_t * mp)
78 {
79   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
80   vl_api_ipsec_tunnel_protect_update_reply_t *rmp;
81   u32 sw_if_index, ii, *sa_ins = NULL;
82   ip_address_t nh;
83   int rv;
84
85   sw_if_index = ntohl (mp->tunnel.sw_if_index);
86
87   VALIDATE_SW_IF_INDEX (&(mp->tunnel));
88
89   for (ii = 0; ii < mp->tunnel.n_sa_in; ii++)
90     vec_add1 (sa_ins, ntohl (mp->tunnel.sa_in[ii]));
91
92   ip_address_decode2 (&mp->tunnel.nh, &nh);
93
94   rv = ipsec_tun_protect_update (sw_if_index, &nh,
95                                  ntohl (mp->tunnel.sa_out), sa_ins);
96
97   BAD_SW_IF_INDEX_LABEL;
98
99   REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_UPDATE_REPLY);
100 }
101
102 static void vl_api_ipsec_tunnel_protect_del_t_handler
103   (vl_api_ipsec_tunnel_protect_del_t * mp)
104 {
105   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
106   vl_api_ipsec_tunnel_protect_del_reply_t *rmp;
107   ip_address_t nh;
108   u32 sw_if_index;
109   int rv;
110
111   sw_if_index = ntohl (mp->sw_if_index);
112
113   VALIDATE_SW_IF_INDEX (mp);
114
115   ip_address_decode2 (&mp->nh, &nh);
116   rv = ipsec_tun_protect_del (sw_if_index, &nh);
117
118   BAD_SW_IF_INDEX_LABEL;
119
120   REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_DEL_REPLY);
121 }
122
123 typedef struct ipsec_dump_walk_ctx_t_
124 {
125   vl_api_registration_t *reg;
126   u32 context;
127   u32 sw_if_index;
128 } ipsec_dump_walk_ctx_t;
129
130 static walk_rc_t
131 send_ipsec_tunnel_protect_details (index_t itpi, void *arg)
132 {
133   ipsec_dump_walk_ctx_t *ctx = arg;
134   vl_api_ipsec_tunnel_protect_details_t *mp;
135   ipsec_tun_protect_t *itp;
136   u32 ii = 0;
137   ipsec_sa_t *sa;
138
139   itp = ipsec_tun_protect_get (itpi);
140
141   mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (u32) * itp->itp_n_sa_in));
142   clib_memset (mp, 0, sizeof (*mp));
143   mp->_vl_msg_id =
144     ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_TUNNEL_PROTECT_DETAILS);
145   mp->context = ctx->context;
146
147   mp->tun.sw_if_index = htonl (itp->itp_sw_if_index);
148   ip_address_encode2 (itp->itp_key, &mp->tun.nh);
149
150   sa = ipsec_sa_get (itp->itp_out_sa);
151   mp->tun.sa_out = htonl (sa->id);
152   mp->tun.n_sa_in = itp->itp_n_sa_in;
153   /* *INDENT-OFF* */
154   FOR_EACH_IPSEC_PROTECT_INPUT_SA(itp, sa,
155   ({
156     mp->tun.sa_in[ii++] = htonl (sa->id);
157   }));
158   /* *INDENT-ON* */
159
160   vl_api_send_msg (ctx->reg, (u8 *) mp);
161
162   return (WALK_CONTINUE);
163 }
164
165 static void
166 vl_api_ipsec_tunnel_protect_dump_t_handler (vl_api_ipsec_tunnel_protect_dump_t
167                                             * mp)
168 {
169   vl_api_registration_t *reg;
170   u32 sw_if_index;
171
172   reg = vl_api_client_index_to_registration (mp->client_index);
173   if (!reg)
174     return;
175
176   ipsec_dump_walk_ctx_t ctx = {
177     .reg = reg,
178     .context = mp->context,
179   };
180
181   sw_if_index = ntohl (mp->sw_if_index);
182
183   if (~0 == sw_if_index)
184     {
185       ipsec_tun_protect_walk (send_ipsec_tunnel_protect_details, &ctx);
186     }
187   else
188     {
189       ipsec_tun_protect_walk_itf (sw_if_index,
190                                   send_ipsec_tunnel_protect_details, &ctx);
191     }
192 }
193
194 static int
195 ipsec_spd_action_decode (vl_api_ipsec_spd_action_t in,
196                          ipsec_policy_action_t * out)
197 {
198   in = clib_net_to_host_u32 (in);
199
200   switch (in)
201     {
202 #define _(v,f,s) case IPSEC_API_SPD_ACTION_##f: \
203       *out = IPSEC_POLICY_ACTION_##f;              \
204       return (0);
205       foreach_ipsec_policy_action
206 #undef _
207     }
208   return (VNET_API_ERROR_UNIMPLEMENTED);
209 }
210
211 static void vl_api_ipsec_spd_entry_add_del_t_handler
212   (vl_api_ipsec_spd_entry_add_del_t * mp)
213 {
214   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
215   vl_api_ipsec_spd_entry_add_del_reply_t *rmp;
216   ip46_type_t itype;
217   u32 stat_index;
218   int rv;
219
220   stat_index = ~0;
221
222   ipsec_policy_t p;
223
224   clib_memset (&p, 0, sizeof (p));
225
226   p.id = ntohl (mp->entry.spd_id);
227   p.priority = ntohl (mp->entry.priority);
228
229   itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start);
230   ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop);
231   ip_address_decode (&mp->entry.local_address_start, &p.laddr.start);
232   ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop);
233
234   p.is_ipv6 = (itype == IP46_TYPE_IP6);
235
236   p.protocol =
237     mp->entry.protocol ? mp->entry.protocol : IPSEC_POLICY_PROTOCOL_ANY;
238   p.rport.start = ntohs (mp->entry.remote_port_start);
239   p.rport.stop = ntohs (mp->entry.remote_port_stop);
240   p.lport.start = ntohs (mp->entry.local_port_start);
241   p.lport.stop = ntohs (mp->entry.local_port_stop);
242
243   rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
244
245   if (rv)
246     goto out;
247
248   /* policy action resolve unsupported */
249   if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
250     {
251       clib_warning ("unsupported action: 'resolve'");
252       rv = VNET_API_ERROR_UNIMPLEMENTED;
253       goto out;
254     }
255   p.sa_id = ntohl (mp->entry.sa_id);
256   rv =
257     ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy,
258                           &p.type);
259   if (rv)
260     goto out;
261
262   rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index);
263   if (rv)
264     goto out;
265
266 out:
267   /* *INDENT-OFF* */
268   REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY,
269   ({
270     rmp->stat_index = ntohl(stat_index);
271   }));
272   /* *INDENT-ON* */
273 }
274
275 static void
276 vl_api_ipsec_spd_entry_add_del_v2_t_handler (
277   vl_api_ipsec_spd_entry_add_del_v2_t *mp)
278 {
279   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
280   vl_api_ipsec_spd_entry_add_del_reply_t *rmp;
281   ip46_type_t itype;
282   u32 stat_index;
283   int rv;
284
285   stat_index = ~0;
286
287   ipsec_policy_t p;
288
289   clib_memset (&p, 0, sizeof (p));
290
291   p.id = ntohl (mp->entry.spd_id);
292   p.priority = ntohl (mp->entry.priority);
293
294   itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start);
295   ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop);
296   ip_address_decode (&mp->entry.local_address_start, &p.laddr.start);
297   ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop);
298
299   p.is_ipv6 = (itype == IP46_TYPE_IP6);
300
301   p.protocol = mp->entry.protocol;
302   p.rport.start = ntohs (mp->entry.remote_port_start);
303   p.rport.stop = ntohs (mp->entry.remote_port_stop);
304   p.lport.start = ntohs (mp->entry.local_port_start);
305   p.lport.stop = ntohs (mp->entry.local_port_stop);
306
307   rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
308
309   if (rv)
310     goto out;
311
312   /* policy action resolve unsupported */
313   if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
314     {
315       clib_warning ("unsupported action: 'resolve'");
316       rv = VNET_API_ERROR_UNIMPLEMENTED;
317       goto out;
318     }
319   p.sa_id = ntohl (mp->entry.sa_id);
320   rv =
321     ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy, &p.type);
322   if (rv)
323     goto out;
324
325   rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index);
326   if (rv)
327     goto out;
328
329 out:
330   REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_V2_REPLY,
331                 ({ rmp->stat_index = ntohl (stat_index); }));
332 }
333
334 static void vl_api_ipsec_sad_entry_add_del_t_handler
335   (vl_api_ipsec_sad_entry_add_del_t * mp)
336 {
337   vl_api_ipsec_sad_entry_add_del_reply_t *rmp;
338   ipsec_key_t crypto_key, integ_key;
339   ipsec_crypto_alg_t crypto_alg;
340   ipsec_integ_alg_t integ_alg;
341   ipsec_protocol_t proto;
342   ipsec_sa_flags_t flags;
343   u32 id, spi, sa_index = ~0;
344   tunnel_t tun = {
345     .t_flags = TUNNEL_FLAG_NONE,
346     .t_encap_decap_flags = TUNNEL_ENCAP_DECAP_FLAG_NONE,
347     .t_dscp = 0,
348     .t_mode = TUNNEL_MODE_P2P,
349     .t_table_id = 0,
350     .t_hop_limit = 255,
351   };
352   int rv;
353
354   id = ntohl (mp->entry.sad_id);
355   if (!mp->is_add)
356     {
357       rv = ipsec_sa_unlock_id (id);
358       goto out;
359     }
360   spi = ntohl (mp->entry.spi);
361
362   rv = ipsec_proto_decode (mp->entry.protocol, &proto);
363
364   if (rv)
365     goto out;
366
367   rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
368
369   if (rv)
370     goto out;
371
372   rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
373
374   if (rv)
375     goto out;
376
377   ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
378   ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
379
380   flags = ipsec_sa_flags_decode (mp->entry.flags);
381
382   ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src);
383   ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst);
384
385   rv = ipsec_sa_add_and_lock (id, spi, proto, crypto_alg, &crypto_key,
386                               integ_alg, &integ_key, flags, mp->entry.salt,
387                               htons (mp->entry.udp_src_port),
388                               htons (mp->entry.udp_dst_port), &tun, &sa_index);
389
390 out:
391   /* *INDENT-OFF* */
392   REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_REPLY,
393   {
394     rmp->stat_index = htonl (sa_index);
395   });
396   /* *INDENT-ON* */
397 }
398
399 static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
400   (vl_api_ipsec_sad_entry_add_del_v2_t * mp)
401 {
402   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
403   vl_api_ipsec_sad_entry_add_del_v2_reply_t *rmp;
404   ipsec_key_t crypto_key, integ_key;
405   ipsec_crypto_alg_t crypto_alg;
406   ipsec_integ_alg_t integ_alg;
407   ipsec_protocol_t proto;
408   ipsec_sa_flags_t flags;
409   u32 id, spi, sa_index = ~0;
410   int rv;
411   tunnel_t tun = {
412     .t_flags = TUNNEL_FLAG_NONE,
413     .t_encap_decap_flags = TUNNEL_ENCAP_DECAP_FLAG_NONE,
414     .t_dscp = 0,
415     .t_mode = TUNNEL_MODE_P2P,
416     .t_table_id = htonl (mp->entry.tx_table_id),
417     .t_hop_limit = 255,
418   };
419
420   id = ntohl (mp->entry.sad_id);
421   if (!mp->is_add)
422     {
423       rv = ipsec_sa_unlock_id (id);
424       goto out;
425     }
426
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 = tunnel_encap_decap_flags_decode (mp->entry.tunnel_flags,
445                                         &tun.t_encap_decap_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   tun.t_dscp = ip_dscp_decode (mp->entry.dscp);
455
456   ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src);
457   ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst);
458
459     rv = ipsec_sa_add_and_lock (
460       id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags,
461       mp->entry.salt, htons (mp->entry.udp_src_port),
462       htons (mp->entry.udp_dst_port), &tun, &sa_index);
463
464 out:
465   /* *INDENT-OFF* */
466   REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_V2_REPLY,
467   {
468     rmp->stat_index = htonl (sa_index);
469   });
470   /* *INDENT-ON* */
471 }
472
473 static int
474 ipsec_sad_entry_add_v3 (const vl_api_ipsec_sad_entry_v3_t *entry,
475                         u32 *sa_index)
476 {
477   ipsec_key_t crypto_key, integ_key;
478   ipsec_crypto_alg_t crypto_alg;
479   ipsec_integ_alg_t integ_alg;
480   ipsec_protocol_t proto;
481   ipsec_sa_flags_t flags;
482   u32 id, spi;
483   tunnel_t tun = { 0 };
484   int rv;
485
486   id = ntohl (entry->sad_id);
487   spi = ntohl (entry->spi);
488
489   rv = ipsec_proto_decode (entry->protocol, &proto);
490
491   if (rv)
492     return (rv);
493
494   rv = ipsec_crypto_algo_decode (entry->crypto_algorithm, &crypto_alg);
495
496   if (rv)
497     return (rv);
498
499   rv = ipsec_integ_algo_decode (entry->integrity_algorithm, &integ_alg);
500
501   if (rv)
502     return (rv);
503
504   flags = ipsec_sa_flags_decode (entry->flags);
505
506   if (flags & IPSEC_SA_FLAG_IS_TUNNEL)
507     {
508       rv = tunnel_decode (&entry->tunnel, &tun);
509
510       if (rv)
511         return (rv);
512     }
513
514   ipsec_key_decode (&entry->crypto_key, &crypto_key);
515   ipsec_key_decode (&entry->integrity_key, &integ_key);
516
517   return ipsec_sa_add_and_lock (id, spi, proto, crypto_alg, &crypto_key,
518                                 integ_alg, &integ_key, flags, entry->salt,
519                                 htons (entry->udp_src_port),
520                                 htons (entry->udp_dst_port), &tun, sa_index);
521 }
522
523 static void
524 vl_api_ipsec_sad_entry_add_del_v3_t_handler (
525   vl_api_ipsec_sad_entry_add_del_v3_t *mp)
526 {
527   vl_api_ipsec_sad_entry_add_del_v3_reply_t *rmp;
528   u32 id, sa_index = ~0;
529   int rv;
530
531   id = ntohl (mp->entry.sad_id);
532
533   if (!mp->is_add)
534     {
535       rv = ipsec_sa_unlock_id (id);
536     }
537   else
538     {
539       rv = ipsec_sad_entry_add_v3 (&mp->entry, &sa_index);
540     }
541
542   REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_V3_REPLY,
543                 { rmp->stat_index = htonl (sa_index); });
544 }
545
546 static void
547 vl_api_ipsec_sad_entry_del_t_handler (vl_api_ipsec_sad_entry_del_t *mp)
548 {
549   vl_api_ipsec_sad_entry_del_reply_t *rmp;
550   int rv;
551
552   rv = ipsec_sa_unlock_id (ntohl (mp->id));
553
554   REPLY_MACRO (VL_API_IPSEC_SAD_ENTRY_DEL_REPLY);
555 }
556
557 static void
558 vl_api_ipsec_sad_entry_add_t_handler (vl_api_ipsec_sad_entry_add_t *mp)
559 {
560   vl_api_ipsec_sad_entry_add_reply_t *rmp;
561   u32 sa_index = ~0;
562   int rv;
563
564   rv = ipsec_sad_entry_add_v3 (&mp->entry, &sa_index);
565
566   REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_REPLY,
567                 { rmp->stat_index = htonl (sa_index); });
568 }
569
570 static void
571 vl_api_ipsec_sad_entry_update_t_handler (vl_api_ipsec_sad_entry_update_t *mp)
572 {
573   vl_api_ipsec_sad_entry_update_reply_t *rmp;
574   u32 id;
575   tunnel_t tun = { 0 };
576   int rv;
577
578   id = ntohl (mp->sad_id);
579
580   if (mp->is_tun)
581     {
582       rv = tunnel_decode (&mp->tunnel, &tun);
583
584       if (rv)
585         goto out;
586     }
587
588   rv = ipsec_sa_update (id, htons (mp->udp_src_port), htons (mp->udp_dst_port),
589                         &tun, mp->is_tun);
590
591 out:
592   REPLY_MACRO (VL_API_IPSEC_SAD_ENTRY_UPDATE_REPLY);
593 }
594
595 static void
596 vl_api_ipsec_sad_bind_t_handler (vl_api_ipsec_sad_bind_t *mp)
597 {
598   vl_api_ipsec_sad_bind_reply_t *rmp;
599   u32 sa_id;
600   u32 worker;
601   int rv;
602
603   sa_id = ntohl (mp->sa_id);
604   worker = ntohl (mp->worker);
605
606   rv = ipsec_sa_bind (sa_id, worker, true /* bind */);
607
608   REPLY_MACRO (VL_API_IPSEC_SAD_BIND_REPLY);
609 }
610
611 static void
612 vl_api_ipsec_sad_unbind_t_handler (vl_api_ipsec_sad_unbind_t *mp)
613 {
614   vl_api_ipsec_sad_unbind_reply_t *rmp;
615   u32 sa_id;
616   int rv;
617
618   sa_id = ntohl (mp->sa_id);
619
620   rv = ipsec_sa_bind (sa_id, ~0, false /* bind */);
621
622   REPLY_MACRO (VL_API_IPSEC_SAD_UNBIND_REPLY);
623 }
624
625 static void
626 send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg,
627                          u32 context)
628 {
629   vl_api_ipsec_spds_details_t *mp;
630   u32 n_policies = 0;
631
632   mp = vl_msg_api_alloc (sizeof (*mp));
633   clib_memset (mp, 0, sizeof (*mp));
634   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SPDS_DETAILS);
635   mp->context = context;
636
637   mp->spd_id = htonl (spd->id);
638 #define _(s, n) n_policies += vec_len (spd->policies[IPSEC_SPD_POLICY_##s]);
639   foreach_ipsec_spd_policy_type
640 #undef _
641     mp->npolicies = htonl (n_policies);
642
643   vl_api_send_msg (reg, (u8 *) mp);
644 }
645
646 static void
647 vl_api_ipsec_spds_dump_t_handler (vl_api_ipsec_spds_dump_t * mp)
648 {
649   vl_api_registration_t *reg;
650   ipsec_main_t *im = &ipsec_main;
651   ipsec_spd_t *spd;
652
653   reg = vl_api_client_index_to_registration (mp->client_index);
654   if (!reg)
655     return;
656
657   pool_foreach (spd, im->spds)  {
658     send_ipsec_spds_details (spd, reg, mp->context);
659   }
660 }
661
662 vl_api_ipsec_spd_action_t
663 ipsec_spd_action_encode (ipsec_policy_action_t in)
664 {
665   vl_api_ipsec_spd_action_t out = IPSEC_API_SPD_ACTION_BYPASS;
666
667   switch (in)
668     {
669 #define _(v,f,s) case IPSEC_POLICY_ACTION_##f: \
670       out = IPSEC_API_SPD_ACTION_##f;          \
671       break;
672       foreach_ipsec_policy_action
673 #undef _
674     }
675   return (clib_host_to_net_u32 (out));
676 }
677
678 static void
679 send_ipsec_spd_details (ipsec_policy_t * p, vl_api_registration_t * reg,
680                         u32 context)
681 {
682   vl_api_ipsec_spd_details_t *mp;
683
684   mp = vl_msg_api_alloc (sizeof (*mp));
685   clib_memset (mp, 0, sizeof (*mp));
686   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SPD_DETAILS);
687   mp->context = context;
688
689   mp->entry.spd_id = htonl (p->id);
690   mp->entry.priority = htonl (p->priority);
691   mp->entry.is_outbound = ((p->type == IPSEC_SPD_POLICY_IP6_OUTBOUND) ||
692                            (p->type == IPSEC_SPD_POLICY_IP4_OUTBOUND));
693
694   ip_address_encode (&p->laddr.start, IP46_TYPE_ANY,
695                      &mp->entry.local_address_start);
696   ip_address_encode (&p->laddr.stop, IP46_TYPE_ANY,
697                      &mp->entry.local_address_stop);
698   ip_address_encode (&p->raddr.start, IP46_TYPE_ANY,
699                      &mp->entry.remote_address_start);
700   ip_address_encode (&p->raddr.stop, IP46_TYPE_ANY,
701                      &mp->entry.remote_address_stop);
702   mp->entry.local_port_start = htons (p->lport.start);
703   mp->entry.local_port_stop = htons (p->lport.stop);
704   mp->entry.remote_port_start = htons (p->rport.start);
705   mp->entry.remote_port_stop = htons (p->rport.stop);
706   mp->entry.protocol = p->protocol;
707   mp->entry.policy = ipsec_spd_action_encode (p->policy);
708   mp->entry.sa_id = htonl (p->sa_id);
709
710   vl_api_send_msg (reg, (u8 *) mp);
711 }
712
713 static void
714 vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
715 {
716   vl_api_registration_t *reg;
717   ipsec_main_t *im = &ipsec_main;
718   ipsec_spd_policy_type_t ptype;
719   ipsec_policy_t *policy;
720   ipsec_spd_t *spd;
721   uword *p;
722   u32 spd_index, *ii;
723
724   reg = vl_api_client_index_to_registration (mp->client_index);
725   if (!reg)
726     return;
727
728   p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
729   if (!p)
730     return;
731
732   spd_index = p[0];
733   spd = pool_elt_at_index (im->spds, spd_index);
734
735   FOR_EACH_IPSEC_SPD_POLICY_TYPE(ptype) {
736     vec_foreach(ii, spd->policies[ptype])
737       {
738         policy = pool_elt_at_index(im->policies, *ii);
739
740         if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
741           send_ipsec_spd_details (policy, reg, mp->context);
742       }
743   }
744 }
745
746 static void
747 send_ipsec_spd_interface_details (vl_api_registration_t * reg, u32 spd_index,
748                                   u32 sw_if_index, u32 context)
749 {
750   vl_api_ipsec_spd_interface_details_t *mp;
751
752   mp = vl_msg_api_alloc (sizeof (*mp));
753   clib_memset (mp, 0, sizeof (*mp));
754   mp->_vl_msg_id =
755     ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SPD_INTERFACE_DETAILS);
756   mp->context = context;
757
758   mp->spd_index = htonl (spd_index);
759   mp->sw_if_index = htonl (sw_if_index);
760
761   vl_api_send_msg (reg, (u8 *) mp);
762 }
763
764 static void
765 vl_api_ipsec_spd_interface_dump_t_handler (vl_api_ipsec_spd_interface_dump_t *
766                                            mp)
767 {
768   ipsec_main_t *im = &ipsec_main;
769   vl_api_registration_t *reg;
770   u32 k, v, spd_index;
771
772   reg = vl_api_client_index_to_registration (mp->client_index);
773   if (!reg)
774     return;
775
776   if (mp->spd_index_valid)
777     {
778       spd_index = ntohl (mp->spd_index);
779       /* *INDENT-OFF* */
780       hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
781         if (v == spd_index)
782           send_ipsec_spd_interface_details(reg, v, k, mp->context);
783       }));
784       /* *INDENT-ON* */
785     }
786   else
787     {
788       hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
789         send_ipsec_spd_interface_details(reg, v, k, mp->context);
790       }));
791     }
792 }
793
794 static void
795 vl_api_ipsec_itf_create_t_handler (vl_api_ipsec_itf_create_t * mp)
796 {
797   vl_api_ipsec_itf_create_reply_t *rmp;
798   tunnel_mode_t mode;
799   u32 sw_if_index = ~0;
800   int rv;
801
802   rv = tunnel_mode_decode (mp->itf.mode, &mode);
803
804   if (!rv)
805     rv = ipsec_itf_create (ntohl (mp->itf.user_instance), mode, &sw_if_index);
806
807   /* *INDENT-OFF* */
808   REPLY_MACRO2 (VL_API_IPSEC_ITF_CREATE_REPLY,
809   ({
810     rmp->sw_if_index = htonl (sw_if_index);
811   }));
812   /* *INDENT-ON* */
813 }
814
815 static void
816 vl_api_ipsec_itf_delete_t_handler (vl_api_ipsec_itf_delete_t * mp)
817 {
818   vl_api_ipsec_itf_delete_reply_t *rmp;
819   int rv;
820
821   rv = ipsec_itf_delete (ntohl (mp->sw_if_index));
822
823   REPLY_MACRO (VL_API_IPSEC_ITF_DELETE_REPLY);
824 }
825
826 static walk_rc_t
827 send_ipsec_itf_details (ipsec_itf_t *itf, void *arg)
828 {
829   ipsec_dump_walk_ctx_t *ctx = arg;
830   vl_api_ipsec_itf_details_t *mp;
831
832   if (~0 != ctx->sw_if_index && ctx->sw_if_index != itf->ii_sw_if_index)
833     return (WALK_CONTINUE);
834
835   mp = vl_msg_api_alloc (sizeof (*mp));
836   clib_memset (mp, 0, sizeof (*mp));
837   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_ITF_DETAILS);
838   mp->context = ctx->context;
839
840   mp->itf.mode = tunnel_mode_encode (itf->ii_mode);
841   mp->itf.user_instance = htonl (itf->ii_user_instance);
842   mp->itf.sw_if_index = htonl (itf->ii_sw_if_index);
843   vl_api_send_msg (ctx->reg, (u8 *) mp);
844
845   return (WALK_CONTINUE);
846 }
847
848 static void
849 vl_api_ipsec_itf_dump_t_handler (vl_api_ipsec_itf_dump_t * mp)
850 {
851   vl_api_registration_t *reg;
852
853   reg = vl_api_client_index_to_registration (mp->client_index);
854   if (!reg)
855     return;
856
857   ipsec_dump_walk_ctx_t ctx = {
858     .reg = reg,
859     .context = mp->context,
860     .sw_if_index = ntohl (mp->sw_if_index),
861   };
862
863   ipsec_itf_walk (send_ipsec_itf_details, &ctx);
864 }
865
866 typedef struct ipsec_sa_dump_match_ctx_t_
867 {
868   index_t sai;
869   u32 sw_if_index;
870 } ipsec_sa_dump_match_ctx_t;
871
872 static walk_rc_t
873 ipsec_sa_dump_match_sa (index_t itpi, void *arg)
874 {
875   ipsec_sa_dump_match_ctx_t *ctx = arg;
876   ipsec_tun_protect_t *itp;
877   index_t sai;
878
879   itp = ipsec_tun_protect_get (itpi);
880
881   if (itp->itp_out_sa == ctx->sai)
882     {
883       ctx->sw_if_index = itp->itp_sw_if_index;
884       return (WALK_STOP);
885     }
886
887   FOR_EACH_IPSEC_PROTECT_INPUT_SAI (itp, sai,
888   ({
889     if (sai == ctx->sai)
890       {
891         ctx->sw_if_index = itp->itp_sw_if_index;
892         return (WALK_STOP);
893       }
894   }));
895
896   return (WALK_CONTINUE);
897 }
898
899 static walk_rc_t
900 send_ipsec_sa_details (ipsec_sa_t * sa, void *arg)
901 {
902   ipsec_dump_walk_ctx_t *ctx = arg;
903   vl_api_ipsec_sa_details_t *mp;
904
905   mp = vl_msg_api_alloc (sizeof (*mp));
906   clib_memset (mp, 0, sizeof (*mp));
907   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SA_DETAILS);
908   mp->context = ctx->context;
909
910   mp->entry.sad_id = htonl (sa->id);
911   mp->entry.spi = htonl (sa->spi);
912   mp->entry.protocol = ipsec_proto_encode (sa->protocol);
913   mp->entry.tx_table_id = htonl (sa->tunnel.t_table_id);
914
915   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
916   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
917
918   mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
919   ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
920
921   mp->entry.flags = ipsec_sad_flags_encode (sa);
922   mp->entry.salt = clib_host_to_net_u32 (sa->salt);
923
924   if (ipsec_sa_is_set_IS_PROTECT (sa))
925     {
926       ipsec_sa_dump_match_ctx_t ctx = {
927         .sai = sa - ipsec_sa_pool,
928         .sw_if_index = ~0,
929       };
930       ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
931
932       mp->sw_if_index = htonl (ctx.sw_if_index);
933     }
934   else
935     mp->sw_if_index = ~0;
936
937   if (ipsec_sa_is_set_IS_TUNNEL (sa))
938     {
939       ip_address_encode2 (&sa->tunnel.t_src, &mp->entry.tunnel_src);
940       ip_address_encode2 (&sa->tunnel.t_dst, &mp->entry.tunnel_dst);
941     }
942   if (ipsec_sa_is_set_UDP_ENCAP (sa))
943     {
944       mp->entry.udp_src_port = sa->udp_hdr.src_port;
945       mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
946     }
947
948   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
949   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
950   if (ipsec_sa_is_set_USE_ESN (sa))
951     {
952       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
953       mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
954     }
955   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
956     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
957
958   mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
959
960   vl_api_send_msg (ctx->reg, (u8 *) mp);
961
962   return (WALK_CONTINUE);
963 }
964
965 static void
966 vl_api_ipsec_sa_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
967 {
968   vl_api_registration_t *reg;
969
970   reg = vl_api_client_index_to_registration (mp->client_index);
971   if (!reg)
972     return;
973
974   ipsec_dump_walk_ctx_t ctx = {
975     .reg = reg,
976     .context = mp->context,
977   };
978
979   ipsec_sa_walk (send_ipsec_sa_details, &ctx);
980 }
981
982 static walk_rc_t
983 send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg)
984 {
985   ipsec_dump_walk_ctx_t *ctx = arg;
986   vl_api_ipsec_sa_v2_details_t *mp;
987
988   mp = vl_msg_api_alloc (sizeof (*mp));
989   clib_memset (mp, 0, sizeof (*mp));
990   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SA_V2_DETAILS);
991   mp->context = ctx->context;
992
993   mp->entry.sad_id = htonl (sa->id);
994   mp->entry.spi = htonl (sa->spi);
995   mp->entry.protocol = ipsec_proto_encode (sa->protocol);
996   mp->entry.tx_table_id = htonl (sa->tunnel.t_table_id);
997
998   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
999   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
1000
1001   mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
1002   ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
1003
1004   mp->entry.flags = ipsec_sad_flags_encode (sa);
1005   mp->entry.salt = clib_host_to_net_u32 (sa->salt);
1006
1007   if (ipsec_sa_is_set_IS_PROTECT (sa))
1008     {
1009       ipsec_sa_dump_match_ctx_t ctx = {
1010         .sai = sa - ipsec_sa_pool,
1011         .sw_if_index = ~0,
1012       };
1013       ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
1014
1015       mp->sw_if_index = htonl (ctx.sw_if_index);
1016     }
1017   else
1018     mp->sw_if_index = ~0;
1019
1020   if (ipsec_sa_is_set_IS_TUNNEL (sa))
1021     {
1022       ip_address_encode2 (&sa->tunnel.t_src, &mp->entry.tunnel_src);
1023       ip_address_encode2 (&sa->tunnel.t_dst, &mp->entry.tunnel_dst);
1024     }
1025   if (ipsec_sa_is_set_UDP_ENCAP (sa))
1026     {
1027       mp->entry.udp_src_port = sa->udp_hdr.src_port;
1028       mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
1029     }
1030
1031   mp->entry.tunnel_flags =
1032     tunnel_encap_decap_flags_encode (sa->tunnel.t_encap_decap_flags);
1033   mp->entry.dscp = ip_dscp_encode (sa->tunnel.t_dscp);
1034
1035   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
1036   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
1037   if (ipsec_sa_is_set_USE_ESN (sa))
1038     {
1039       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1040       mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1041     }
1042   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
1043     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
1044
1045   mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
1046
1047   vl_api_send_msg (ctx->reg, (u8 *) mp);
1048
1049   return (WALK_CONTINUE);
1050 }
1051
1052 static void
1053 vl_api_ipsec_sa_v2_dump_t_handler (vl_api_ipsec_sa_v2_dump_t *mp)
1054 {
1055   vl_api_registration_t *reg;
1056
1057   reg = vl_api_client_index_to_registration (mp->client_index);
1058   if (!reg)
1059     return;
1060
1061   ipsec_dump_walk_ctx_t ctx = {
1062     .reg = reg,
1063     .context = mp->context,
1064   };
1065
1066   ipsec_sa_walk (send_ipsec_sa_v2_details, &ctx);
1067 }
1068
1069 static walk_rc_t
1070 send_ipsec_sa_v3_details (ipsec_sa_t *sa, void *arg)
1071 {
1072   ipsec_dump_walk_ctx_t *ctx = arg;
1073   vl_api_ipsec_sa_v3_details_t *mp;
1074
1075   mp = vl_msg_api_alloc (sizeof (*mp));
1076   clib_memset (mp, 0, sizeof (*mp));
1077   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SA_V3_DETAILS);
1078   mp->context = ctx->context;
1079
1080   mp->entry.sad_id = htonl (sa->id);
1081   mp->entry.spi = htonl (sa->spi);
1082   mp->entry.protocol = ipsec_proto_encode (sa->protocol);
1083
1084   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
1085   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
1086
1087   mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
1088   ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
1089
1090   mp->entry.flags = ipsec_sad_flags_encode (sa);
1091   mp->entry.salt = clib_host_to_net_u32 (sa->salt);
1092
1093   if (ipsec_sa_is_set_IS_PROTECT (sa))
1094     {
1095       ipsec_sa_dump_match_ctx_t ctx = {
1096         .sai = sa - ipsec_sa_pool,
1097         .sw_if_index = ~0,
1098       };
1099       ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
1100
1101       mp->sw_if_index = htonl (ctx.sw_if_index);
1102     }
1103   else
1104     mp->sw_if_index = ~0;
1105
1106   if (ipsec_sa_is_set_IS_TUNNEL (sa))
1107     tunnel_encode (&sa->tunnel, &mp->entry.tunnel);
1108
1109   if (ipsec_sa_is_set_UDP_ENCAP (sa))
1110     {
1111       mp->entry.udp_src_port = sa->udp_hdr.src_port;
1112       mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
1113     }
1114
1115   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
1116   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
1117   if (ipsec_sa_is_set_USE_ESN (sa))
1118     {
1119       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1120       mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1121     }
1122   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
1123     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
1124
1125   mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
1126
1127   vl_api_send_msg (ctx->reg, (u8 *) mp);
1128
1129   return (WALK_CONTINUE);
1130 }
1131
1132 static void
1133 vl_api_ipsec_sa_v3_dump_t_handler (vl_api_ipsec_sa_v3_dump_t *mp)
1134 {
1135   vl_api_registration_t *reg;
1136
1137   reg = vl_api_client_index_to_registration (mp->client_index);
1138   if (!reg)
1139     return;
1140
1141   ipsec_dump_walk_ctx_t ctx = {
1142     .reg = reg,
1143     .context = mp->context,
1144   };
1145
1146   ipsec_sa_walk (send_ipsec_sa_v3_details, &ctx);
1147 }
1148
1149 static walk_rc_t
1150 send_ipsec_sa_v4_details (ipsec_sa_t *sa, void *arg)
1151 {
1152   ipsec_dump_walk_ctx_t *ctx = arg;
1153   vl_api_ipsec_sa_v4_details_t *mp;
1154
1155   mp = vl_msg_api_alloc (sizeof (*mp));
1156   clib_memset (mp, 0, sizeof (*mp));
1157   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_SA_V4_DETAILS);
1158   mp->context = ctx->context;
1159
1160   mp->entry.sad_id = htonl (sa->id);
1161   mp->entry.spi = htonl (sa->spi);
1162   mp->entry.protocol = ipsec_proto_encode (sa->protocol);
1163
1164   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
1165   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
1166
1167   mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
1168   ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
1169
1170   mp->entry.flags = ipsec_sad_flags_encode (sa);
1171   mp->entry.salt = clib_host_to_net_u32 (sa->salt);
1172
1173   if (ipsec_sa_is_set_IS_PROTECT (sa))
1174     {
1175       ipsec_sa_dump_match_ctx_t ctx = {
1176         .sai = sa - ipsec_sa_pool,
1177         .sw_if_index = ~0,
1178       };
1179       ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
1180
1181       mp->sw_if_index = htonl (ctx.sw_if_index);
1182     }
1183   else
1184     mp->sw_if_index = ~0;
1185
1186   if (ipsec_sa_is_set_IS_TUNNEL (sa))
1187     tunnel_encode (&sa->tunnel, &mp->entry.tunnel);
1188
1189   if (ipsec_sa_is_set_UDP_ENCAP (sa))
1190     {
1191       mp->entry.udp_src_port = sa->udp_hdr.src_port;
1192       mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
1193     }
1194
1195   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
1196   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
1197   if (ipsec_sa_is_set_USE_ESN (sa))
1198     {
1199       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1200       mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
1201     }
1202   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
1203     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
1204
1205   mp->thread_index = clib_host_to_net_u32 (sa->thread_index);
1206   mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
1207
1208   vl_api_send_msg (ctx->reg, (u8 *) mp);
1209
1210   return (WALK_CONTINUE);
1211 }
1212
1213 static void
1214 vl_api_ipsec_sa_v4_dump_t_handler (vl_api_ipsec_sa_v4_dump_t *mp)
1215 {
1216   vl_api_registration_t *reg;
1217
1218   reg = vl_api_client_index_to_registration (mp->client_index);
1219   if (!reg)
1220     return;
1221
1222   ipsec_dump_walk_ctx_t ctx = {
1223     .reg = reg,
1224     .context = mp->context,
1225   };
1226
1227   ipsec_sa_walk (send_ipsec_sa_v4_details, &ctx);
1228 }
1229
1230 static void
1231 vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp)
1232 {
1233   vl_api_registration_t *rp;
1234   ipsec_main_t *im = &ipsec_main;
1235   u32 context = mp->context;
1236
1237   rp = vl_api_client_index_to_registration (mp->client_index);
1238
1239   if (rp == 0)
1240     {
1241       clib_warning ("Client %d AWOL", mp->client_index);
1242       return;
1243     }
1244
1245   ipsec_ah_backend_t *ab;
1246   ipsec_esp_backend_t *eb;
1247   /* *INDENT-OFF* */
1248   pool_foreach (ab, im->ah_backends) {
1249     vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1250     clib_memset (mp, 0, sizeof (*mp));
1251     mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_BACKEND_DETAILS);
1252     mp->context = context;
1253     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (ab->name),
1254               ab->name);
1255     mp->protocol = ntohl (IPSEC_API_PROTO_AH);
1256     mp->index = ab - im->ah_backends;
1257     mp->active = mp->index == im->ah_current_backend ? 1 : 0;
1258     vl_api_send_msg (rp, (u8 *)mp);
1259   }
1260   pool_foreach (eb, im->esp_backends) {
1261     vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
1262     clib_memset (mp, 0, sizeof (*mp));
1263     mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_BACKEND_DETAILS);
1264     mp->context = context;
1265     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (eb->name),
1266               eb->name);
1267     mp->protocol = ntohl (IPSEC_API_PROTO_ESP);
1268     mp->index = eb - im->esp_backends;
1269     mp->active = mp->index == im->esp_current_backend ? 1 : 0;
1270     vl_api_send_msg (rp, (u8 *)mp);
1271   }
1272   /* *INDENT-ON* */
1273 }
1274
1275 static void
1276 vl_api_ipsec_select_backend_t_handler (vl_api_ipsec_select_backend_t * mp)
1277 {
1278   ipsec_main_t *im = &ipsec_main;
1279   vl_api_ipsec_select_backend_reply_t *rmp;
1280   ipsec_protocol_t protocol;
1281   int rv = 0;
1282   if (pool_elts (ipsec_sa_pool) > 0)
1283     {
1284       rv = VNET_API_ERROR_INSTANCE_IN_USE;
1285       goto done;
1286     }
1287
1288   rv = ipsec_proto_decode (mp->protocol, &protocol);
1289
1290   if (rv)
1291     goto done;
1292
1293   switch (protocol)
1294     {
1295     case IPSEC_PROTOCOL_ESP:
1296       rv = ipsec_select_esp_backend (im, mp->index);
1297       break;
1298     case IPSEC_PROTOCOL_AH:
1299       rv = ipsec_select_ah_backend (im, mp->index);
1300       break;
1301     default:
1302       rv = VNET_API_ERROR_INVALID_PROTOCOL;
1303       break;
1304     }
1305 done:
1306   REPLY_MACRO (VL_API_IPSEC_SELECT_BACKEND_REPLY);
1307 }
1308
1309 static void
1310 vl_api_ipsec_set_async_mode_t_handler (vl_api_ipsec_set_async_mode_t * mp)
1311 {
1312   vl_api_ipsec_set_async_mode_reply_t *rmp;
1313   int rv = 0;
1314
1315   ipsec_set_async_mode (mp->async_enable);
1316
1317   REPLY_MACRO (VL_API_IPSEC_SET_ASYNC_MODE_REPLY);
1318 }
1319
1320 #include <vnet/ipsec/ipsec.api.c>
1321 static clib_error_t *
1322 ipsec_api_hookup (vlib_main_t * vm)
1323 {
1324   /*
1325    * Set up the (msg_name, crc, message-id) table
1326    */
1327   REPLY_MSG_ID_BASE = setup_message_id_table ();
1328
1329   return 0;
1330 }
1331
1332 VLIB_API_INIT_FUNCTION (ipsec_api_hookup);
1333
1334 /*
1335  * fd.io coding-style-patch-verification: ON
1336  *
1337  * Local Variables:
1338  * eval: (c-set-style "gnu")
1339  * End:
1340  */