1 // SPDX-License-Identifier: GPL-2.0-only
3 * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c.
5 * Copyright (C) 2010 secunet Security Networks AG
6 * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
9 #include <linux/export.h>
12 u32
xfrm_replay_seqhi(struct xfrm_state
*x
, __be32 net_seq
)
14 u32 seq
, seq_hi
, bottom
;
15 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
17 if (!(x
->props
.flags
& XFRM_STATE_ESN
))
21 seq_hi
= replay_esn
->seq_hi
;
22 bottom
= replay_esn
->seq
- replay_esn
->replay_window
+ 1;
24 if (likely(replay_esn
->seq
>= replay_esn
->replay_window
- 1)) {
25 /* A. same subspace */
26 if (unlikely(seq
< bottom
))
29 /* B. window spans two subspaces */
30 if (unlikely(seq
>= bottom
))
36 EXPORT_SYMBOL(xfrm_replay_seqhi
);
38 static void xfrm_replay_notify_bmp(struct xfrm_state
*x
, int event
);
39 static void xfrm_replay_notify_esn(struct xfrm_state
*x
, int event
);
41 void xfrm_replay_notify(struct xfrm_state
*x
, int event
)
44 /* we send notify messages in case
45 * 1. we updated on of the sequence numbers, and the seqno difference
46 * is at least x->replay_maxdiff, in this case we also update the
47 * timeout of our timer function
48 * 2. if x->replay_maxage has elapsed since last update,
49 * and there were changes
51 * The state structure must be locked!
54 switch (x
->repl_mode
) {
55 case XFRM_REPLAY_MODE_LEGACY
:
57 case XFRM_REPLAY_MODE_BMP
:
58 xfrm_replay_notify_bmp(x
, event
);
60 case XFRM_REPLAY_MODE_ESN
:
61 xfrm_replay_notify_esn(x
, event
);
66 case XFRM_REPLAY_UPDATE
:
67 if (!x
->replay_maxdiff
||
68 ((x
->replay
.seq
- x
->preplay
.seq
< x
->replay_maxdiff
) &&
69 (x
->replay
.oseq
- x
->preplay
.oseq
< x
->replay_maxdiff
))) {
70 if (x
->xflags
& XFRM_TIME_DEFER
)
71 event
= XFRM_REPLAY_TIMEOUT
;
78 case XFRM_REPLAY_TIMEOUT
:
79 if (memcmp(&x
->replay
, &x
->preplay
,
80 sizeof(struct xfrm_replay_state
)) == 0) {
81 x
->xflags
|= XFRM_TIME_DEFER
;
88 memcpy(&x
->preplay
, &x
->replay
, sizeof(struct xfrm_replay_state
));
89 c
.event
= XFRM_MSG_NEWAE
;
90 c
.data
.aevent
= event
;
91 km_state_notify(x
, &c
);
93 if (x
->replay_maxage
&&
94 !mod_timer(&x
->rtimer
, jiffies
+ x
->replay_maxage
))
95 x
->xflags
&= ~XFRM_TIME_DEFER
;
98 static int __xfrm_replay_overflow(struct xfrm_state
*x
, struct sk_buff
*skb
)
101 struct net
*net
= xs_net(x
);
103 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
104 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++x
->replay
.oseq
;
105 XFRM_SKB_CB(skb
)->seq
.output
.hi
= 0;
106 if (unlikely(x
->replay
.oseq
== 0) &&
107 !(x
->props
.extra_flags
& XFRM_SA_XFLAG_OSEQ_MAY_WRAP
)) {
109 xfrm_audit_state_replay_overflow(x
, skb
);
114 if (xfrm_aevent_is_on(net
))
115 xfrm_replay_notify(x
, XFRM_REPLAY_UPDATE
);
121 static int xfrm_replay_check_legacy(struct xfrm_state
*x
,
122 struct sk_buff
*skb
, __be32 net_seq
)
125 u32 seq
= ntohl(net_seq
);
127 if (!x
->props
.replay_window
)
130 if (unlikely(seq
== 0))
133 if (likely(seq
> x
->replay
.seq
))
136 diff
= x
->replay
.seq
- seq
;
137 if (diff
>= x
->props
.replay_window
) {
138 x
->stats
.replay_window
++;
142 if (x
->replay
.bitmap
& (1U << diff
)) {
149 xfrm_audit_state_replay(x
, skb
, net_seq
);
153 static void xfrm_replay_advance_bmp(struct xfrm_state
*x
, __be32 net_seq
);
154 static void xfrm_replay_advance_esn(struct xfrm_state
*x
, __be32 net_seq
);
156 void xfrm_replay_advance(struct xfrm_state
*x
, __be32 net_seq
)
160 switch (x
->repl_mode
) {
161 case XFRM_REPLAY_MODE_LEGACY
:
163 case XFRM_REPLAY_MODE_BMP
:
164 return xfrm_replay_advance_bmp(x
, net_seq
);
165 case XFRM_REPLAY_MODE_ESN
:
166 return xfrm_replay_advance_esn(x
, net_seq
);
169 if (!x
->props
.replay_window
)
172 seq
= ntohl(net_seq
);
173 if (seq
> x
->replay
.seq
) {
174 diff
= seq
- x
->replay
.seq
;
175 if (diff
< x
->props
.replay_window
)
176 x
->replay
.bitmap
= ((x
->replay
.bitmap
) << diff
) | 1;
178 x
->replay
.bitmap
= 1;
181 diff
= x
->replay
.seq
- seq
;
182 x
->replay
.bitmap
|= (1U << diff
);
185 if (xfrm_aevent_is_on(xs_net(x
)))
186 xfrm_replay_notify(x
, XFRM_REPLAY_UPDATE
);
189 static int xfrm_replay_overflow_bmp(struct xfrm_state
*x
, struct sk_buff
*skb
)
192 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
193 struct net
*net
= xs_net(x
);
195 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
196 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++replay_esn
->oseq
;
197 XFRM_SKB_CB(skb
)->seq
.output
.hi
= 0;
198 if (unlikely(replay_esn
->oseq
== 0) &&
199 !(x
->props
.extra_flags
& XFRM_SA_XFLAG_OSEQ_MAY_WRAP
)) {
201 xfrm_audit_state_replay_overflow(x
, skb
);
206 if (xfrm_aevent_is_on(net
))
207 xfrm_replay_notify(x
, XFRM_REPLAY_UPDATE
);
213 static int xfrm_replay_check_bmp(struct xfrm_state
*x
,
214 struct sk_buff
*skb
, __be32 net_seq
)
216 unsigned int bitnr
, nr
;
217 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
219 u32 seq
= ntohl(net_seq
);
220 u32 diff
= replay_esn
->seq
- seq
;
222 if (!replay_esn
->replay_window
)
225 if (unlikely(seq
== 0))
228 if (likely(seq
> replay_esn
->seq
))
231 if (diff
>= replay_esn
->replay_window
) {
232 x
->stats
.replay_window
++;
236 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
239 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
241 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
244 bitnr
= bitnr
& 0x1F;
245 if (replay_esn
->bmp
[nr
] & (1U << bitnr
))
253 xfrm_audit_state_replay(x
, skb
, net_seq
);
257 static void xfrm_replay_advance_bmp(struct xfrm_state
*x
, __be32 net_seq
)
259 unsigned int bitnr
, nr
, i
;
261 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
262 u32 seq
= ntohl(net_seq
);
265 if (!replay_esn
->replay_window
)
268 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
270 if (seq
> replay_esn
->seq
) {
271 diff
= seq
- replay_esn
->seq
;
273 if (diff
< replay_esn
->replay_window
) {
274 for (i
= 1; i
< diff
; i
++) {
275 bitnr
= (pos
+ i
) % replay_esn
->replay_window
;
277 bitnr
= bitnr
& 0x1F;
278 replay_esn
->bmp
[nr
] &= ~(1U << bitnr
);
281 nr
= (replay_esn
->replay_window
- 1) >> 5;
282 for (i
= 0; i
<= nr
; i
++)
283 replay_esn
->bmp
[i
] = 0;
286 bitnr
= (pos
+ diff
) % replay_esn
->replay_window
;
287 replay_esn
->seq
= seq
;
289 diff
= replay_esn
->seq
- seq
;
292 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
294 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
298 bitnr
= bitnr
& 0x1F;
299 replay_esn
->bmp
[nr
] |= (1U << bitnr
);
301 if (xfrm_aevent_is_on(xs_net(x
)))
302 xfrm_replay_notify(x
, XFRM_REPLAY_UPDATE
);
305 static void xfrm_replay_notify_bmp(struct xfrm_state
*x
, int event
)
308 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
309 struct xfrm_replay_state_esn
*preplay_esn
= x
->preplay_esn
;
311 /* we send notify messages in case
312 * 1. we updated on of the sequence numbers, and the seqno difference
313 * is at least x->replay_maxdiff, in this case we also update the
314 * timeout of our timer function
315 * 2. if x->replay_maxage has elapsed since last update,
316 * and there were changes
318 * The state structure must be locked!
322 case XFRM_REPLAY_UPDATE
:
323 if (!x
->replay_maxdiff
||
324 ((replay_esn
->seq
- preplay_esn
->seq
< x
->replay_maxdiff
) &&
325 (replay_esn
->oseq
- preplay_esn
->oseq
326 < x
->replay_maxdiff
))) {
327 if (x
->xflags
& XFRM_TIME_DEFER
)
328 event
= XFRM_REPLAY_TIMEOUT
;
335 case XFRM_REPLAY_TIMEOUT
:
336 if (memcmp(x
->replay_esn
, x
->preplay_esn
,
337 xfrm_replay_state_esn_len(replay_esn
)) == 0) {
338 x
->xflags
|= XFRM_TIME_DEFER
;
345 memcpy(x
->preplay_esn
, x
->replay_esn
,
346 xfrm_replay_state_esn_len(replay_esn
));
347 c
.event
= XFRM_MSG_NEWAE
;
348 c
.data
.aevent
= event
;
349 km_state_notify(x
, &c
);
351 if (x
->replay_maxage
&&
352 !mod_timer(&x
->rtimer
, jiffies
+ x
->replay_maxage
))
353 x
->xflags
&= ~XFRM_TIME_DEFER
;
356 static void xfrm_replay_notify_esn(struct xfrm_state
*x
, int event
)
358 u32 seq_diff
, oseq_diff
;
360 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
361 struct xfrm_replay_state_esn
*preplay_esn
= x
->preplay_esn
;
363 /* we send notify messages in case
364 * 1. we updated on of the sequence numbers, and the seqno difference
365 * is at least x->replay_maxdiff, in this case we also update the
366 * timeout of our timer function
367 * 2. if x->replay_maxage has elapsed since last update,
368 * and there were changes
370 * The state structure must be locked!
374 case XFRM_REPLAY_UPDATE
:
375 if (x
->replay_maxdiff
) {
376 if (replay_esn
->seq_hi
== preplay_esn
->seq_hi
)
377 seq_diff
= replay_esn
->seq
- preplay_esn
->seq
;
379 seq_diff
= ~preplay_esn
->seq
+ replay_esn
->seq
382 if (replay_esn
->oseq_hi
== preplay_esn
->oseq_hi
)
383 oseq_diff
= replay_esn
->oseq
386 oseq_diff
= ~preplay_esn
->oseq
387 + replay_esn
->oseq
+ 1;
389 if (seq_diff
>= x
->replay_maxdiff
||
390 oseq_diff
>= x
->replay_maxdiff
)
394 if (x
->xflags
& XFRM_TIME_DEFER
)
395 event
= XFRM_REPLAY_TIMEOUT
;
401 case XFRM_REPLAY_TIMEOUT
:
402 if (memcmp(x
->replay_esn
, x
->preplay_esn
,
403 xfrm_replay_state_esn_len(replay_esn
)) == 0) {
404 x
->xflags
|= XFRM_TIME_DEFER
;
411 memcpy(x
->preplay_esn
, x
->replay_esn
,
412 xfrm_replay_state_esn_len(replay_esn
));
413 c
.event
= XFRM_MSG_NEWAE
;
414 c
.data
.aevent
= event
;
415 km_state_notify(x
, &c
);
417 if (x
->replay_maxage
&&
418 !mod_timer(&x
->rtimer
, jiffies
+ x
->replay_maxage
))
419 x
->xflags
&= ~XFRM_TIME_DEFER
;
422 static int xfrm_replay_overflow_esn(struct xfrm_state
*x
, struct sk_buff
*skb
)
425 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
426 struct net
*net
= xs_net(x
);
428 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
429 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++replay_esn
->oseq
;
430 XFRM_SKB_CB(skb
)->seq
.output
.hi
= replay_esn
->oseq_hi
;
432 if (unlikely(replay_esn
->oseq
== 0)) {
433 XFRM_SKB_CB(skb
)->seq
.output
.hi
= ++replay_esn
->oseq_hi
;
435 if (replay_esn
->oseq_hi
== 0) {
437 replay_esn
->oseq_hi
--;
438 xfrm_audit_state_replay_overflow(x
, skb
);
444 if (xfrm_aevent_is_on(net
))
445 xfrm_replay_notify(x
, XFRM_REPLAY_UPDATE
);
451 static int xfrm_replay_check_esn(struct xfrm_state
*x
,
452 struct sk_buff
*skb
, __be32 net_seq
)
454 unsigned int bitnr
, nr
;
456 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
458 u32 seq
= ntohl(net_seq
);
459 u32 wsize
= replay_esn
->replay_window
;
460 u32 top
= replay_esn
->seq
;
461 u32 bottom
= top
- wsize
+ 1;
466 if (unlikely(seq
== 0 && replay_esn
->seq_hi
== 0 &&
467 (replay_esn
->seq
< replay_esn
->replay_window
- 1)))
472 if (likely(top
>= wsize
- 1)) {
473 /* A. same subspace */
474 if (likely(seq
> top
) || seq
< bottom
)
477 /* B. window spans two subspaces */
478 if (likely(seq
> top
&& seq
< bottom
))
481 diff
= ~seq
+ top
+ 1;
484 if (diff
>= replay_esn
->replay_window
) {
485 x
->stats
.replay_window
++;
489 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
492 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
494 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
497 bitnr
= bitnr
& 0x1F;
498 if (replay_esn
->bmp
[nr
] & (1U << bitnr
))
506 xfrm_audit_state_replay(x
, skb
, net_seq
);
510 int xfrm_replay_check(struct xfrm_state
*x
,
511 struct sk_buff
*skb
, __be32 net_seq
)
513 switch (x
->repl_mode
) {
514 case XFRM_REPLAY_MODE_LEGACY
:
516 case XFRM_REPLAY_MODE_BMP
:
517 return xfrm_replay_check_bmp(x
, skb
, net_seq
);
518 case XFRM_REPLAY_MODE_ESN
:
519 return xfrm_replay_check_esn(x
, skb
, net_seq
);
522 return xfrm_replay_check_legacy(x
, skb
, net_seq
);
525 static int xfrm_replay_recheck_esn(struct xfrm_state
*x
,
526 struct sk_buff
*skb
, __be32 net_seq
)
528 if (unlikely(XFRM_SKB_CB(skb
)->seq
.input
.hi
!=
529 htonl(xfrm_replay_seqhi(x
, net_seq
)))) {
530 x
->stats
.replay_window
++;
534 return xfrm_replay_check_esn(x
, skb
, net_seq
);
537 int xfrm_replay_recheck(struct xfrm_state
*x
,
538 struct sk_buff
*skb
, __be32 net_seq
)
540 switch (x
->repl_mode
) {
541 case XFRM_REPLAY_MODE_LEGACY
:
543 case XFRM_REPLAY_MODE_BMP
:
544 /* no special recheck treatment */
545 return xfrm_replay_check_bmp(x
, skb
, net_seq
);
546 case XFRM_REPLAY_MODE_ESN
:
547 return xfrm_replay_recheck_esn(x
, skb
, net_seq
);
550 return xfrm_replay_check_legacy(x
, skb
, net_seq
);
553 static void xfrm_replay_advance_esn(struct xfrm_state
*x
, __be32 net_seq
)
555 unsigned int bitnr
, nr
, i
;
557 u32 diff
, pos
, seq
, seq_hi
;
558 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
560 if (!replay_esn
->replay_window
)
563 seq
= ntohl(net_seq
);
564 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
565 seq_hi
= xfrm_replay_seqhi(x
, net_seq
);
566 wrap
= seq_hi
- replay_esn
->seq_hi
;
568 if ((!wrap
&& seq
> replay_esn
->seq
) || wrap
> 0) {
570 diff
= seq
- replay_esn
->seq
;
572 diff
= ~replay_esn
->seq
+ seq
+ 1;
574 if (diff
< replay_esn
->replay_window
) {
575 for (i
= 1; i
< diff
; i
++) {
576 bitnr
= (pos
+ i
) % replay_esn
->replay_window
;
578 bitnr
= bitnr
& 0x1F;
579 replay_esn
->bmp
[nr
] &= ~(1U << bitnr
);
582 nr
= (replay_esn
->replay_window
- 1) >> 5;
583 for (i
= 0; i
<= nr
; i
++)
584 replay_esn
->bmp
[i
] = 0;
587 bitnr
= (pos
+ diff
) % replay_esn
->replay_window
;
588 replay_esn
->seq
= seq
;
590 if (unlikely(wrap
> 0))
591 replay_esn
->seq_hi
++;
593 diff
= replay_esn
->seq
- seq
;
596 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
598 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
601 xfrm_dev_state_advance_esn(x
);
604 bitnr
= bitnr
& 0x1F;
605 replay_esn
->bmp
[nr
] |= (1U << bitnr
);
607 if (xfrm_aevent_is_on(xs_net(x
)))
608 xfrm_replay_notify(x
, XFRM_REPLAY_UPDATE
);
611 #ifdef CONFIG_XFRM_OFFLOAD
612 static int xfrm_replay_overflow_offload(struct xfrm_state
*x
, struct sk_buff
*skb
)
615 struct net
*net
= xs_net(x
);
616 struct xfrm_offload
*xo
= xfrm_offload(skb
);
617 __u32 oseq
= x
->replay
.oseq
;
620 return __xfrm_replay_overflow(x
, skb
);
622 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
623 if (!skb_is_gso(skb
)) {
624 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++oseq
;
627 XFRM_SKB_CB(skb
)->seq
.output
.low
= oseq
+ 1;
628 xo
->seq
.low
= oseq
+ 1;
629 oseq
+= skb_shinfo(skb
)->gso_segs
;
632 XFRM_SKB_CB(skb
)->seq
.output
.hi
= 0;
634 if (unlikely(oseq
< x
->replay
.oseq
) &&
635 !(x
->props
.extra_flags
& XFRM_SA_XFLAG_OSEQ_MAY_WRAP
)) {
636 xfrm_audit_state_replay_overflow(x
, skb
);
642 x
->replay
.oseq
= oseq
;
644 if (xfrm_aevent_is_on(net
))
645 xfrm_replay_notify(x
, XFRM_REPLAY_UPDATE
);
651 static int xfrm_replay_overflow_offload_bmp(struct xfrm_state
*x
, struct sk_buff
*skb
)
654 struct xfrm_offload
*xo
= xfrm_offload(skb
);
655 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
656 struct net
*net
= xs_net(x
);
657 __u32 oseq
= replay_esn
->oseq
;
660 return xfrm_replay_overflow_bmp(x
, skb
);
662 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
663 if (!skb_is_gso(skb
)) {
664 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++oseq
;
667 XFRM_SKB_CB(skb
)->seq
.output
.low
= oseq
+ 1;
668 xo
->seq
.low
= oseq
+ 1;
669 oseq
+= skb_shinfo(skb
)->gso_segs
;
672 XFRM_SKB_CB(skb
)->seq
.output
.hi
= 0;
674 if (unlikely(oseq
< replay_esn
->oseq
) &&
675 !(x
->props
.extra_flags
& XFRM_SA_XFLAG_OSEQ_MAY_WRAP
)) {
676 xfrm_audit_state_replay_overflow(x
, skb
);
681 replay_esn
->oseq
= oseq
;
684 if (xfrm_aevent_is_on(net
))
685 xfrm_replay_notify(x
, XFRM_REPLAY_UPDATE
);
691 static int xfrm_replay_overflow_offload_esn(struct xfrm_state
*x
, struct sk_buff
*skb
)
694 struct xfrm_offload
*xo
= xfrm_offload(skb
);
695 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
696 struct net
*net
= xs_net(x
);
697 __u32 oseq
= replay_esn
->oseq
;
698 __u32 oseq_hi
= replay_esn
->oseq_hi
;
701 return xfrm_replay_overflow_esn(x
, skb
);
703 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
704 if (!skb_is_gso(skb
)) {
705 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++oseq
;
706 XFRM_SKB_CB(skb
)->seq
.output
.hi
= oseq_hi
;
708 xo
->seq
.hi
= oseq_hi
;
710 XFRM_SKB_CB(skb
)->seq
.output
.low
= oseq
+ 1;
711 XFRM_SKB_CB(skb
)->seq
.output
.hi
= oseq_hi
;
712 xo
->seq
.low
= oseq
+ 1;
713 xo
->seq
.hi
= oseq_hi
;
714 oseq
+= skb_shinfo(skb
)->gso_segs
;
717 if (unlikely(xo
->seq
.low
< replay_esn
->oseq
)) {
718 XFRM_SKB_CB(skb
)->seq
.output
.hi
= ++oseq_hi
;
719 xo
->seq
.hi
= oseq_hi
;
720 replay_esn
->oseq_hi
= oseq_hi
;
721 if (replay_esn
->oseq_hi
== 0) {
723 replay_esn
->oseq_hi
--;
724 xfrm_audit_state_replay_overflow(x
, skb
);
731 replay_esn
->oseq
= oseq
;
733 if (xfrm_aevent_is_on(net
))
734 xfrm_replay_notify(x
, XFRM_REPLAY_UPDATE
);
740 int xfrm_replay_overflow(struct xfrm_state
*x
, struct sk_buff
*skb
)
742 switch (x
->repl_mode
) {
743 case XFRM_REPLAY_MODE_LEGACY
:
745 case XFRM_REPLAY_MODE_BMP
:
746 return xfrm_replay_overflow_offload_bmp(x
, skb
);
747 case XFRM_REPLAY_MODE_ESN
:
748 return xfrm_replay_overflow_offload_esn(x
, skb
);
751 return xfrm_replay_overflow_offload(x
, skb
);
754 int xfrm_replay_overflow(struct xfrm_state
*x
, struct sk_buff
*skb
)
756 switch (x
->repl_mode
) {
757 case XFRM_REPLAY_MODE_LEGACY
:
759 case XFRM_REPLAY_MODE_BMP
:
760 return xfrm_replay_overflow_bmp(x
, skb
);
761 case XFRM_REPLAY_MODE_ESN
:
762 return xfrm_replay_overflow_esn(x
, skb
);
765 return __xfrm_replay_overflow(x
, skb
);
769 int xfrm_init_replay(struct xfrm_state
*x
, struct netlink_ext_ack
*extack
)
771 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
774 if (replay_esn
->replay_window
>
775 replay_esn
->bmp_len
* sizeof(__u32
) * 8) {
776 NL_SET_ERR_MSG(extack
, "ESN replay window is too large for the chosen bitmap size");
780 if (x
->props
.flags
& XFRM_STATE_ESN
) {
781 if (replay_esn
->replay_window
== 0 &&
782 (!x
->dir
|| x
->dir
== XFRM_SA_DIR_IN
)) {
783 NL_SET_ERR_MSG(extack
, "ESN replay window must be > 0");
786 x
->repl_mode
= XFRM_REPLAY_MODE_ESN
;
788 x
->repl_mode
= XFRM_REPLAY_MODE_BMP
;
791 x
->repl_mode
= XFRM_REPLAY_MODE_LEGACY
;
796 EXPORT_SYMBOL(xfrm_init_replay
);