Merge tag 'mac80211-next-for-net-next-2021-06-25' of git://git.kernel.org/pub/scm...
[linux-2.6-microblaze.git] / net / xfrm / xfrm_replay.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c.
4  *
5  * Copyright (C) 2010 secunet Security Networks AG
6  * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
7  */
8
9 #include <linux/export.h>
10 #include <net/xfrm.h>
11
12 u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq)
13 {
14         u32 seq, seq_hi, bottom;
15         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
16
17         if (!(x->props.flags & XFRM_STATE_ESN))
18                 return 0;
19
20         seq = ntohl(net_seq);
21         seq_hi = replay_esn->seq_hi;
22         bottom = replay_esn->seq - replay_esn->replay_window + 1;
23
24         if (likely(replay_esn->seq >= replay_esn->replay_window - 1)) {
25                 /* A. same subspace */
26                 if (unlikely(seq < bottom))
27                         seq_hi++;
28         } else {
29                 /* B. window spans two subspaces */
30                 if (unlikely(seq >= bottom))
31                         seq_hi--;
32         }
33
34         return seq_hi;
35 }
36 EXPORT_SYMBOL(xfrm_replay_seqhi);
37 ;
38 static void xfrm_replay_notify(struct xfrm_state *x, int event)
39 {
40         struct km_event c;
41         /* we send notify messages in case
42          *  1. we updated on of the sequence numbers, and the seqno difference
43          *     is at least x->replay_maxdiff, in this case we also update the
44          *     timeout of our timer function
45          *  2. if x->replay_maxage has elapsed since last update,
46          *     and there were changes
47          *
48          *  The state structure must be locked!
49          */
50
51         switch (event) {
52         case XFRM_REPLAY_UPDATE:
53                 if (!x->replay_maxdiff ||
54                     ((x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
55                     (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))) {
56                         if (x->xflags & XFRM_TIME_DEFER)
57                                 event = XFRM_REPLAY_TIMEOUT;
58                         else
59                                 return;
60                 }
61
62                 break;
63
64         case XFRM_REPLAY_TIMEOUT:
65                 if (memcmp(&x->replay, &x->preplay,
66                            sizeof(struct xfrm_replay_state)) == 0) {
67                         x->xflags |= XFRM_TIME_DEFER;
68                         return;
69                 }
70
71                 break;
72         }
73
74         memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
75         c.event = XFRM_MSG_NEWAE;
76         c.data.aevent = event;
77         km_state_notify(x, &c);
78
79         if (x->replay_maxage &&
80             !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
81                 x->xflags &= ~XFRM_TIME_DEFER;
82 }
83
84 static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
85 {
86         int err = 0;
87         struct net *net = xs_net(x);
88
89         if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
90                 XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq;
91                 XFRM_SKB_CB(skb)->seq.output.hi = 0;
92                 if (unlikely(x->replay.oseq == 0) &&
93                     !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
94                         x->replay.oseq--;
95                         xfrm_audit_state_replay_overflow(x, skb);
96                         err = -EOVERFLOW;
97
98                         return err;
99                 }
100                 if (xfrm_aevent_is_on(net))
101                         x->repl->notify(x, XFRM_REPLAY_UPDATE);
102         }
103
104         return err;
105 }
106
107 static int xfrm_replay_check(struct xfrm_state *x,
108                       struct sk_buff *skb, __be32 net_seq)
109 {
110         u32 diff;
111         u32 seq = ntohl(net_seq);
112
113         if (!x->props.replay_window)
114                 return 0;
115
116         if (unlikely(seq == 0))
117                 goto err;
118
119         if (likely(seq > x->replay.seq))
120                 return 0;
121
122         diff = x->replay.seq - seq;
123         if (diff >= x->props.replay_window) {
124                 x->stats.replay_window++;
125                 goto err;
126         }
127
128         if (x->replay.bitmap & (1U << diff)) {
129                 x->stats.replay++;
130                 goto err;
131         }
132         return 0;
133
134 err:
135         xfrm_audit_state_replay(x, skb, net_seq);
136         return -EINVAL;
137 }
138
139 static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
140 {
141         u32 diff;
142         u32 seq = ntohl(net_seq);
143
144         if (!x->props.replay_window)
145                 return;
146
147         if (seq > x->replay.seq) {
148                 diff = seq - x->replay.seq;
149                 if (diff < x->props.replay_window)
150                         x->replay.bitmap = ((x->replay.bitmap) << diff) | 1;
151                 else
152                         x->replay.bitmap = 1;
153                 x->replay.seq = seq;
154         } else {
155                 diff = x->replay.seq - seq;
156                 x->replay.bitmap |= (1U << diff);
157         }
158
159         if (xfrm_aevent_is_on(xs_net(x)))
160                 x->repl->notify(x, XFRM_REPLAY_UPDATE);
161 }
162
163 static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb)
164 {
165         int err = 0;
166         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
167         struct net *net = xs_net(x);
168
169         if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
170                 XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
171                 XFRM_SKB_CB(skb)->seq.output.hi = 0;
172                 if (unlikely(replay_esn->oseq == 0) &&
173                     !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
174                         replay_esn->oseq--;
175                         xfrm_audit_state_replay_overflow(x, skb);
176                         err = -EOVERFLOW;
177
178                         return err;
179                 }
180                 if (xfrm_aevent_is_on(net))
181                         x->repl->notify(x, XFRM_REPLAY_UPDATE);
182         }
183
184         return err;
185 }
186
187 static int xfrm_replay_check_bmp(struct xfrm_state *x,
188                                  struct sk_buff *skb, __be32 net_seq)
189 {
190         unsigned int bitnr, nr;
191         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
192         u32 pos;
193         u32 seq = ntohl(net_seq);
194         u32 diff =  replay_esn->seq - seq;
195
196         if (!replay_esn->replay_window)
197                 return 0;
198
199         if (unlikely(seq == 0))
200                 goto err;
201
202         if (likely(seq > replay_esn->seq))
203                 return 0;
204
205         if (diff >= replay_esn->replay_window) {
206                 x->stats.replay_window++;
207                 goto err;
208         }
209
210         pos = (replay_esn->seq - 1) % replay_esn->replay_window;
211
212         if (pos >= diff)
213                 bitnr = (pos - diff) % replay_esn->replay_window;
214         else
215                 bitnr = replay_esn->replay_window - (diff - pos);
216
217         nr = bitnr >> 5;
218         bitnr = bitnr & 0x1F;
219         if (replay_esn->bmp[nr] & (1U << bitnr))
220                 goto err_replay;
221
222         return 0;
223
224 err_replay:
225         x->stats.replay++;
226 err:
227         xfrm_audit_state_replay(x, skb, net_seq);
228         return -EINVAL;
229 }
230
231 static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq)
232 {
233         unsigned int bitnr, nr, i;
234         u32 diff;
235         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
236         u32 seq = ntohl(net_seq);
237         u32 pos;
238
239         if (!replay_esn->replay_window)
240                 return;
241
242         pos = (replay_esn->seq - 1) % replay_esn->replay_window;
243
244         if (seq > replay_esn->seq) {
245                 diff = seq - replay_esn->seq;
246
247                 if (diff < replay_esn->replay_window) {
248                         for (i = 1; i < diff; i++) {
249                                 bitnr = (pos + i) % replay_esn->replay_window;
250                                 nr = bitnr >> 5;
251                                 bitnr = bitnr & 0x1F;
252                                 replay_esn->bmp[nr] &=  ~(1U << bitnr);
253                         }
254                 } else {
255                         nr = (replay_esn->replay_window - 1) >> 5;
256                         for (i = 0; i <= nr; i++)
257                                 replay_esn->bmp[i] = 0;
258                 }
259
260                 bitnr = (pos + diff) % replay_esn->replay_window;
261                 replay_esn->seq = seq;
262         } else {
263                 diff = replay_esn->seq - seq;
264
265                 if (pos >= diff)
266                         bitnr = (pos - diff) % replay_esn->replay_window;
267                 else
268                         bitnr = replay_esn->replay_window - (diff - pos);
269         }
270
271         nr = bitnr >> 5;
272         bitnr = bitnr & 0x1F;
273         replay_esn->bmp[nr] |= (1U << bitnr);
274
275         if (xfrm_aevent_is_on(xs_net(x)))
276                 x->repl->notify(x, XFRM_REPLAY_UPDATE);
277 }
278
279 static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
280 {
281         struct km_event c;
282         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
283         struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
284
285         /* we send notify messages in case
286          *  1. we updated on of the sequence numbers, and the seqno difference
287          *     is at least x->replay_maxdiff, in this case we also update the
288          *     timeout of our timer function
289          *  2. if x->replay_maxage has elapsed since last update,
290          *     and there were changes
291          *
292          *  The state structure must be locked!
293          */
294
295         switch (event) {
296         case XFRM_REPLAY_UPDATE:
297                 if (!x->replay_maxdiff ||
298                     ((replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
299                     (replay_esn->oseq - preplay_esn->oseq
300                      < x->replay_maxdiff))) {
301                         if (x->xflags & XFRM_TIME_DEFER)
302                                 event = XFRM_REPLAY_TIMEOUT;
303                         else
304                                 return;
305                 }
306
307                 break;
308
309         case XFRM_REPLAY_TIMEOUT:
310                 if (memcmp(x->replay_esn, x->preplay_esn,
311                            xfrm_replay_state_esn_len(replay_esn)) == 0) {
312                         x->xflags |= XFRM_TIME_DEFER;
313                         return;
314                 }
315
316                 break;
317         }
318
319         memcpy(x->preplay_esn, x->replay_esn,
320                xfrm_replay_state_esn_len(replay_esn));
321         c.event = XFRM_MSG_NEWAE;
322         c.data.aevent = event;
323         km_state_notify(x, &c);
324
325         if (x->replay_maxage &&
326             !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
327                 x->xflags &= ~XFRM_TIME_DEFER;
328 }
329
330 static void xfrm_replay_notify_esn(struct xfrm_state *x, int event)
331 {
332         u32 seq_diff, oseq_diff;
333         struct km_event c;
334         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
335         struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
336
337         /* we send notify messages in case
338          *  1. we updated on of the sequence numbers, and the seqno difference
339          *     is at least x->replay_maxdiff, in this case we also update the
340          *     timeout of our timer function
341          *  2. if x->replay_maxage has elapsed since last update,
342          *     and there were changes
343          *
344          *  The state structure must be locked!
345          */
346
347         switch (event) {
348         case XFRM_REPLAY_UPDATE:
349                 if (x->replay_maxdiff) {
350                         if (replay_esn->seq_hi == preplay_esn->seq_hi)
351                                 seq_diff = replay_esn->seq - preplay_esn->seq;
352                         else
353                                 seq_diff = ~preplay_esn->seq + replay_esn->seq
354                                            + 1;
355
356                         if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
357                                 oseq_diff = replay_esn->oseq
358                                             - preplay_esn->oseq;
359                         else
360                                 oseq_diff = ~preplay_esn->oseq
361                                             + replay_esn->oseq + 1;
362
363                         if (seq_diff >= x->replay_maxdiff ||
364                             oseq_diff >= x->replay_maxdiff)
365                                 break;
366                 }
367
368                 if (x->xflags & XFRM_TIME_DEFER)
369                         event = XFRM_REPLAY_TIMEOUT;
370                 else
371                         return;
372
373                 break;
374
375         case XFRM_REPLAY_TIMEOUT:
376                 if (memcmp(x->replay_esn, x->preplay_esn,
377                            xfrm_replay_state_esn_len(replay_esn)) == 0) {
378                         x->xflags |= XFRM_TIME_DEFER;
379                         return;
380                 }
381
382                 break;
383         }
384
385         memcpy(x->preplay_esn, x->replay_esn,
386                xfrm_replay_state_esn_len(replay_esn));
387         c.event = XFRM_MSG_NEWAE;
388         c.data.aevent = event;
389         km_state_notify(x, &c);
390
391         if (x->replay_maxage &&
392             !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
393                 x->xflags &= ~XFRM_TIME_DEFER;
394 }
395
396 static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb)
397 {
398         int err = 0;
399         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
400         struct net *net = xs_net(x);
401
402         if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
403                 XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
404                 XFRM_SKB_CB(skb)->seq.output.hi = replay_esn->oseq_hi;
405
406                 if (unlikely(replay_esn->oseq == 0)) {
407                         XFRM_SKB_CB(skb)->seq.output.hi = ++replay_esn->oseq_hi;
408
409                         if (replay_esn->oseq_hi == 0) {
410                                 replay_esn->oseq--;
411                                 replay_esn->oseq_hi--;
412                                 xfrm_audit_state_replay_overflow(x, skb);
413                                 err = -EOVERFLOW;
414
415                                 return err;
416                         }
417                 }
418                 if (xfrm_aevent_is_on(net))
419                         x->repl->notify(x, XFRM_REPLAY_UPDATE);
420         }
421
422         return err;
423 }
424
425 static int xfrm_replay_check_esn(struct xfrm_state *x,
426                                  struct sk_buff *skb, __be32 net_seq)
427 {
428         unsigned int bitnr, nr;
429         u32 diff;
430         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
431         u32 pos;
432         u32 seq = ntohl(net_seq);
433         u32 wsize = replay_esn->replay_window;
434         u32 top = replay_esn->seq;
435         u32 bottom = top - wsize + 1;
436
437         if (!wsize)
438                 return 0;
439
440         if (unlikely(seq == 0 && replay_esn->seq_hi == 0 &&
441                      (replay_esn->seq < replay_esn->replay_window - 1)))
442                 goto err;
443
444         diff = top - seq;
445
446         if (likely(top >= wsize - 1)) {
447                 /* A. same subspace */
448                 if (likely(seq > top) || seq < bottom)
449                         return 0;
450         } else {
451                 /* B. window spans two subspaces */
452                 if (likely(seq > top && seq < bottom))
453                         return 0;
454                 if (seq >= bottom)
455                         diff = ~seq + top + 1;
456         }
457
458         if (diff >= replay_esn->replay_window) {
459                 x->stats.replay_window++;
460                 goto err;
461         }
462
463         pos = (replay_esn->seq - 1) % replay_esn->replay_window;
464
465         if (pos >= diff)
466                 bitnr = (pos - diff) % replay_esn->replay_window;
467         else
468                 bitnr = replay_esn->replay_window - (diff - pos);
469
470         nr = bitnr >> 5;
471         bitnr = bitnr & 0x1F;
472         if (replay_esn->bmp[nr] & (1U << bitnr))
473                 goto err_replay;
474
475         return 0;
476
477 err_replay:
478         x->stats.replay++;
479 err:
480         xfrm_audit_state_replay(x, skb, net_seq);
481         return -EINVAL;
482 }
483
484 static int xfrm_replay_recheck_esn(struct xfrm_state *x,
485                                    struct sk_buff *skb, __be32 net_seq)
486 {
487         if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi !=
488                      htonl(xfrm_replay_seqhi(x, net_seq)))) {
489                         x->stats.replay_window++;
490                         return -EINVAL;
491         }
492
493         return xfrm_replay_check_esn(x, skb, net_seq);
494 }
495
496 static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
497 {
498         unsigned int bitnr, nr, i;
499         int wrap;
500         u32 diff, pos, seq, seq_hi;
501         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
502
503         if (!replay_esn->replay_window)
504                 return;
505
506         seq = ntohl(net_seq);
507         pos = (replay_esn->seq - 1) % replay_esn->replay_window;
508         seq_hi = xfrm_replay_seqhi(x, net_seq);
509         wrap = seq_hi - replay_esn->seq_hi;
510
511         if ((!wrap && seq > replay_esn->seq) || wrap > 0) {
512                 if (likely(!wrap))
513                         diff = seq - replay_esn->seq;
514                 else
515                         diff = ~replay_esn->seq + seq + 1;
516
517                 if (diff < replay_esn->replay_window) {
518                         for (i = 1; i < diff; i++) {
519                                 bitnr = (pos + i) % replay_esn->replay_window;
520                                 nr = bitnr >> 5;
521                                 bitnr = bitnr & 0x1F;
522                                 replay_esn->bmp[nr] &=  ~(1U << bitnr);
523                         }
524                 } else {
525                         nr = (replay_esn->replay_window - 1) >> 5;
526                         for (i = 0; i <= nr; i++)
527                                 replay_esn->bmp[i] = 0;
528                 }
529
530                 bitnr = (pos + diff) % replay_esn->replay_window;
531                 replay_esn->seq = seq;
532
533                 if (unlikely(wrap > 0))
534                         replay_esn->seq_hi++;
535         } else {
536                 diff = replay_esn->seq - seq;
537
538                 if (pos >= diff)
539                         bitnr = (pos - diff) % replay_esn->replay_window;
540                 else
541                         bitnr = replay_esn->replay_window - (diff - pos);
542         }
543
544         xfrm_dev_state_advance_esn(x);
545
546         nr = bitnr >> 5;
547         bitnr = bitnr & 0x1F;
548         replay_esn->bmp[nr] |= (1U << bitnr);
549
550         if (xfrm_aevent_is_on(xs_net(x)))
551                 x->repl->notify(x, XFRM_REPLAY_UPDATE);
552 }
553
554 #ifdef CONFIG_XFRM_OFFLOAD
555 static int xfrm_replay_overflow_offload(struct xfrm_state *x, struct sk_buff *skb)
556 {
557         int err = 0;
558         struct net *net = xs_net(x);
559         struct xfrm_offload *xo = xfrm_offload(skb);
560         __u32 oseq = x->replay.oseq;
561
562         if (!xo)
563                 return xfrm_replay_overflow(x, skb);
564
565         if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
566                 if (!skb_is_gso(skb)) {
567                         XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
568                         xo->seq.low = oseq;
569                 } else {
570                         XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
571                         xo->seq.low = oseq + 1;
572                         oseq += skb_shinfo(skb)->gso_segs;
573                 }
574
575                 XFRM_SKB_CB(skb)->seq.output.hi = 0;
576                 xo->seq.hi = 0;
577                 if (unlikely(oseq < x->replay.oseq) &&
578                     !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
579                         xfrm_audit_state_replay_overflow(x, skb);
580                         err = -EOVERFLOW;
581
582                         return err;
583                 }
584
585                 x->replay.oseq = oseq;
586
587                 if (xfrm_aevent_is_on(net))
588                         x->repl->notify(x, XFRM_REPLAY_UPDATE);
589         }
590
591         return err;
592 }
593
594 static int xfrm_replay_overflow_offload_bmp(struct xfrm_state *x, struct sk_buff *skb)
595 {
596         int err = 0;
597         struct xfrm_offload *xo = xfrm_offload(skb);
598         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
599         struct net *net = xs_net(x);
600         __u32 oseq = replay_esn->oseq;
601
602         if (!xo)
603                 return xfrm_replay_overflow_bmp(x, skb);
604
605         if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
606                 if (!skb_is_gso(skb)) {
607                         XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
608                         xo->seq.low = oseq;
609                 } else {
610                         XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
611                         xo->seq.low = oseq + 1;
612                         oseq += skb_shinfo(skb)->gso_segs;
613                 }
614
615                 XFRM_SKB_CB(skb)->seq.output.hi = 0;
616                 xo->seq.hi = 0;
617                 if (unlikely(oseq < replay_esn->oseq) &&
618                     !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
619                         xfrm_audit_state_replay_overflow(x, skb);
620                         err = -EOVERFLOW;
621
622                         return err;
623                 } else {
624                         replay_esn->oseq = oseq;
625                 }
626
627                 if (xfrm_aevent_is_on(net))
628                         x->repl->notify(x, XFRM_REPLAY_UPDATE);
629         }
630
631         return err;
632 }
633
634 static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff *skb)
635 {
636         int err = 0;
637         struct xfrm_offload *xo = xfrm_offload(skb);
638         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
639         struct net *net = xs_net(x);
640         __u32 oseq = replay_esn->oseq;
641         __u32 oseq_hi = replay_esn->oseq_hi;
642
643         if (!xo)
644                 return xfrm_replay_overflow_esn(x, skb);
645
646         if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
647                 if (!skb_is_gso(skb)) {
648                         XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
649                         XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi;
650                         xo->seq.low = oseq;
651                         xo->seq.hi = oseq_hi;
652                 } else {
653                         XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
654                         XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi;
655                         xo->seq.low = oseq + 1;
656                         xo->seq.hi = oseq_hi;
657                         oseq += skb_shinfo(skb)->gso_segs;
658                 }
659
660                 if (unlikely(oseq < replay_esn->oseq)) {
661                         XFRM_SKB_CB(skb)->seq.output.hi = ++oseq_hi;
662                         xo->seq.hi = oseq_hi;
663                         replay_esn->oseq_hi = oseq_hi;
664                         if (replay_esn->oseq_hi == 0) {
665                                 replay_esn->oseq--;
666                                 replay_esn->oseq_hi--;
667                                 xfrm_audit_state_replay_overflow(x, skb);
668                                 err = -EOVERFLOW;
669
670                                 return err;
671                         }
672                 }
673
674                 replay_esn->oseq = oseq;
675
676                 if (xfrm_aevent_is_on(net))
677                         x->repl->notify(x, XFRM_REPLAY_UPDATE);
678         }
679
680         return err;
681 }
682
683 static const struct xfrm_replay xfrm_replay_legacy = {
684         .advance        = xfrm_replay_advance,
685         .check          = xfrm_replay_check,
686         .recheck        = xfrm_replay_check,
687         .notify         = xfrm_replay_notify,
688         .overflow       = xfrm_replay_overflow_offload,
689 };
690
691 static const struct xfrm_replay xfrm_replay_bmp = {
692         .advance        = xfrm_replay_advance_bmp,
693         .check          = xfrm_replay_check_bmp,
694         .recheck        = xfrm_replay_check_bmp,
695         .notify         = xfrm_replay_notify_bmp,
696         .overflow       = xfrm_replay_overflow_offload_bmp,
697 };
698
699 static const struct xfrm_replay xfrm_replay_esn = {
700         .advance        = xfrm_replay_advance_esn,
701         .check          = xfrm_replay_check_esn,
702         .recheck        = xfrm_replay_recheck_esn,
703         .notify         = xfrm_replay_notify_esn,
704         .overflow       = xfrm_replay_overflow_offload_esn,
705 };
706 #else
707 static const struct xfrm_replay xfrm_replay_legacy = {
708         .advance        = xfrm_replay_advance,
709         .check          = xfrm_replay_check,
710         .recheck        = xfrm_replay_check,
711         .notify         = xfrm_replay_notify,
712         .overflow       = xfrm_replay_overflow,
713 };
714
715 static const struct xfrm_replay xfrm_replay_bmp = {
716         .advance        = xfrm_replay_advance_bmp,
717         .check          = xfrm_replay_check_bmp,
718         .recheck        = xfrm_replay_check_bmp,
719         .notify         = xfrm_replay_notify_bmp,
720         .overflow       = xfrm_replay_overflow_bmp,
721 };
722
723 static const struct xfrm_replay xfrm_replay_esn = {
724         .advance        = xfrm_replay_advance_esn,
725         .check          = xfrm_replay_check_esn,
726         .recheck        = xfrm_replay_recheck_esn,
727         .notify         = xfrm_replay_notify_esn,
728         .overflow       = xfrm_replay_overflow_esn,
729 };
730 #endif
731
732 int xfrm_init_replay(struct xfrm_state *x)
733 {
734         struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
735
736         if (replay_esn) {
737                 if (replay_esn->replay_window >
738                     replay_esn->bmp_len * sizeof(__u32) * 8)
739                         return -EINVAL;
740
741                 if (x->props.flags & XFRM_STATE_ESN) {
742                         if (replay_esn->replay_window == 0)
743                                 return -EINVAL;
744                         x->repl = &xfrm_replay_esn;
745                 } else {
746                         x->repl = &xfrm_replay_bmp;
747                 }
748         } else {
749                 x->repl = &xfrm_replay_legacy;
750         }
751
752         return 0;
753 }
754 EXPORT_SYMBOL(xfrm_init_replay);