ipsec: fix coverity 249204
[vpp.git] / src / vnet / ipsec / ipsec_api.c
index a0c2768..767dc82 100644 (file)
@@ -124,6 +124,7 @@ typedef struct ipsec_dump_walk_ctx_t_
 {
   vl_api_registration_t *reg;
   u32 context;
+  u32 sw_if_index;
 } ipsec_dump_walk_ctx_t;
 
 static walk_rc_t
@@ -232,7 +233,8 @@ static void vl_api_ipsec_spd_entry_add_del_t_handler
 
   p.is_ipv6 = (itype == IP46_TYPE_IP6);
 
-  p.protocol = mp->entry.protocol;
+  p.protocol =
+    mp->entry.protocol ? mp->entry.protocol : IPSEC_POLICY_PROTOCOL_ANY;
   p.rport.start = ntohs (mp->entry.remote_port_start);
   p.rport.stop = ntohs (mp->entry.remote_port_stop);
   p.lport.start = ntohs (mp->entry.local_port_start);
@@ -270,6 +272,65 @@ out:
   /* *INDENT-ON* */
 }
 
+static void
+vl_api_ipsec_spd_entry_add_del_v2_t_handler (
+  vl_api_ipsec_spd_entry_add_del_v2_t *mp)
+{
+  vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
+  vl_api_ipsec_spd_entry_add_del_reply_t *rmp;
+  ip46_type_t itype;
+  u32 stat_index;
+  int rv;
+
+  stat_index = ~0;
+
+  ipsec_policy_t p;
+
+  clib_memset (&p, 0, sizeof (p));
+
+  p.id = ntohl (mp->entry.spd_id);
+  p.priority = ntohl (mp->entry.priority);
+
+  itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start);
+  ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop);
+  ip_address_decode (&mp->entry.local_address_start, &p.laddr.start);
+  ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop);
+
+  p.is_ipv6 = (itype == IP46_TYPE_IP6);
+
+  p.protocol = mp->entry.protocol;
+  p.rport.start = ntohs (mp->entry.remote_port_start);
+  p.rport.stop = ntohs (mp->entry.remote_port_stop);
+  p.lport.start = ntohs (mp->entry.local_port_start);
+  p.lport.stop = ntohs (mp->entry.local_port_stop);
+
+  rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
+
+  if (rv)
+    goto out;
+
+  /* policy action resolve unsupported */
+  if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
+    {
+      clib_warning ("unsupported action: 'resolve'");
+      rv = VNET_API_ERROR_UNIMPLEMENTED;
+      goto out;
+    }
+  p.sa_id = ntohl (mp->entry.sa_id);
+  rv =
+    ipsec_policy_mk_type (mp->entry.is_outbound, p.is_ipv6, p.policy, &p.type);
+  if (rv)
+    goto out;
+
+  rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index);
+  if (rv)
+    goto out;
+
+out:
+  REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY,
+               ({ rmp->stat_index = ntohl (stat_index); }));
+}
+
 static void vl_api_ipsec_sad_entry_add_del_t_handler
   (vl_api_ipsec_sad_entry_add_del_t * mp)
 {
@@ -291,6 +352,11 @@ static void vl_api_ipsec_sad_entry_add_del_t_handler
   int rv;
 
   id = ntohl (mp->entry.sad_id);
+  if (!mp->is_add)
+    {
+      rv = ipsec_sa_unlock_id (id);
+      goto out;
+    }
   spi = ntohl (mp->entry.spi);
 
   rv = ipsec_proto_decode (mp->entry.protocol, &proto);
@@ -316,13 +382,10 @@ static void vl_api_ipsec_sad_entry_add_del_t_handler
   ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src);
   ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst);
 
