aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorThomas Egerer <thomas.egerer@secunet.com>2013-09-19 07:19:19 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2013-09-25 01:32:48 -0400
commitcd808fc9a6c7cd3a4311d9d2cffc4adbeaef5f6c (patch)
tree82279120c03e0980a1da1f22beba85ee97a228f2 /net/xfrm
parent33fce60d6a6e137035f8e23a89d7fd55f3a24cda (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.c51
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: