ipsec: Deprecated the old IPsec Tunnel interface
[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_SELECT_BACKEND, ipsec_select_backend)                   \
72 _(IPSEC_BACKEND_DUMP, ipsec_backend_dump)                       \
73 _(IPSEC_TUNNEL_PROTECT_UPDATE, ipsec_tunnel_protect_update)     \
74 _(IPSEC_TUNNEL_PROTECT_DEL, ipsec_tunnel_protect_del)           \
75 _(IPSEC_TUNNEL_PROTECT_DUMP, ipsec_tunnel_protect_dump)         \
76 _(IPSEC_SET_ASYNC_MODE, ipsec_set_async_mode)
77
78 static void
79 vl_api_ipsec_spd_add_del_t_handler (vl_api_ipsec_spd_add_del_t * mp)
80 {
81 #if WITH_LIBSSL == 0
82   clib_warning ("unimplemented");
83 #else
84
85   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
86   vl_api_ipsec_spd_add_del_reply_t *rmp;
87   int rv;
88
89   rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
90
91   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
92 #endif
93 }
94
95 static void vl_api_ipsec_interface_add_del_spd_t_handler
96   (vl_api_ipsec_interface_add_del_spd_t * mp)
97 {
98   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
99   vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
100   int rv;
101   u32 sw_if_index __attribute__ ((unused));
102   u32 spd_id __attribute__ ((unused));
103
104   sw_if_index = ntohl (mp->sw_if_index);
105   spd_id = ntohl (mp->spd_id);
106
107   VALIDATE_SW_IF_INDEX (mp);
108
109 #if WITH_LIBSSL > 0
110   rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
111 #else
112   rv = VNET_API_ERROR_UNIMPLEMENTED;
113 #endif
114
115   BAD_SW_IF_INDEX_LABEL;
116
117   REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
118 }
119
120 static void vl_api_ipsec_tunnel_protect_update_t_handler
121   (vl_api_ipsec_tunnel_protect_update_t * mp)
122 {
123   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
124   vl_api_ipsec_tunnel_protect_update_reply_t *rmp;
125   u32 sw_if_index, ii, *sa_ins = NULL;
126   ip_address_t nh;
127   int rv;
128
129   sw_if_index = ntohl (mp->tunnel.sw_if_index);
130
131   VALIDATE_SW_IF_INDEX (&(mp->tunnel));
132
133 #if WITH_LIBSSL > 0
134
135   for (ii = 0; ii < mp->tunnel.n_sa_in; ii++)
136     vec_add1 (sa_ins, ntohl (mp->tunnel.sa_in[ii]));
137
138   ip_address_decode2 (&mp->tunnel.nh, &nh);
139
140   rv = ipsec_tun_protect_update (sw_if_index, &nh,
141                                  ntohl (mp->tunnel.sa_out), sa_ins);
142 #else
143   rv = VNET_API_ERROR_UNIMPLEMENTED;
144 #endif
145
146   BAD_SW_IF_INDEX_LABEL;
147
148   REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_UPDATE_REPLY);
149 }
150
151 static void vl_api_ipsec_tunnel_protect_del_t_handler
152   (vl_api_ipsec_tunnel_protect_del_t * mp)
153 {
154   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
155   vl_api_ipsec_tunnel_protect_del_reply_t *rmp;
156   ip_address_t nh;
157   u32 sw_if_index;
158   int rv;
159
160   sw_if_index = ntohl (mp->sw_if_index);
161
162   VALIDATE_SW_IF_INDEX (mp);
163
164 #if WITH_LIBSSL > 0
165   ip_address_decode2 (&mp->nh, &nh);
166   rv = ipsec_tun_protect_del (sw_if_index, &nh);
167 #else
168   rv = VNET_API_ERROR_UNIMPLEMENTED;
169 #endif
170
171   BAD_SW_IF_INDEX_LABEL;
172
173   REPLY_MACRO (VL_API_IPSEC_TUNNEL_PROTECT_DEL_REPLY);
174 }
175
176 typedef struct ipsec_dump_walk_ctx_t_
177 {
178   vl_api_registration_t *reg;
179   u32 context;
180 } ipsec_dump_walk_ctx_t;
181
182 static walk_rc_t
183 send_ipsec_tunnel_protect_details (index_t itpi, void *arg)
184 {
185   ipsec_dump_walk_ctx_t *ctx = arg;
186   vl_api_ipsec_tunnel_protect_details_t *mp;
187   ipsec_tun_protect_t *itp;
188   u32 ii = 0;
189   ipsec_sa_t *sa;
190
191   itp = ipsec_tun_protect_get (itpi);
192
193   mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (u32) * itp->itp_n_sa_in));
194   clib_memset (mp, 0, sizeof (*mp));
195   mp->_vl_msg_id = ntohs (VL_API_IPSEC_TUNNEL_PROTECT_DETAILS);
196   mp->context = ctx->context;
197
198   mp->tun.sw_if_index = htonl (itp->itp_sw_if_index);
199   ip_address_encode2 (itp->itp_key, &mp->tun.nh);
200
201   sa = ipsec_sa_get (itp->itp_out_sa);
202   mp->tun.sa_out = htonl (sa->id);
203   mp->tun.n_sa_in = itp->itp_n_sa_in;
204   /* *INDENT-OFF* */
205   FOR_EACH_IPSEC_PROTECT_INPUT_SA(itp, sa,
206   ({
207     mp->tun.sa_in[ii++] = htonl (sa->id);
208   }));
209   /* *INDENT-ON* */
210
211   vl_api_send_msg (ctx->reg, (u8 *) mp);
212
213   return (WALK_CONTINUE);
214 }
215
216 static void
217 vl_api_ipsec_tunnel_protect_dump_t_handler (vl_api_ipsec_tunnel_protect_dump_t
218                                             * mp)
219 {
220   vl_api_registration_t *reg;
221   u32 sw_if_index;
222
223 #if WITH_LIBSSL > 0
224   reg = vl_api_client_index_to_registration (mp->client_index);
225   if (!reg)
226     return;
227
228   ipsec_dump_walk_ctx_t ctx = {
229     .reg = reg,
230     .context = mp->context,
231   };
232
233   sw_if_index = ntohl (mp->sw_if_index);
234
235   if (~0 == sw_if_index)
236     {
237       ipsec_tun_protect_walk (send_ipsec_tunnel_protect_details, &ctx);
238     }
239   else
240     {
241       ipsec_tun_protect_walk_itf (sw_if_index,
242                                   send_ipsec_tunnel_protect_details, &ctx);
243     }
244 #else
245   clib_warning ("unimplemented");
246 #endif
247 }
248
249 static int
250 ipsec_spd_action_decode (vl_api_ipsec_spd_action_t in,
251                          ipsec_policy_action_t * out)
252 {
253   in = clib_net_to_host_u32 (in);
254
255   switch (in)
256     {
257 #define _(v,f,s) case IPSEC_API_SPD_ACTION_##f: \
258       *out = IPSEC_POLICY_ACTION_##f;              \
259       return (0);
260       foreach_ipsec_policy_action
261 #undef _
262     }
263   return (VNET_API_ERROR_UNIMPLEMENTED);
264 }
265
266 static void vl_api_ipsec_spd_entry_add_del_t_handler
267   (vl_api_ipsec_spd_entry_add_del_t * mp)
268 {
269   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
270   vl_api_ipsec_spd_entry_add_del_reply_t *rmp;
271   ip46_type_t itype;
272   u32 stat_index;
273   int rv;
274
275   stat_index = ~0;
276
277 #if WITH_LIBSSL > 0
278   ipsec_policy_t p;
279
280   clib_memset (&p, 0, sizeof (p));
281
282   p.id = ntohl (mp->entry.spd_id);
283   p.priority = ntohl (mp->entry.priority);
284
285   itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start);
286   ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop);
287   ip_address_decode (&mp->entry.local_address_start, &p.laddr.start);
288   ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop);
289
290   p.is_ipv6 = (itype == IP46_TYPE_IP6);
291
292   p.protocol = mp->entry.protocol;
293   p.rport.start = ntohs (mp->entry.remote_port_start);
294   p.rport.stop = ntohs (mp->entry.remote_port_stop);
295   p.lport.start = ntohs (mp->entry.local_port_start);
296   p.lport.stop = ntohs (mp->entry.local_port_stop);
297
298   rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
299
300   if (rv)
301     goto out;
302
303   /* policy action resolve unsupported */
304   if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
305     {
306       clib_warning ("unsupported action: 'resolve'");
307       rv = VNET_API_ERROR_UNIMPLEMENTED;
308       goto out;
309     }
310   p.sa_id = ntohl (mp->entry.sa_id);
311   rv =
312     ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy,
313                           &p.type);
314   if (rv)
315     goto out;
316
317   rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index);
318   if (rv)
319     goto out;
320
321 #else
322   rv = VNET_API_ERROR_UNIMPLEMENTED;
323   goto out;
324 #endif
325
326 out:
327   /* *INDENT-OFF* */
328   REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY,
329   ({
330     rmp->stat_index = ntohl(stat_index);
331   }));
332   /* *INDENT-ON* */
333 }
334
335 static void vl_api_ipsec_sad_entry_add_del_t_handler
336   (vl_api_ipsec_sad_entry_add_del_t * mp)
337 {
338   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
339   vl_api_ipsec_sad_entry_add_del_reply_t *rmp;
340   ip46_address_t tun_src = { }, tun_dst =
341   {
342   };
343   ipsec_key_t crypto_key, integ_key;
344   ipsec_crypto_alg_t crypto_alg;
345   ipsec_integ_alg_t integ_alg;
346   ipsec_protocol_t proto;
347   ipsec_sa_flags_t flags;
348   u32 id, spi, sa_index = ~0;
349   int rv;
350
351 #if WITH_LIBSSL > 0
352
353   id = ntohl (mp->entry.sad_id);
354   spi = ntohl (mp->entry.spi);
355
356   rv = ipsec_proto_decode (mp->entry.protocol, &proto);
357
358   if (rv)
359     goto out;
360
361   rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
362
363   if (rv)
364     goto out;
365
366   rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
367
368   if (rv)
369     goto out;
370
371   ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
372   ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
373
374   flags = ipsec_sa_flags_decode (mp->entry.flags);
375
376   ip_address_decode (&mp->entry.tunnel_src, &tun_src);
377   ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
378
379   if (mp->is_add)
380     rv = ipsec_sa_add_and_lock (id, spi, proto,
381                                 crypto_alg, &crypto_key,
382                                 integ_alg, &integ_key, flags,
383                                 0, mp->entry.salt, &tun_src, &tun_dst,
384                                 TUNNEL_ENCAP_DECAP_FLAG_NONE,
385                                 IP_DSCP_CS0,
386                                 &sa_index,
387                                 htons (mp->entry.udp_src_port),
388                                 htons (mp->entry.udp_dst_port));
389   else
390     rv = ipsec_sa_unlock_id (id);
391
392 #else
393   rv = VNET_API_ERROR_UNIMPLEMENTED;
394 #endif
395
396 out:
397   /* *INDENT-OFF* */
398   REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_REPLY,
399   {
400     rmp->stat_index = htonl (sa_index);
401   });
402   /* *INDENT-ON* */
403 }
404
405 static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
406   (vl_api_ipsec_sad_entry_add_del_v2_t * mp)
407 {
408   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
409   vl_api_ipsec_sad_entry_add_del_v2_reply_t *rmp;
410   ip46_address_t tun_src = { }, tun_dst =
411   {
412   };
413   tunnel_encap_decap_flags_t tunnel_flags;
414   ipsec_key_t crypto_key, integ_key;
415   ipsec_crypto_alg_t crypto_alg;
416   ipsec_integ_alg_t integ_alg;
417   ipsec_protocol_t proto;
418   ipsec_sa_flags_t flags;
419   u32 id, spi, sa_index = ~0;
420   int rv;
421
422 #if WITH_LIBSSL > 0
423
424   id = ntohl (mp->entry.sad_id);
425   spi = ntohl (mp->entry.spi);
426
427   rv = ipsec_proto_decode (mp->entry.protocol, &proto);
428
429   if (rv)
430     goto out;
431
432   rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
433
434   if (rv)
435     goto out;
436
437   rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
438
439   if (rv)
440     goto out;
441
442   rv =
443     tunnel_encap_decap_flags_decode (mp->entry.tunnel_flags, &tunnel_flags);
444
445   if (rv)
446     goto out;
447
448   ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
449   ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
450
451   flags = ipsec_sa_flags_decode (mp->entry.flags);
452
453   ip_address_decode (&mp->entry.tunnel_src, &tun_src);
454   ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
455
456   if (mp->is_add)
457     rv = ipsec_sa_add_and_lock (id, spi, proto,
458                                 crypto_alg, &crypto_key,
459                                 integ_alg, &integ_key, flags,
460                                 0, mp->entry.salt, &tun_src, &tun_dst,
461                                 tunnel_flags,
462                                 ip_dscp_decode (mp->entry.dscp),
463                                 &sa_index,
464                                 htons (mp->entry.udp_src_port),
465                                 htons (mp->entry.udp_dst_port));
466   else
467     rv = ipsec_sa_unlock_id (id);
468
469 #else
470   rv = VNET_API_ERROR_UNIMPLEMENTED;
471 #endif
472
473 out:
474   /* *INDENT-OFF* */
475   REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_V2_REPLY,
476   {
477     rmp->stat_index = htonl (sa_index);
478   });
479   /* *INDENT-ON* */
480 }
481
482 static void
483 send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg,
484                          u32 context)
485 {
486   vl_api_ipsec_spds_details_t *mp;
487   u32 n_policies = 0;
488
489   mp = vl_msg_api_alloc (sizeof (*mp));
490   clib_memset (mp, 0, sizeof (*mp));
491   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPDS_DETAILS);
492   mp->context = context;
493
494   mp->spd_id = htonl (spd->id);
495 #define _(s, n) n_policies += vec_len (spd->policies[IPSEC_SPD_POLICY_##s]);
496   foreach_ipsec_spd_policy_type
497 #undef _
498     mp->npolicies = htonl (n_policies);
499
500   vl_api_send_msg (reg, (u8 *) mp);
501 }
502
503 static void
504 vl_api_ipsec_spds_dump_t_handler (vl_api_ipsec_spds_dump_t * mp)
505 {
506   vl_api_registration_t *reg;
507   ipsec_main_t *im = &ipsec_main;
508   ipsec_spd_t *spd;
509 #if WITH_LIBSSL > 0
510   reg = vl_api_client_index_to_registration (mp->client_index);
511   if (!reg)
512     return;
513
514   /* *INDENT-OFF* */
515   pool_foreach (spd, im->spds)  {
516     send_ipsec_spds_details (spd, reg, mp->context);
517   }
518   /* *INDENT-ON* */
519 #else
520   clib_warning ("unimplemented");
521 #endif
522 }
523
524 vl_api_ipsec_spd_action_t
525 ipsec_spd_action_encode (ipsec_policy_action_t in)
526 {
527   vl_api_ipsec_spd_action_t out = IPSEC_API_SPD_ACTION_BYPASS;
528
529   switch (in)
530     {
531 #define _(v,f,s) case IPSEC_POLICY_ACTION_##f: \
532       out = IPSEC_API_SPD_ACTION_##f;          \
533       break;
534       foreach_ipsec_policy_action
535 #undef _
536     }
537   return (clib_host_to_net_u32 (out));
538 }
539
540 static void
541 send_ipsec_spd_details (ipsec_policy_t * p, vl_api_registration_t * reg,
542                         u32 context)
543 {
544   vl_api_ipsec_spd_details_t *mp;
545
546   mp = vl_msg_api_alloc (sizeof (*mp));
547   clib_memset (mp, 0, sizeof (*mp));
548   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
549   mp->context = context;
550
551   mp->entry.spd_id = htonl (p->id);
552   mp->entry.priority = htonl (p->priority);
553   mp->entry.is_outbound = ((p->type == IPSEC_SPD_POLICY_IP6_OUTBOUND) ||
554                            (p->type == IPSEC_SPD_POLICY_IP4_OUTBOUND));
555
556   ip_address_encode (&p->laddr.start, IP46_TYPE_ANY,
557                      &mp->entry.local_address_start);
558   ip_address_encode (&p->laddr.stop, IP46_TYPE_ANY,
559                      &mp->entry.local_address_stop);
560   ip_address_encode (&p->raddr.start, IP46_TYPE_ANY,
561                      &mp->entry.remote_address_start);
562   ip_address_encode (&p->raddr.stop, IP46_TYPE_ANY,
563                      &mp->entry.remote_address_stop);
564   mp->entry.local_port_start = htons (p->lport.start);
565   mp->entry.local_port_stop = htons (p->lport.stop);
566   mp->entry.remote_port_start = htons (p->rport.start);
567   mp->entry.remote_port_stop = htons (p->rport.stop);
568   mp->entry.protocol = p->protocol;
569   mp->entry.policy = ipsec_spd_action_encode (p->policy);
570   mp->entry.sa_id = htonl (p->sa_id);
571
572   vl_api_send_msg (reg, (u8 *) mp);
573 }
574
575 static void
576 vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
577 {
578   vl_api_registration_t *reg;
579   ipsec_main_t *im = &ipsec_main;
580   ipsec_spd_policy_type_t ptype;
581   ipsec_policy_t *policy;
582   ipsec_spd_t *spd;
583   uword *p;
584   u32 spd_index, *ii;
585 #if WITH_LIBSSL > 0
586   reg = vl_api_client_index_to_registration (mp->client_index);
587   if (!reg)
588     return;
589
590   p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
591   if (!p)
592     return;
593
594   spd_index = p[0];
595   spd = pool_elt_at_index (im->spds, spd_index);
596
597   /* *INDENT-OFF* */
598   FOR_EACH_IPSEC_SPD_POLICY_TYPE(ptype) {
599     vec_foreach(ii, spd->policies[ptype])
600       {
601         policy = pool_elt_at_index(im->policies, *ii);
602
603         if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
604           send_ipsec_spd_details (policy, reg, mp->context);
605       }
606   }
607   /* *INDENT-ON* */
608 #else
609   clib_warning ("unimplemented");
610 #endif
611 }
612
613 static void
614 send_ipsec_spd_interface_details (vl_api_registration_t * reg, u32 spd_index,
615                                   u32 sw_if_index, u32 context)
616 {
617   vl_api_ipsec_spd_interface_details_t *mp;
618
619   mp = vl_msg_api_alloc (sizeof (*mp));
620   clib_memset (mp, 0, sizeof (*mp));
621   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_INTERFACE_DETAILS);
622   mp->context = context;
623
624   mp->spd_index = htonl (spd_index);
625   mp->sw_if_index = htonl (sw_if_index);
626
627   vl_api_send_msg (reg, (u8 *) mp);
628 }
629
630 static void
631 vl_api_ipsec_spd_interface_dump_t_handler (vl_api_ipsec_spd_interface_dump_t *
632                                            mp)
633 {
634   ipsec_main_t *im = &ipsec_main;
635   vl_api_registration_t *reg;
636   u32 k, v, spd_index;
637
638 #if WITH_LIBSSL > 0
639   reg = vl_api_client_index_to_registration (mp->client_index);
640   if (!reg)
641     return;
642
643   if (mp->spd_index_valid)
644     {
645       spd_index = ntohl (mp->spd_index);
646       /* *INDENT-OFF* */
647       hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
648         if (v == spd_index)
649           send_ipsec_spd_interface_details(reg, v, k, mp->context);
650       }));
651       /* *INDENT-ON* */
652     }
653   else
654     {
655       /* *INDENT-OFF* */
656       hash_foreach(k, v, im->spd_index_by_sw_if_index, ({
657         send_ipsec_spd_interface_details(reg, v, k, mp->context);
658       }));
659       /* *INDENT-ON* */
660     }
661
662 #else
663   clib_warning ("unimplemented");
664 #endif
665 }
666
667 static void
668 vl_api_ipsec_itf_create_t_handler (vl_api_ipsec_itf_create_t * mp)
669 {
670   vl_api_ipsec_itf_create_reply_t *rmp;
671   tunnel_mode_t mode;
672   u32 sw_if_index = ~0;
673   int rv;
674
675   rv = tunnel_mode_decode (mp->itf.mode, &mode);
676
677   if (!rv)
678     rv = ipsec_itf_create (ntohl (mp->itf.user_instance), mode, &sw_if_index);
679
680   /* *INDENT-OFF* */
681   REPLY_MACRO2 (VL_API_IPSEC_ITF_CREATE_REPLY,
682   ({
683     rmp->sw_if_index = htonl (sw_if_index);
684   }));
685   /* *INDENT-ON* */
686 }
687
688 static void
689 vl_api_ipsec_itf_delete_t_handler (vl_api_ipsec_itf_delete_t * mp)
690 {
691   vl_api_ipsec_itf_delete_reply_t *rmp;
692   int rv;
693
694   rv = ipsec_itf_delete (ntohl (mp->sw_if_index));
695
696   REPLY_MACRO (VL_API_IPSEC_ITF_DELETE_REPLY);
697 }
698
699 static void
700 vl_api_ipsec_itf_dump_t_handler (vl_api_ipsec_itf_dump_t * mp)
701 {
702 }
703
704 typedef struct ipsec_sa_dump_match_ctx_t_
705 {
706   index_t sai;
707   u32 sw_if_index;
708 } ipsec_sa_dump_match_ctx_t;
709
710 static walk_rc_t
711 ipsec_sa_dump_match_sa (index_t itpi, void *arg)
712 {
713   ipsec_sa_dump_match_ctx_t *ctx = arg;
714   ipsec_tun_protect_t *itp;
715   index_t sai;
716
717   itp = ipsec_tun_protect_get (itpi);
718
719   if (itp->itp_out_sa == ctx->sai)
720     {
721       ctx->sw_if_index = itp->itp_sw_if_index;
722       return (WALK_STOP);
723     }
724   /* *INDENT-OFF* */
725   FOR_EACH_IPSEC_PROTECT_INPUT_SAI (itp, sai,
726   ({
727     if (sai == ctx->sai)
728       {
729         ctx->sw_if_index = itp->itp_sw_if_index;
730         return (WALK_STOP);
731       }
732   }));
733   /* *INDENT-OFF* */
734
735   return (WALK_CONTINUE);
736 }
737
738 static walk_rc_t
739 send_ipsec_sa_details (ipsec_sa_t * sa, void *arg)
740 {
741   ipsec_dump_walk_ctx_t *ctx = arg;
742   vl_api_ipsec_sa_details_t *mp;
743   ipsec_main_t *im = &ipsec_main;
744
745   mp = vl_msg_api_alloc (sizeof (*mp));
746   clib_memset (mp, 0, sizeof (*mp));
747   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_DETAILS);
748   mp->context = ctx->context;
749
750   mp->entry.sad_id = htonl (sa->id);
751   mp->entry.spi = htonl (sa->spi);
752   mp->entry.protocol = ipsec_proto_encode (sa->protocol);
753   mp->entry.tx_table_id =
754     htonl (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
755
756   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
757   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
758
759   mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
760   ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
761
762   mp->entry.flags = ipsec_sad_flags_encode (sa);
763   mp->entry.salt = clib_host_to_net_u32 (sa->salt);
764
765   if (ipsec_sa_is_set_IS_PROTECT (sa))
766     {
767       ipsec_sa_dump_match_ctx_t ctx = {
768         .sai = sa - im->sad,
769         .sw_if_index = ~0,
770       };
771       ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
772
773       mp->sw_if_index = htonl (ctx.sw_if_index);
774     }
775   else
776     mp->sw_if_index = ~0;
777
778   if (ipsec_sa_is_set_IS_TUNNEL (sa))
779     {
780       ip_address_encode (&sa->tunnel_src_addr, IP46_TYPE_ANY,
781                          &mp->entry.tunnel_src);
782       ip_address_encode (&sa->tunnel_dst_addr, IP46_TYPE_ANY,
783                          &mp->entry.tunnel_dst);
784     }
785   if (ipsec_sa_is_set_UDP_ENCAP (sa))
786     {
787       mp->entry.udp_src_port = sa->udp_hdr.src_port;
788       mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
789     }
790
791   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
792   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
793   if (ipsec_sa_is_set_USE_ESN (sa))
794     {
795       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
796       mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
797     }
798   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
799     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
800
801   mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
802
803   vl_api_send_msg (ctx->reg, (u8 *) mp);
804
805   return (WALK_CONTINUE);
806 }
807
808 static void
809 vl_api_ipsec_sa_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
810 {
811   vl_api_registration_t *reg;
812
813 #if WITH_LIBSSL > 0
814   reg = vl_api_client_index_to_registration (mp->client_index);
815   if (!reg)
816     return;
817
818   ipsec_dump_walk_ctx_t ctx = {
819     .reg = reg,
820     .context = mp->context,
821   };
822
823   ipsec_sa_walk (send_ipsec_sa_details, &ctx);
824
825 #else
826   clib_warning ("unimplemented");
827 #endif
828 }
829
830 static walk_rc_t
831 send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg)
832 {
833   ipsec_dump_walk_ctx_t *ctx = arg;
834   vl_api_ipsec_sa_v2_details_t *mp;
835   ipsec_main_t *im = &ipsec_main;
836
837   mp = vl_msg_api_alloc (sizeof (*mp));
838   clib_memset (mp, 0, sizeof (*mp));
839   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_V2_DETAILS);
840   mp->context = ctx->context;
841
842   mp->entry.sad_id = htonl (sa->id);
843   mp->entry.spi = htonl (sa->spi);
844   mp->entry.protocol = ipsec_proto_encode (sa->protocol);
845   mp->entry.tx_table_id =
846     htonl (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
847
848   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
849   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
850
851   mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
852   ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
853
854   mp->entry.flags = ipsec_sad_flags_encode (sa);
855   mp->entry.salt = clib_host_to_net_u32 (sa->salt);
856
857   if (ipsec_sa_is_set_IS_PROTECT (sa))
858     {
859       ipsec_sa_dump_match_ctx_t ctx = {
860         .sai = sa - im->sad,
861         .sw_if_index = ~0,
862       };
863       ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
864
865       mp->sw_if_index = htonl (ctx.sw_if_index);
866     }
867   else
868     mp->sw_if_index = ~0;
869
870   if (ipsec_sa_is_set_IS_TUNNEL (sa))
871     {
872       ip_address_encode (&sa->tunnel_src_addr, IP46_TYPE_ANY,
873                          &mp->entry.tunnel_src);
874       ip_address_encode (&sa->tunnel_dst_addr, IP46_TYPE_ANY,
875                          &mp->entry.tunnel_dst);
876     }
877   if (ipsec_sa_is_set_UDP_ENCAP (sa))
878     {
879       mp->entry.udp_src_port = sa->udp_hdr.src_port;
880       mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
881     }
882
883   mp->entry.tunnel_flags = tunnel_encap_decap_flags_encode (sa->tunnel_flags);
884   mp->entry.dscp = ip_dscp_encode (sa->dscp);
885
886   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
887   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
888   if (ipsec_sa_is_set_USE_ESN (sa))
889     {
890       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
891       mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
892     }
893   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
894     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
895
896   mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
897
898   vl_api_send_msg (ctx->reg, (u8 *) mp);
899
900   return (WALK_CONTINUE);
901 }
902
903 static void
904 vl_api_ipsec_sa_v2_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
905 {
906   vl_api_registration_t *reg;
907
908 #if WITH_LIBSSL > 0
909   reg = vl_api_client_index_to_registration (mp->client_index);
910   if (!reg)
911     return;
912
913   ipsec_dump_walk_ctx_t ctx = {
914     .reg = reg,
915     .context = mp->context,
916   };
917
918   ipsec_sa_walk (send_ipsec_sa_v2_details, &ctx);
919
920 #else
921   clib_warning ("unimplemented");
922 #endif
923 }
924
925 static void
926 vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp)
927 {
928   vl_api_registration_t *rp;
929   ipsec_main_t *im = &ipsec_main;
930   u32 context = mp->context;
931
932   rp = vl_api_client_index_to_registration (mp->client_index);
933
934   if (rp == 0)
935     {
936       clib_warning ("Client %d AWOL", mp->client_index);
937       return;
938     }
939
940   ipsec_ah_backend_t *ab;
941   ipsec_esp_backend_t *eb;
942   /* *INDENT-OFF* */
943   pool_foreach (ab, im->ah_backends) {
944     vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
945     clib_memset (mp, 0, sizeof (*mp));
946     mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
947     mp->context = context;
948     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (ab->name),
949               ab->name);
950     mp->protocol = ntohl (IPSEC_API_PROTO_AH);
951     mp->index = ab - im->ah_backends;
952     mp->active = mp->index == im->ah_current_backend ? 1 : 0;
953     vl_api_send_msg (rp, (u8 *)mp);
954   }
955   pool_foreach (eb, im->esp_backends) {
956     vl_api_ipsec_backend_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
957     clib_memset (mp, 0, sizeof (*mp));
958     mp->_vl_msg_id = ntohs (VL_API_IPSEC_BACKEND_DETAILS);
959     mp->context = context;
960     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (eb->name),
961               eb->name);
962     mp->protocol = ntohl (IPSEC_API_PROTO_ESP);
963     mp->index = eb - im->esp_backends;
964     mp->active = mp->index == im->esp_current_backend ? 1 : 0;
965     vl_api_send_msg (rp, (u8 *)mp);
966   }
967   /* *INDENT-ON* */
968 }
969
970 static void
971 vl_api_ipsec_select_backend_t_handler (vl_api_ipsec_select_backend_t * mp)
972 {
973   ipsec_main_t *im = &ipsec_main;
974   vl_api_ipsec_select_backend_reply_t *rmp;
975   ipsec_protocol_t protocol;
976   int rv = 0;
977   if (pool_elts (im->sad) > 0)
978     {
979       rv = VNET_API_ERROR_INSTANCE_IN_USE;
980       goto done;
981     }
982
983   rv = ipsec_proto_decode (mp->protocol, &protocol);
984
985   if (rv)
986     goto done;
987
988 #if WITH_LIBSSL > 0
989   switch (protocol)
990     {
991     case IPSEC_PROTOCOL_ESP:
992       rv = ipsec_select_esp_backend (im, mp->index);
993       break;
994     case IPSEC_PROTOCOL_AH:
995       rv = ipsec_select_ah_backend (im, mp->index);
996       break;
997     default:
998       rv = VNET_API_ERROR_INVALID_PROTOCOL;
999       break;
1000     }
1001 #else
1002   clib_warning ("unimplemented");       /* FIXME */
1003 #endif
1004 done:
1005   REPLY_MACRO (VL_API_IPSEC_SELECT_BACKEND_REPLY);
1006 }
1007
1008 static void
1009 vl_api_ipsec_set_async_mode_t_handler (vl_api_ipsec_set_async_mode_t * mp)
1010 {
1011   vl_api_ipsec_set_async_mode_reply_t *rmp;
1012   int rv = 0;
1013
1014   vnet_crypto_request_async_mode (mp->async_enable);
1015   ipsec_set_async_mode (mp->async_enable);
1016
1017   REPLY_MACRO (VL_API_IPSEC_SET_ASYNC_MODE_REPLY);
1018 }
1019
1020 /*
1021  * ipsec_api_hookup
1022  * Add vpe's API message handlers to the table.
1023  * vlib has already mapped shared memory and
1024  * added the client registration handlers.
1025  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
1026  */
1027 #define vl_msg_name_crc_list
1028 #include <vnet/vnet_all_api_h.h>
1029 #undef vl_msg_name_crc_list
1030
1031 static void
1032 setup_message_id_table (api_main_t * am)
1033 {
1034 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
1035   foreach_vl_msg_name_crc_ipsec;
1036 #undef _
1037 }
1038
1039 static clib_error_t *
1040 ipsec_api_hookup (vlib_main_t * vm)
1041 {
1042   api_main_t *am = vlibapi_get_main ();
1043
1044 #define _(N,n)                                                  \
1045     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
1046                            vl_api_##n##_t_handler,              \
1047                            vl_noop_handler,                     \
1048                            vl_api_##n##_t_endian,               \
1049                            vl_api_##n##_t_print,                \
1050                            sizeof(vl_api_##n##_t), 1);
1051   foreach_vpe_api_msg;
1052 #undef _
1053
1054   /*
1055    * Set up the (msg_name, crc, message-id) table
1056    */
1057   setup_message_id_table (am);
1058
1059   return 0;
1060 }
1061
1062 VLIB_API_INIT_FUNCTION (ipsec_api_hookup);
1063
1064 /*
1065  * fd.io coding-style-patch-verification: ON
1066  *
1067  * Local Variables:
1068  * eval: (c-set-style "gnu")
1069  * End:
1070  */