diff options
author | Thomas Egerer <thomas.egerer@secunet.com> | 2013-09-19 07:19:19 -0400 |
---|---|---|
committer | Steffen Klassert <steffen.klassert@secunet.com> | 2013-09-25 01:32:48 -0400 |
commit | cd808fc9a6c7cd3a4311d9d2cffc4adbeaef5f6c (patch) | |
tree | 82279120c03e0980a1da1f22beba85ee97a228f2 /net/xfrm | |
parent | 33fce60d6a6e137035f8e23a89d7fd55f3a24cda (diff) |
xfrm: Fix aevent generation for each received packet
If asynchronous events are enabled for a particular netlink socket,
the notify function is called by the advance function. The notify
function creates and dispatches a km_event if a replay timeout occurred,
or at least replay_maxdiff packets have been received since the last
asynchronous event has been sent. The function is supposed to return if
neither of the two events were detected for a state, or replay_maxdiff
is equal to zero.
Replay_maxdiff is initialized in xfrm_state_construct to the value of
the xfrm.sysctl_aevent_rseqth (2 by default), and updated if for a state
if the netlink attribute XFRMA_REPLAY_THRESH is set.
If, however, replay_maxdiff is set to zero, then all of the three notify
implementations perform a break from the switch statement instead of
checking whether a timeout occurred, and -- if not -- return. As a
result an asynchronous event is generated for every replay update of a
state that has a zero replay_maxdiff value.
This patch modifies the notify functions such that they immediately
return if replay_maxdiff has the value zero, unless a timeout occurred.
Signed-off-by: Thomas Egerer <thomas.egerer@secunet.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_replay.c | 51 |
1 files changed, 27 insertions, 24 deletions
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index eeca388effc7..dab57daae408 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
@@ -61,9 +61,9 @@ static void xfrm_replay_notify(struct xfrm_state *x, int event) | |||
61 | 61 | ||
62 | switch (event) { | 62 | switch (event) { |
63 | case XFRM_REPLAY_UPDATE: | 63 | case XFRM_REPLAY_UPDATE: |
64 | if (x->replay_maxdiff && | 64 | if (!x->replay_maxdiff || |
65 | (x->replay.seq - x->preplay.seq < x->replay_maxdiff) && | 65 | ((x->replay.seq - x->preplay.seq < x->replay_maxdiff) && |
66 | (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) { | 66 | (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))) { |
67 | if (x->xflags & XFRM_TIME_DEFER) | 67 | if (x->xflags & XFRM_TIME_DEFER) |
68 | event = XFRM_REPLAY_TIMEOUT; | 68 | event = XFRM_REPLAY_TIMEOUT; |
69 | else | 69 | else |
@@ -301,9 +301,10 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event) | |||
301 | 301 | ||
302 | switch (event) { | 302 | switch (event) { |
303 | case XFRM_REPLAY_UPDATE: | 303 | case XFRM_REPLAY_UPDATE: |
304 | if (x->replay_maxdiff && | 304 | if (!x->replay_maxdiff || |
305 | (replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) && | 305 | ((replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) && |
306 | (replay_esn->oseq - preplay_esn->oseq < x->replay_maxdiff)) { | 306 | (replay_esn->oseq - preplay_esn->oseq |
307 | < x->replay_maxdiff))) { | ||
307 | if (x->xflags & XFRM_TIME_DEFER) | 308 | if (x->xflags & XFRM_TIME_DEFER) |
308 | event = XFRM_REPLAY_TIMEOUT; | 309 | event = XFRM_REPLAY_TIMEOUT; |
309 | else | 310 | else |
@@ -352,28 +353,30 @@ static void xfrm_replay_notify_esn(struct xfrm_state *x, int event) | |||
352 | 353 | ||
353 | switch (event) { | 354 | switch (event) { |
354 | case XFRM_REPLAY_UPDATE: | 355 | case XFRM_REPLAY_UPDATE: |
355 | if (!x->replay_maxdiff) | 356 | if (x->replay_maxdiff) { |
356 | break; | 357 | if (replay_esn->seq_hi == preplay_esn->seq_hi) |
357 | 358 | seq_diff = replay_esn->seq - preplay_esn->seq; | |
358 | if (replay_esn->seq_hi == preplay_esn->seq_hi) | 359 | else |
359 | seq_diff = replay_esn->seq - preplay_esn->seq; | 360 | seq_diff = ~preplay_esn->seq + replay_esn->seq |
360 | else | 361 | + 1; |
361 | seq_diff = ~preplay_esn->seq + replay_esn->seq + 1; | ||
362 | |||
363 | if (replay_esn->oseq_hi == preplay_esn->oseq_hi) | ||
364 | oseq_diff = replay_esn->oseq - preplay_esn->oseq; | ||
365 | else | ||
366 | oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1; | ||
367 | |||
368 | if (seq_diff < x->replay_maxdiff && | ||
369 | oseq_diff < x->replay_maxdiff) { | ||
370 | 362 | ||
371 | if (x->xflags & XFRM_TIME_DEFER) | 363 | if (replay_esn->oseq_hi == preplay_esn->oseq_hi) |
372 | event = XFRM_REPLAY_TIMEOUT; | 364 | oseq_diff = replay_esn->oseq |
365 | - preplay_esn->oseq; | ||
373 | else | 366 | else |
374 | return; | 367 | oseq_diff = ~preplay_esn->oseq |
368 | + replay_esn->oseq + 1; | ||
369 | |||
370 | if (seq_diff >= x->replay_maxdiff || | ||
371 | oseq_diff >= x->replay_maxdiff) | ||
372 | break; | ||
375 | } | 373 | } |
376 | 374 | ||
375 | if (x->xflags & XFRM_TIME_DEFER) | ||
376 | event = XFRM_REPLAY_TIMEOUT; | ||
377 | else | ||
378 | return; | ||
379 | |||
377 | break; | 380 | break; |
378 | 381 | ||
379 | case XFRM_REPLAY_TIMEOUT: | 382 | case XFRM_REPLAY_TIMEOUT: |