/* search by reqid if given */
entry = this->reqids->get(this->reqids, tmpl);
}
- if (entry && entry_equals_selectors(entry, tmpl))
+
+ /* if the IPsec stack supports sequence numbers for acquires, we can
+ * allocate a new reqid if narrowing occurred (otherwise, we get the same
+ * reqid back anyway). if not, we want to reuse the existing reqid of
+ * the trap polices and explicitly don't want to match the traffic
+ * selectors. another case where we want to reuse an existing reqid is
+ * when labels are used. because we currently only install policies once
+ * with the generic label, the reqid has to stay the same even if narrowing
+ * occurs. however, in either case we don't want to reuse the reqid if the
+ * additional selectors (e.g. marks) are different */
+ if (entry && (label || !(get_features(this) & KERNEL_ACQUIRE_SEQ)) &&
+ entry_equals_selectors(entry, tmpl))
{
- /* we don't require a traffic selector match for existing reqids,
- * as we want to reuse a reqid for trap-triggered policies that
- * got narrowed during negotiation, but we don't want to reuse the
- * reqid if the additional selectors (e.g. marks) are different */
reqid_entry_destroy(tmpl);
}
else
KERNEL_POLICY_SPI = (1<<4),
/** IPsec backend reports use time per SA via query_sa() */
KERNEL_SA_USE_TIME = (1<<5),
+ /** IPsec backend associates acquires and SAs with a sequence number */
+ KERNEL_ACQUIRE_SEQ = (1<<6),
};
/**
if (!this->reqid)
{
/* reuse old reqid if we are rekeying an existing CHILD_SA and when
- * initiating a trap policy. While the reqid cache would find the same
- * reqid for our selectors, this does not work in a special case: If an
- * SA is triggered by a trap policy, but the negotiated TS get
- * narrowed, we still must reuse the same reqid to successfully
- * replace the temporary SA on the kernel level. Rekeying such an SA
- * requires an explicit reqid, as the cache currently knows the original
- * selectors only for that reqid. */
+ * initiating a trap policy. the reqid cache will generally find the
+ * same reqid for our selectors. but this does not work in a special
+ * case: if the IPsec stack does not use sequence numbers for acquires,
+ * an SA is triggered by a trap policy and the negotiated TS get
+ * narrowed, we still must reuse the same reqid to successfully replace
+ * the temporary SA on the kernel level. however, if sequence numbers
+ * are supported, the reqid will later get updated in case of narrowing
+ * when alloc_reqid() is called */
if (data->reqid &&
charon->kernel->ref_reqid(charon->kernel, data->reqid) == SUCCESS)
{