diff options
Diffstat (limited to 'extras/strongswan')
-rw-r--r-- | extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c b/extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c index 3fe3c4403e2..2a0d86d7ef0 100644 --- a/extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c +++ b/extras/strongswan/vpp_sswan/kernel_vpp_ipsec.c @@ -500,6 +500,22 @@ sa_equals (kernel_ipsec_sa_id_t *sa, kernel_ipsec_sa_id_t *other_sa) } /** + * Equality function for policy SPD + */ +static bool +policy_equals (vl_api_ipsec_spd_entry_t *policy, + vl_api_ipsec_spd_entry_t *other_policy) +{ + + /* change protocol due to legacy implementation of ANY protocol inside VPP */ + if (other_policy->protocol == 255) + other_policy->protocol = 0; + + /* return true if both policies are equal */ + return !memcmp (policy, other_policy, sizeof (*policy)); +} + +/** * Hash function for interface */ static u_int @@ -1111,6 +1127,49 @@ manage_policy (private_kernel_vpp_ipsec_t *this, bool add, mp->entry.remote_port_start = htons (id->dst_ts->get_from_port (id->dst_ts)); mp->entry.remote_port_stop = htons (id->dst_ts->get_to_port (id->dst_ts)); + /* check if policy exists in SPD */ + vl_api_ipsec_spd_dump_t *mp_dump; + vl_api_ipsec_spd_details_t *rmp_dump, *tmp; + + mp_dump = vl_msg_api_alloc (sizeof (*mp_dump)); + memset (mp_dump, 0, sizeof (*mp_dump)); + + msg_id = vl_msg_api_get_msg_index ((u8 *) "ipsec_spd_dump_afefbf7d"); + mp_dump->_vl_msg_id = htons (msg_id); + mp_dump->spd_id = htonl (spd->spd_id); + mp_dump->sa_id = htonl (sad_id); + + if (vac->send_dump (vac, (char *) mp_dump, sizeof (*mp_dump), &out, + &out_len)) + { + DBG1 (DBG_KNL, "vac %s SPD lookup failed", add ? "adding" : "removing"); + goto error; + } + + int num = out_len / sizeof (*rmp_dump); + tmp = (void *) out; + + /* found existing policy */ + if (add && num) + { + int i; + for (i = 0; i < num; i++) + { + rmp_dump = tmp; + tmp += 1; + /* check if found entry equals the new one */ + if (policy_equals (&mp->entry, &rmp_dump->entry)) + goto next; + } + } + else if (!add && num == 0) + { + /* VPP doesn't have any policy to delete */ + goto next; + } + + free (out); + if (vac->send (vac, (char *) mp, sizeof (*mp), &out, &out_len)) { DBG1 (DBG_KNL, "vac %s SPD entry failed", add ? "adding" : "removing"); @@ -1124,6 +1183,7 @@ manage_policy (private_kernel_vpp_ipsec_t *this, bool add, goto error; } +next: if (add) { ref_get (&spd->policy_num); @@ -1153,6 +1213,7 @@ manage_policy (private_kernel_vpp_ipsec_t *this, bool add, rv = SUCCESS; error: free (out); + vl_msg_api_free (mp_dump); vl_msg_api_free (mp); this->mutex->unlock (this->mutex); return rv; |