uint32_t reqid;
/** destination address (wildcard case) */
host_t *dst;
- /** security label, if any */
- sec_label_t *label;
- /** sequence number from the kernel or generated by the trap manager */
- uint32_t seq;
+ /** data from the kernel */
+ kernel_acquire_data_t *data;
/** optional sequence number from the kernel if an acquire is retriggered */
uint32_t new_seq;
} acquire_t;
static void destroy_acquire(acquire_t *this)
{
DESTROY_IF(this->dst);
- DESTROY_IF(this->label);
+ kernel_acquire_data_destroy(this->data);
free(this);
}
sec_label_t *label;
VA_ARGS_VGET(args, reqid, label);
- return this->reqid == reqid && sec_labels_equal(this->label, label);
+ return this->reqid == reqid && sec_labels_equal(this->data->label, label);
}
CALLBACK(acquire_by_dst, bool,
child_cfg_t *child;
ike_sa_t *ike_sa;
host_t *host = NULL;
- sec_label_t *label = NULL;
uint32_t allocated_reqid, seq = 0;
bool wildcard;
host->destroy(host);
}
}
- else if (!this->acquires->find_first(this->acquires, acquire_by_reqid,
- (void**)&acquire, reqid, data->label))
+ else
{
- label = data->label ? data->label->clone(data->label) : NULL;
+ this->acquires->find_first(this->acquires, acquire_by_reqid,
+ (void**)&acquire, reqid, data->label);
}
if (!acquire)
{
- seq = data->seq ?: ref_get_nonzero(&this->acquire_seq);
-
INIT(acquire,
.dst = host,
.reqid = reqid,
- .label = label,
- .seq = seq,
+ .data = kernel_acquire_data_clone(data),
);
+ seq = data->seq = data->seq ?: ref_get_nonzero(&this->acquire_seq);
this->acquires->insert_last(this->acquires, acquire);
}
- else if (data->seq && acquire->seq != data->seq)
+ else if (data->seq && data->seq != acquire->data->seq)
{
/* acquire got retriggered, update to latest sequence number */
acquire->new_seq = data->seq;
acquire_t *acquire;
uint32_t seq;
- /* ignore trap policies and CHILD_SAs not triggered by an acquire */
- if (!ike_sa || !(seq = child_sa->get_acquire_seq(child_sa)))
+ /* ignore trap policies */
+ if (!ike_sa)
+ {
+ return;
+ }
+ /* if a CHILD_SA was not triggered by an acquire (e.g. manually or via
+ * start action) and the kernel supports sequence numbers, we check if the
+ * negotiated TS match the triggering packet and set the sequence number
+ * to remove the temporary state in the kernel */
+ seq = child_sa->get_acquire_seq(child_sa);
+ if (!seq &&
+ !(charon->kernel->get_features(charon->kernel) & KERNEL_ACQUIRE_SEQ))
{
return;
}
enumerator = this->acquires->create_enumerator(this->acquires);
while (enumerator->enumerate(enumerator, &acquire))
{
- if (!acquire->ike_sa || seq != acquire->seq)
+ if (!seq)
+ {
+ /* if not triggered by an acquire, compare the TS from the packet
+ * that triggered the current acquire, set the seq if they match */
+ if (!child_sa_ts_match(child_sa, acquire->data->src,
+ acquire->data->dst))
+ {
+ continue;
+ }
+ child_sa->set_acquire_seq(child_sa, acquire->data->seq);
+ }
+ else if (!acquire->ike_sa || seq != acquire->data->seq)
{
continue;
}
if (acquire->new_seq)
{
child_sa->set_acquire_seq(child_sa, acquire->new_seq);
- acquire->seq = acquire->new_seq;
+ acquire->data->seq = acquire->new_seq;
acquire->new_seq = 0;
}
break;
{
/* just look at the sequence number when handling a CHILD_SA event,
* otherwise, compare the IKE_SA */
- if (!acquire->ike_sa || (seq && seq != acquire->seq) ||
+ if (!acquire->ike_sa || (seq && seq != acquire->data->seq) ||
(!seq && acquire->ike_sa != ike_sa))
{
continue;