@@ -559,6 +559,158 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
559
559
x -> repl -> notify (x , XFRM_REPLAY_UPDATE );
560
560
}
561
561
562
+ #ifdef CONFIG_XFRM_OFFLOAD
563
+ static int xfrm_replay_overflow_offload (struct xfrm_state * x , struct sk_buff * skb )
564
+ {
565
+ int err = 0 ;
566
+ struct net * net = xs_net (x );
567
+ struct xfrm_offload * xo = xfrm_offload (skb );
568
+ __u32 oseq = x -> replay .oseq ;
569
+
570
+ if (!xo )
571
+ return xfrm_replay_overflow (x , skb );
572
+
573
+ if (x -> type -> flags & XFRM_TYPE_REPLAY_PROT ) {
574
+ if (!skb_is_gso (skb )) {
575
+ XFRM_SKB_CB (skb )-> seq .output .low = ++ oseq ;
576
+ xo -> seq .low = oseq ;
577
+ } else {
578
+ XFRM_SKB_CB (skb )-> seq .output .low = oseq + 1 ;
579
+ xo -> seq .low = oseq + 1 ;
580
+ oseq += skb_shinfo (skb )-> gso_segs ;
581
+ }
582
+
583
+ XFRM_SKB_CB (skb )-> seq .output .hi = 0 ;
584
+ xo -> seq .hi = 0 ;
585
+ if (unlikely (oseq < x -> replay .oseq )) {
586
+ xfrm_audit_state_replay_overflow (x , skb );
587
+ err = - EOVERFLOW ;
588
+
589
+ return err ;
590
+ }
591
+
592
+ x -> replay .oseq = oseq ;
593
+
594
+ if (xfrm_aevent_is_on (net ))
595
+ x -> repl -> notify (x , XFRM_REPLAY_UPDATE );
596
+ }
597
+
598
+ return err ;
599
+ }
600
+
601
+ static int xfrm_replay_overflow_offload_bmp (struct xfrm_state * x , struct sk_buff * skb )
602
+ {
603
+ int err = 0 ;
604
+ struct xfrm_offload * xo = xfrm_offload (skb );
605
+ struct xfrm_replay_state_esn * replay_esn = x -> replay_esn ;
606
+ struct net * net = xs_net (x );
607
+ __u32 oseq = replay_esn -> oseq ;
608
+
609
+ if (!xo )
610
+ return xfrm_replay_overflow_bmp (x , skb );
611
+
612
+ if (x -> type -> flags & XFRM_TYPE_REPLAY_PROT ) {
613
+ if (!skb_is_gso (skb )) {
614
+ XFRM_SKB_CB (skb )-> seq .output .low = ++ oseq ;
615
+ xo -> seq .low = oseq ;
616
+ } else {
617
+ XFRM_SKB_CB (skb )-> seq .output .low = oseq + 1 ;
618
+ xo -> seq .low = oseq + 1 ;
619
+ oseq += skb_shinfo (skb )-> gso_segs ;
620
+ }
621
+
622
+ XFRM_SKB_CB (skb )-> seq .output .hi = 0 ;
623
+ xo -> seq .hi = 0 ;
624
+ if (unlikely (oseq < replay_esn -> oseq )) {
625
+ xfrm_audit_state_replay_overflow (x , skb );
626
+ err = - EOVERFLOW ;
627
+
628
+ return err ;
629
+ } else {
630
+ replay_esn -> oseq = oseq ;
631
+ }
632
+
633
+ if (xfrm_aevent_is_on (net ))
634
+ x -> repl -> notify (x , XFRM_REPLAY_UPDATE );
635
+ }
636
+
637
+ return err ;
638
+ }
639
+
640
+ static int xfrm_replay_overflow_offload_esn (struct xfrm_state * x , struct sk_buff * skb )
641
+ {
642
+ int err = 0 ;
643
+ struct xfrm_offload * xo = xfrm_offload (skb );
644
+ struct xfrm_replay_state_esn * replay_esn = x -> replay_esn ;
645
+ struct net * net = xs_net (x );
646
+ __u32 oseq = replay_esn -> oseq ;
647
+ __u32 oseq_hi = replay_esn -> oseq_hi ;
648
+
649
+ if (!xo )
650
+ return xfrm_replay_overflow_esn (x , skb );
651
+
652
+ if (x -> type -> flags & XFRM_TYPE_REPLAY_PROT ) {
653
+ if (!skb_is_gso (skb )) {
654
+ XFRM_SKB_CB (skb )-> seq .output .low = ++ oseq ;
655
+ XFRM_SKB_CB (skb )-> seq .output .hi = oseq_hi ;
656
+ xo -> seq .low = oseq ;
657
+ xo -> seq .hi = oseq_hi ;
658
+ } else {
659
+ XFRM_SKB_CB (skb )-> seq .output .low = oseq + 1 ;
660
+ XFRM_SKB_CB (skb )-> seq .output .hi = oseq_hi ;
661
+ xo -> seq .low = oseq = oseq + 1 ;
662
+ xo -> seq .hi = oseq_hi ;
663
+ oseq += skb_shinfo (skb )-> gso_segs ;
664
+ }
665
+
666
+ if (unlikely (oseq < replay_esn -> oseq )) {
667
+ XFRM_SKB_CB (skb )-> seq .output .hi = ++ oseq_hi ;
668
+ xo -> seq .hi = oseq_hi ;
669
+
670
+ if (replay_esn -> oseq_hi == 0 ) {
671
+ replay_esn -> oseq -- ;
672
+ replay_esn -> oseq_hi -- ;
673
+ xfrm_audit_state_replay_overflow (x , skb );
674
+ err = - EOVERFLOW ;
675
+
676
+ return err ;
677
+ }
678
+ }
679
+
680
+ replay_esn -> oseq = oseq ;
681
+ replay_esn -> oseq_hi = oseq_hi ;
682
+
683
+ if (xfrm_aevent_is_on (net ))
684
+ x -> repl -> notify (x , XFRM_REPLAY_UPDATE );
685
+ }
686
+
687
+ return err ;
688
+ }
689
+
690
+ static const struct xfrm_replay xfrm_replay_legacy = {
691
+ .advance = xfrm_replay_advance ,
692
+ .check = xfrm_replay_check ,
693
+ .recheck = xfrm_replay_check ,
694
+ .notify = xfrm_replay_notify ,
695
+ .overflow = xfrm_replay_overflow_offload ,
696
+ };
697
+
698
+ static const struct xfrm_replay xfrm_replay_bmp = {
699
+ .advance = xfrm_replay_advance_bmp ,
700
+ .check = xfrm_replay_check_bmp ,
701
+ .recheck = xfrm_replay_check_bmp ,
702
+ .notify = xfrm_replay_notify_bmp ,
703
+ .overflow = xfrm_replay_overflow_offload_bmp ,
704
+ };
705
+
706
+ static const struct xfrm_replay xfrm_replay_esn = {
707
+ .advance = xfrm_replay_advance_esn ,
708
+ .check = xfrm_replay_check_esn ,
709
+ .recheck = xfrm_replay_recheck_esn ,
710
+ .notify = xfrm_replay_notify_esn ,
711
+ .overflow = xfrm_replay_overflow_offload_esn ,
712
+ };
713
+ #else
562
714
static const struct xfrm_replay xfrm_replay_legacy = {
563
715
.advance = xfrm_replay_advance ,
564
716
.check = xfrm_replay_check ,
@@ -582,6 +734,7 @@ static const struct xfrm_replay xfrm_replay_esn = {
582
734
.notify = xfrm_replay_notify_esn ,
583
735
.overflow = xfrm_replay_overflow_esn ,
584
736
};
737
+ #endif
585
738
586
739
int xfrm_init_replay (struct xfrm_state * x )
587
740
{
@@ -596,10 +749,12 @@ int xfrm_init_replay(struct xfrm_state *x)
596
749
if (replay_esn -> replay_window == 0 )
597
750
return - EINVAL ;
598
751
x -> repl = & xfrm_replay_esn ;
599
- } else
752
+ } else {
600
753
x -> repl = & xfrm_replay_bmp ;
601
- } else
754
+ }
755
+ } else {
602
756
x -> repl = & xfrm_replay_legacy ;
757
+ }
603
758
604
759
return 0 ;
605
760
}
0 commit comments