-  if (mp->is_add)
-    rv = ipsec_sa_add_and_lock (
-      id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags,
-      mp->entry.salt, htons (mp->entry.udp_src_port),
-      htons (mp->entry.udp_dst_port), &tun, &sa_index);
-  else
-    rv = ipsec_sa_unlock_id (id);
+  rv = ipsec_sa_add_and_lock (id, spi, proto, crypto_alg, &crypto_key,
+                             integ_alg, &integ_key, flags, mp->entry.salt,
+                             htons (mp->entry.udp_src_port),
+                             htons (mp->entry.udp_dst_port), &tun, &sa_index);
 
 out:
   /* *INDENT-OFF* */
@@ -355,6 +418,12 @@ static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
   };
 
   id = ntohl (mp->entry.sad_id);
+  if (!mp->is_add)
+    {
+      rv = ipsec_sa_unlock_id (id);
+      goto out;
+    }
+
   spi = ntohl (mp->entry.spi);
 
   rv = ipsec_proto_decode (mp->entry.protocol, &proto);
@@ -387,13 +456,10 @@ static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
   ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src);
   ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst);
 
-  if (mp->is_add)
     rv = ipsec_sa_add_and_lock (
       id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags,
       mp->entry.salt, htons (mp->entry.udp_src_port),
       htons (mp->entry.udp_dst_port), &tun, &sa_index);
-  else
-    rv = ipsec_sa_unlock_id (id);
 
 out:
   /* *INDENT-OFF* */
@@ -404,64 +470,103 @@ out:
   /* *INDENT-ON* */
 }
 
-static void
-vl_api_ipsec_sad_entry_add_del_v3_t_handler (
-  vl_api_ipsec_sad_entry_add_del_v3_t *mp)
+static int
+ipsec_sad_entry_add_v3 (const vl_api_ipsec_sad_entry_v3_t *entry,
+                       u32 *sa_index)
 {
-  vl_api_ipsec_sad_entry_add_del_v3_reply_t *rmp;
   ipsec_key_t crypto_key, integ_key;
   ipsec_crypto_alg_t crypto_alg;
   ipsec_integ_alg_t integ_alg;
   ipsec_protocol_t proto;
   ipsec_sa_flags_t flags;
-  u32 id, spi, sa_index = ~0;
-  tunnel_t tun;
+  u32 id, spi;
+  tunnel_t tun = { 0 };
   int rv;
 
-  id = ntohl (mp->entry.sad_id);
-  spi = ntohl (mp->entry.spi);
+  id = ntohl (entry->sad_id);
+  spi = ntohl (entry->spi);
 
-  rv = ipsec_proto_decode (mp->entry.protocol, &proto);
+  rv = ipsec_proto_decode (entry->protocol, &proto);
 
   if (rv)
-    goto out;
+    return (rv);
 
-  rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
+  rv = ipsec_crypto_algo_decode (entry->crypto_algorithm, &crypto_alg);
 
   if (rv)
-    goto out;
+    return (rv);
 
-  rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
+  rv = ipsec_integ_algo_decode (entry->integrity_algorithm, &integ_alg);
 
   if (rv)
-    goto out;
+    return (rv);
 
-  flags = ipsec_sa_flags_decode (mp->entry.flags);
+  flags = ipsec_sa_flags_decode (entry->flags);
 
   if (flags & IPSEC_SA_FLAG_IS_TUNNEL)
     {
-      rv = tunnel_decode (&mp->entry.tunnel, &tun);
+      rv = tunnel_decode (&entry->tunnel, &tun);
 
       if (rv)
-       goto out;
+       return (rv);
     }
 
-  ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
-  ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
+  ipsec_key_decode (&entry->crypto_key, &crypto_key);
+  ipsec_key_decode (&entry->integrity_key, &integ_key);
 
-  if (mp->is_add)
-    rv = ipsec_sa_add_and_lock (
-      id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags,
-      mp->entry.salt, htons (mp->entry.udp_src_port),
-      htons (mp->entry.udp_dst_port), &tun, &sa_index);
+  return ipsec_sa_add_and_lock (id, spi, proto, crypto_alg, &crypto_key,
+                               integ_alg, &integ_key, flags, entry->salt,
+                               htons (entry->udp_src_port),
+                               htons (entry->udp_dst_port), &tun, sa_index);
+}
+
+static void
+vl_api_ipsec_sad_entry_add_del_v3_t_handler (
+  vl_api_ipsec_sad_entry_add_del_v3_t *mp)
+{
+  vl_api_ipsec_sad_entry_add_del_v3_reply_t *rmp;
+  u32 id, sa_index = ~0;
+  int rv;
+
+  id = ntohl (mp->entry.sad_id);
+
+  if (!mp->is_add)
+    {
+      rv = ipsec_sa_unlock_id (id);
+    }
   else
-    rv = ipsec_sa_unlock_id (id);
+    {
+      rv = ipsec_sad_entry_add_v3 (&mp->entry, &sa_index);
+    }
 
-out:
   REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_V3_REPLY,
                { rmp->stat_index = htonl (sa_index); });
 }
 
