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