Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== 1) Initialize the satype field in key_notify_policy_flush(), this was left uninitialized. From Nicolas Dichtel. 2) The sequence number difference for replay notifications was misscalculated on ESN sequence number wrap. We need a separate replay notify function for esn. 3) Fix an off by one in the esn replay notify function. From Mathias Krause. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
0fb031f036
2 changed files with 66 additions and 1 deletions
|
@ -2693,6 +2693,7 @@ static int key_notify_policy_flush(const struct km_event *c)
|
|||
hdr->sadb_msg_pid = c->portid;
|
||||
hdr->sadb_msg_version = PF_KEY_V2;
|
||||
hdr->sadb_msg_errno = (uint8_t) 0;
|
||||
hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
|
||||
hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
|
||||
pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
|
||||
return 0;
|
||||
|
|
|
@ -334,6 +334,70 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
|
|||
x->xflags &= ~XFRM_TIME_DEFER;
|
||||
}
|
||||
|
||||
static void xfrm_replay_notify_esn(struct xfrm_state *x, int event)
|
||||
{
|
||||
u32 seq_diff, oseq_diff;
|
||||
struct km_event c;
|
||||
struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
|
||||
struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
|
||||
|
||||
/* we send notify messages in case
|
||||
* 1. we updated on of the sequence numbers, and the seqno difference
|
||||
* is at least x->replay_maxdiff, in this case we also update the
|
||||
* timeout of our timer function
|
||||
* 2. if x->replay_maxage has elapsed since last update,
|
||||
* and there were changes
|
||||
*
|
||||
* The state structure must be locked!
|
||||
*/
|
||||
|
||||
switch (event) {
|
||||
case XFRM_REPLAY_UPDATE:
|
||||
if (!x->replay_maxdiff)
|
||||
break;
|
||||
|
||||
if (replay_esn->seq_hi == preplay_esn->seq_hi)
|
||||
seq_diff = replay_esn->seq - preplay_esn->seq;
|
||||
else
|
||||
seq_diff = ~preplay_esn->seq + replay_esn->seq + 1;
|
||||
|
||||
if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
|
||||
oseq_diff = replay_esn->oseq - preplay_esn->oseq;
|
||||
else
|
||||
oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1;
|
||||
|
||||
if (seq_diff < x->replay_maxdiff &&
|
||||
oseq_diff < x->replay_maxdiff) {
|
||||
|
||||
if (x->xflags & XFRM_TIME_DEFER)
|
||||
event = XFRM_REPLAY_TIMEOUT;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case XFRM_REPLAY_TIMEOUT:
|
||||
if (memcmp(x->replay_esn, x->preplay_esn,
|
||||
xfrm_replay_state_esn_len(replay_esn)) == 0) {
|
||||
x->xflags |= XFRM_TIME_DEFER;
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(x->preplay_esn, x->replay_esn,
|
||||
xfrm_replay_state_esn_len(replay_esn));
|
||||
c.event = XFRM_MSG_NEWAE;
|
||||
c.data.aevent = event;
|
||||
km_state_notify(x, &c);
|
||||
|
||||
if (x->replay_maxage &&
|
||||
!mod_timer(&x->rtimer, jiffies + x->replay_maxage))
|
||||
x->xflags &= ~XFRM_TIME_DEFER;
|
||||
}
|
||||
|
||||
static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
int err = 0;
|
||||
|
@ -510,7 +574,7 @@ static struct xfrm_replay xfrm_replay_esn = {
|
|||
.advance = xfrm_replay_advance_esn,
|
||||
.check = xfrm_replay_check_esn,
|
||||
.recheck = xfrm_replay_recheck_esn,
|
||||
.notify = xfrm_replay_notify_bmp,
|
||||
.notify = xfrm_replay_notify_esn,
|
||||
.overflow = xfrm_replay_overflow_esn,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue