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