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