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