LCOV - code coverage report
Current view: top level - vnet/ipsec - ipsec_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 421 598 70.4 %
Date: 2023-07-05 22:20:52 Functions: 38 44 86.4 %

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

Generated by: LCOV version 1.14