+static void
+vl_api_ipsec_sad_entry_del_t_handler (vl_api_ipsec_sad_entry_del_t *mp)
+{
+  vl_api_ipsec_sad_entry_del_reply_t *rmp;
+  int rv;
+
+  rv = ipsec_sa_unlock_id (ntohl (mp->id));
+
+  REPLY_MACRO (VL_API_IPSEC_SAD_ENTRY_DEL_REPLY);
+}
+
+static void
+vl_api_ipsec_sad_entry_add_t_handler (vl_api_ipsec_sad_entry_add_t *mp)
+{
+  vl_api_ipsec_sad_entry_add_reply_t *rmp;
+  u32 sa_index = ~0;
+  int rv;
+
+  rv = ipsec_sad_entry_add_v3 (&mp->entry, &sa_index);
+
+  REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_REPLY,
+               { rmp->stat_index = htonl (sa_index); });
+}
+
 static void
 send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg,
                         u32 context)
@@ -669,6 +774,9 @@ send_ipsec_itf_details (ipsec_itf_t *itf, void *arg)
   ipsec_dump_walk_ctx_t *ctx = arg;
   vl_api_ipsec_itf_details_t *mp;
 
+  if (~0 != ctx->sw_if_index && ctx->sw_if_index != itf->ii_sw_if_index)
+    return (WALK_CONTINUE);
+
   mp = vl_msg_api_alloc (sizeof (*mp));
   clib_memset (mp, 0, sizeof (*mp));
   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_IPSEC_ITF_DETAILS);
@@ -694,6 +802,7 @@ vl_api_ipsec_itf_dump_t_handler (vl_api_ipsec_itf_dump_t * mp)
   ipsec_dump_walk_ctx_t ctx = {
     .reg = reg,
     .context = mp->context,
+    .sw_if_index = ntohl (mp->sw_if_index),
   };
 
   ipsec_itf_walk (send_ipsec_itf_details, &ctx);
@@ -782,11 +891,11 @@ send_ipsec_sa_details (ipsec_sa_t * sa, void *arg)
     }
 
   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
-  mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
+  mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
   if (ipsec_sa_is_set_USE_ESN (sa))
     {
       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
-      mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
+      mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
     }
   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
@@ -869,11 +978,11 @@ send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg)
   mp->entry.dscp = ip_dscp_encode (sa->tunnel.t_dscp);
 
   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
-  mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
+  mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
   if (ipsec_sa_is_set_USE_ESN (sa))
     {
       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
-      mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
+      mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
     }
   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
@@ -949,11 +1058,11 @@ send_ipsec_sa_v3_details (ipsec_sa_t *sa, void *arg)
     }
 
   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
-  mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
+  mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->seq));
   if (ipsec_sa_is_set_USE_ESN (sa))
     {
       mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
-      mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
+      mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
     }
   if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
     mp->replay_window = clib_host_to_net_u64 (sa->replay_window);