2 * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c.
4 * Copyright (C) 2010 secunet Security Networks AG
5 * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <linux/export.h>
24 u32
xfrm_replay_seqhi(struct xfrm_state
*x
, __be32 net_seq
)
26 u32 seq
, seq_hi
, bottom
;
27 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
29 if (!(x
->props
.flags
& XFRM_STATE_ESN
))
33 seq_hi
= replay_esn
->seq_hi
;
34 bottom
= replay_esn
->seq
- replay_esn
->replay_window
+ 1;
36 if (likely(replay_esn
->seq
>= replay_esn
->replay_window
- 1)) {
37 /* A. same subspace */
38 if (unlikely(seq
< bottom
))
41 /* B. window spans two subspaces */
42 if (unlikely(seq
>= bottom
))
48 EXPORT_SYMBOL(xfrm_replay_seqhi
);
50 static void xfrm_replay_notify(struct xfrm_state
*x
, int event
)
53 /* we send notify messages in case
54 * 1. we updated on of the sequence numbers, and the seqno difference
55 * is at least x->replay_maxdiff, in this case we also update the
56 * timeout of our timer function
57 * 2. if x->replay_maxage has elapsed since last update,
58 * and there were changes
60 * The state structure must be locked!
64 case XFRM_REPLAY_UPDATE
:
65 if (!x
->replay_maxdiff
||
66 ((x
->replay
.seq
- x
->preplay
.seq
< x
->replay_maxdiff
) &&
67 (x
->replay
.oseq
- x
->preplay
.oseq
< x
->replay_maxdiff
))) {
68 if (x
->xflags
& XFRM_TIME_DEFER
)
69 event
= XFRM_REPLAY_TIMEOUT
;
76 case XFRM_REPLAY_TIMEOUT
:
77 if (memcmp(&x
->replay
, &x
->preplay
,
78 sizeof(struct xfrm_replay_state
)) == 0) {
79 x
->xflags
|= XFRM_TIME_DEFER
;
86 memcpy(&x
->preplay
, &x
->replay
, sizeof(struct xfrm_replay_state
));
87 c
.event
= XFRM_MSG_NEWAE
;
88 c
.data
.aevent
= event
;
89 km_state_notify(x
, &c
);
91 if (x
->replay_maxage
&&
92 !mod_timer(&x
->rtimer
, jiffies
+ x
->replay_maxage
))
93 x
->xflags
&= ~XFRM_TIME_DEFER
;
96 static int xfrm_replay_overflow(struct xfrm_state
*x
, struct sk_buff
*skb
)
99 struct net
*net
= xs_net(x
);
101 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
102 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++x
->replay
.oseq
;
103 XFRM_SKB_CB(skb
)->seq
.output
.hi
= 0;
104 if (unlikely(x
->replay
.oseq
== 0)) {
106 xfrm_audit_state_replay_overflow(x
, skb
);
111 if (xfrm_aevent_is_on(net
))
112 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
118 static int xfrm_replay_check(struct xfrm_state
*x
,
119 struct sk_buff
*skb
, __be32 net_seq
)
122 u32 seq
= ntohl(net_seq
);
124 if (!x
->props
.replay_window
)
127 if (unlikely(seq
== 0))
130 if (likely(seq
> x
->replay
.seq
))
133 diff
= x
->replay
.seq
- seq
;
134 if (diff
>= x
->props
.replay_window
) {
135 x
->stats
.replay_window
++;
139 if (x
->replay
.bitmap
& (1U << diff
)) {
146 xfrm_audit_state_replay(x
, skb
, net_seq
);
150 static void xfrm_replay_advance(struct xfrm_state
*x
, __be32 net_seq
)
153 u32 seq
= ntohl(net_seq
);
155 if (!x
->props
.replay_window
)
158 if (seq
> x
->replay
.seq
) {
159 diff
= seq
- x
->replay
.seq
;
160 if (diff
< x
->props
.replay_window
)
161 x
->replay
.bitmap
= ((x
->replay
.bitmap
) << diff
) | 1;
163 x
->replay
.bitmap
= 1;
166 diff
= x
->replay
.seq
- seq
;
167 x
->replay
.bitmap
|= (1U << diff
);
170 if (xfrm_aevent_is_on(xs_net(x
)))
171 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
174 static int xfrm_replay_overflow_bmp(struct xfrm_state
*x
, struct sk_buff
*skb
)
177 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
178 struct net
*net
= xs_net(x
);
180 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
181 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++replay_esn
->oseq
;
182 XFRM_SKB_CB(skb
)->seq
.output
.hi
= 0;
183 if (unlikely(replay_esn
->oseq
== 0)) {
185 xfrm_audit_state_replay_overflow(x
, skb
);
190 if (xfrm_aevent_is_on(net
))
191 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
197 static int xfrm_replay_check_bmp(struct xfrm_state
*x
,
198 struct sk_buff
*skb
, __be32 net_seq
)
200 unsigned int bitnr
, nr
;
201 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
203 u32 seq
= ntohl(net_seq
);
204 u32 diff
= replay_esn
->seq
- seq
;
206 if (!replay_esn
->replay_window
)
209 if (unlikely(seq
== 0))
212 if (likely(seq
> replay_esn
->seq
))
215 if (diff
>= replay_esn
->replay_window
) {
216 x
->stats
.replay_window
++;
220 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
223 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
225 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
228 bitnr
= bitnr
& 0x1F;
229 if (replay_esn
->bmp
[nr
] & (1U << bitnr
))
237 xfrm_audit_state_replay(x
, skb
, net_seq
);
241 static void xfrm_replay_advance_bmp(struct xfrm_state
*x
, __be32 net_seq
)
243 unsigned int bitnr
, nr
, i
;
245 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
246 u32 seq
= ntohl(net_seq
);
249 if (!replay_esn
->replay_window
)
252 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
254 if (seq
> replay_esn
->seq
) {
255 diff
= seq
- replay_esn
->seq
;
257 if (diff
< replay_esn
->replay_window
) {
258 for (i
= 1; i
< diff
; i
++) {
259 bitnr
= (pos
+ i
) % replay_esn
->replay_window
;
261 bitnr
= bitnr
& 0x1F;
262 replay_esn
->bmp
[nr
] &= ~(1U << bitnr
);
265 nr
= (replay_esn
->replay_window
- 1) >> 5;
266 for (i
= 0; i
<= nr
; i
++)
267 replay_esn
->bmp
[i
] = 0;
270 bitnr
= (pos
+ diff
) % replay_esn
->replay_window
;
271 replay_esn
->seq
= seq
;
273 diff
= replay_esn
->seq
- seq
;
276 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
278 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
282 bitnr
= bitnr
& 0x1F;
283 replay_esn
->bmp
[nr
] |= (1U << bitnr
);
285 if (xfrm_aevent_is_on(xs_net(x
)))
286 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
289 static void xfrm_replay_notify_bmp(struct xfrm_state
*x
, int event
)
292 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
293 struct xfrm_replay_state_esn
*preplay_esn
= x
->preplay_esn
;
295 /* we send notify messages in case
296 * 1. we updated on of the sequence numbers, and the seqno difference
297 * is at least x->replay_maxdiff, in this case we also update the
298 * timeout of our timer function
299 * 2. if x->replay_maxage has elapsed since last update,
300 * and there were changes
302 * The state structure must be locked!
306 case XFRM_REPLAY_UPDATE
:
307 if (!x
->replay_maxdiff
||
308 ((replay_esn
->seq
- preplay_esn
->seq
< x
->replay_maxdiff
) &&
309 (replay_esn
->oseq
- preplay_esn
->oseq
310 < x
->replay_maxdiff
))) {
311 if (x
->xflags
& XFRM_TIME_DEFER
)
312 event
= XFRM_REPLAY_TIMEOUT
;
319 case XFRM_REPLAY_TIMEOUT
:
320 if (memcmp(x
->replay_esn
, x
->preplay_esn
,
321 xfrm_replay_state_esn_len(replay_esn
)) == 0) {
322 x
->xflags
|= XFRM_TIME_DEFER
;
329 memcpy(x
->preplay_esn
, x
->replay_esn
,
330 xfrm_replay_state_esn_len(replay_esn
));
331 c
.event
= XFRM_MSG_NEWAE
;
332 c
.data
.aevent
= event
;
333 km_state_notify(x
, &c
);
335 if (x
->replay_maxage
&&
336 !mod_timer(&x
->rtimer
, jiffies
+ x
->replay_maxage
))
337 x
->xflags
&= ~XFRM_TIME_DEFER
;
340 static void xfrm_replay_notify_esn(struct xfrm_state
*x
, int event
)
342 u32 seq_diff
, oseq_diff
;
344 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
345 struct xfrm_replay_state_esn
*preplay_esn
= x
->preplay_esn
;
347 /* we send notify messages in case
348 * 1. we updated on of the sequence numbers, and the seqno difference
349 * is at least x->replay_maxdiff, in this case we also update the
350 * timeout of our timer function
351 * 2. if x->replay_maxage has elapsed since last update,
352 * and there were changes
354 * The state structure must be locked!
358 case XFRM_REPLAY_UPDATE
:
359 if (x
->replay_maxdiff
) {
360 if (replay_esn
->seq_hi
== preplay_esn
->seq_hi
)
361 seq_diff
= replay_esn
->seq
- preplay_esn
->seq
;
363 seq_diff
= ~preplay_esn
->seq
+ replay_esn
->seq
366 if (replay_esn
->oseq_hi
== preplay_esn
->oseq_hi
)
367 oseq_diff
= replay_esn
->oseq
370 oseq_diff
= ~preplay_esn
->oseq
371 + replay_esn
->oseq
+ 1;
373 if (seq_diff
>= x
->replay_maxdiff
||
374 oseq_diff
>= x
->replay_maxdiff
)
378 if (x
->xflags
& XFRM_TIME_DEFER
)
379 event
= XFRM_REPLAY_TIMEOUT
;
385 case XFRM_REPLAY_TIMEOUT
:
386 if (memcmp(x
->replay_esn
, x
->preplay_esn
,
387 xfrm_replay_state_esn_len(replay_esn
)) == 0) {
388 x
->xflags
|= XFRM_TIME_DEFER
;
395 memcpy(x
->preplay_esn
, x
->replay_esn
,
396 xfrm_replay_state_esn_len(replay_esn
));
397 c
.event
= XFRM_MSG_NEWAE
;
398 c
.data
.aevent
= event
;
399 km_state_notify(x
, &c
);
401 if (x
->replay_maxage
&&
402 !mod_timer(&x
->rtimer
, jiffies
+ x
->replay_maxage
))
403 x
->xflags
&= ~XFRM_TIME_DEFER
;
406 static int xfrm_replay_overflow_esn(struct xfrm_state
*x
, struct sk_buff
*skb
)
409 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
410 struct net
*net
= xs_net(x
);
412 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
413 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++replay_esn
->oseq
;
414 XFRM_SKB_CB(skb
)->seq
.output
.hi
= replay_esn
->oseq_hi
;
416 if (unlikely(replay_esn
->oseq
== 0)) {
417 XFRM_SKB_CB(skb
)->seq
.output
.hi
= ++replay_esn
->oseq_hi
;
419 if (replay_esn
->oseq_hi
== 0) {
421 replay_esn
->oseq_hi
--;
422 xfrm_audit_state_replay_overflow(x
, skb
);
428 if (xfrm_aevent_is_on(net
))
429 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
435 static int xfrm_replay_check_esn(struct xfrm_state
*x
,
436 struct sk_buff
*skb
, __be32 net_seq
)
438 unsigned int bitnr
, nr
;
440 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
442 u32 seq
= ntohl(net_seq
);
443 u32 wsize
= replay_esn
->replay_window
;
444 u32 top
= replay_esn
->seq
;
445 u32 bottom
= top
- wsize
+ 1;
450 if (unlikely(seq
== 0 && replay_esn
->seq_hi
== 0 &&
451 (replay_esn
->seq
< replay_esn
->replay_window
- 1)))
456 if (likely(top
>= wsize
- 1)) {
457 /* A. same subspace */
458 if (likely(seq
> top
) || seq
< bottom
)
461 /* B. window spans two subspaces */
462 if (likely(seq
> top
&& seq
< bottom
))
465 diff
= ~seq
+ top
+ 1;
468 if (diff
>= replay_esn
->replay_window
) {
469 x
->stats
.replay_window
++;
473 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
476 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
478 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
481 bitnr
= bitnr
& 0x1F;
482 if (replay_esn
->bmp
[nr
] & (1U << bitnr
))
490 xfrm_audit_state_replay(x
, skb
, net_seq
);
494 static int xfrm_replay_recheck_esn(struct xfrm_state
*x
,
495 struct sk_buff
*skb
, __be32 net_seq
)
497 if (unlikely(XFRM_SKB_CB(skb
)->seq
.input
.hi
!=
498 htonl(xfrm_replay_seqhi(x
, net_seq
)))) {
499 x
->stats
.replay_window
++;
503 return xfrm_replay_check_esn(x
, skb
, net_seq
);
506 static void xfrm_replay_advance_esn(struct xfrm_state
*x
, __be32 net_seq
)
508 unsigned int bitnr
, nr
, i
;
510 u32 diff
, pos
, seq
, seq_hi
;
511 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
513 if (!replay_esn
->replay_window
)
516 seq
= ntohl(net_seq
);
517 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
518 seq_hi
= xfrm_replay_seqhi(x
, net_seq
);
519 wrap
= seq_hi
- replay_esn
->seq_hi
;
521 if ((!wrap
&& seq
> replay_esn
->seq
) || wrap
> 0) {
523 diff
= seq
- replay_esn
->seq
;
525 diff
= ~replay_esn
->seq
+ seq
+ 1;
527 if (diff
< replay_esn
->replay_window
) {
528 for (i
= 1; i
< diff
; i
++) {
529 bitnr
= (pos
+ i
) % replay_esn
->replay_window
;
531 bitnr
= bitnr
& 0x1F;
532 replay_esn
->bmp
[nr
] &= ~(1U << bitnr
);
535 nr
= (replay_esn
->replay_window
- 1) >> 5;
536 for (i
= 0; i
<= nr
; i
++)
537 replay_esn
->bmp
[i
] = 0;
540 bitnr
= (pos
+ diff
) % replay_esn
->replay_window
;
541 replay_esn
->seq
= seq
;
543 if (unlikely(wrap
> 0))
544 replay_esn
->seq_hi
++;
546 diff
= replay_esn
->seq
- seq
;
549 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
551 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
555 bitnr
= bitnr
& 0x1F;
556 replay_esn
->bmp
[nr
] |= (1U << bitnr
);
558 if (xfrm_aevent_is_on(xs_net(x
)))
559 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
562 #ifdef CONFIG_XFRM_OFFLOAD
563 static int xfrm_replay_overflow_offload(struct xfrm_state
*x
, struct sk_buff
*skb
)
566 struct net
*net
= xs_net(x
);
567 struct xfrm_offload
*xo
= xfrm_offload(skb
);
568 __u32 oseq
= x
->replay
.oseq
;
571 return xfrm_replay_overflow(x
, skb
);
573 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
574 if (!skb_is_gso(skb
)) {
575 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++oseq
;
578 XFRM_SKB_CB(skb
)->seq
.output
.low
= oseq
+ 1;
579 xo
->seq
.low
= oseq
+ 1;
580 oseq
+= skb_shinfo(skb
)->gso_segs
;
583 XFRM_SKB_CB(skb
)->seq
.output
.hi
= 0;
585 if (unlikely(oseq
< x
->replay
.oseq
)) {
586 xfrm_audit_state_replay_overflow(x
, skb
);
592 x
->replay
.oseq
= oseq
;
594 if (xfrm_aevent_is_on(net
))
595 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
601 static int xfrm_replay_overflow_offload_bmp(struct xfrm_state
*x
, struct sk_buff
*skb
)
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
;
610 return xfrm_replay_overflow_bmp(x
, skb
);
612 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
613 if (!skb_is_gso(skb
)) {
614 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++oseq
;
617 XFRM_SKB_CB(skb
)->seq
.output
.low
= oseq
+ 1;
618 xo
->seq
.low
= oseq
+ 1;
619 oseq
+= skb_shinfo(skb
)->gso_segs
;
622 XFRM_SKB_CB(skb
)->seq
.output
.hi
= 0;
624 if (unlikely(oseq
< replay_esn
->oseq
)) {
625 xfrm_audit_state_replay_overflow(x
, skb
);
630 replay_esn
->oseq
= oseq
;
633 if (xfrm_aevent_is_on(net
))
634 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
640 static int xfrm_replay_overflow_offload_esn(struct xfrm_state
*x
, struct sk_buff
*skb
)
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
;
650 return xfrm_replay_overflow_esn(x
, skb
);
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
;
657 xo
->seq
.hi
= oseq_hi
;
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
+ 1;
662 xo
->seq
.hi
= oseq_hi
;
663 oseq
+= skb_shinfo(skb
)->gso_segs
;
666 if (unlikely(oseq
< replay_esn
->oseq
)) {
667 XFRM_SKB_CB(skb
)->seq
.output
.hi
= ++oseq_hi
;
668 xo
->seq
.hi
= oseq_hi
;
669 replay_esn
->oseq_hi
= oseq_hi
;
670 if (replay_esn
->oseq_hi
== 0) {
672 replay_esn
->oseq_hi
--;
673 xfrm_audit_state_replay_overflow(x
, skb
);
680 replay_esn
->oseq
= oseq
;
682 if (xfrm_aevent_is_on(net
))
683 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
689 static const struct xfrm_replay xfrm_replay_legacy
= {
690 .advance
= xfrm_replay_advance
,
691 .check
= xfrm_replay_check
,
692 .recheck
= xfrm_replay_check
,
693 .notify
= xfrm_replay_notify
,
694 .overflow
= xfrm_replay_overflow_offload
,
697 static const struct xfrm_replay xfrm_replay_bmp
= {
698 .advance
= xfrm_replay_advance_bmp
,
699 .check
= xfrm_replay_check_bmp
,
700 .recheck
= xfrm_replay_check_bmp
,
701 .notify
= xfrm_replay_notify_bmp
,
702 .overflow
= xfrm_replay_overflow_offload_bmp
,
705 static const struct xfrm_replay xfrm_replay_esn
= {
706 .advance
= xfrm_replay_advance_esn
,
707 .check
= xfrm_replay_check_esn
,
708 .recheck
= xfrm_replay_recheck_esn
,
709 .notify
= xfrm_replay_notify_esn
,
710 .overflow
= xfrm_replay_overflow_offload_esn
,
713 static const struct xfrm_replay xfrm_replay_legacy
= {
714 .advance
= xfrm_replay_advance
,
715 .check
= xfrm_replay_check
,
716 .recheck
= xfrm_replay_check
,
717 .notify
= xfrm_replay_notify
,
718 .overflow
= xfrm_replay_overflow
,
721 static const struct xfrm_replay xfrm_replay_bmp
= {
722 .advance
= xfrm_replay_advance_bmp
,
723 .check
= xfrm_replay_check_bmp
,
724 .recheck
= xfrm_replay_check_bmp
,
725 .notify
= xfrm_replay_notify_bmp
,
726 .overflow
= xfrm_replay_overflow_bmp
,
729 static const struct xfrm_replay xfrm_replay_esn
= {
730 .advance
= xfrm_replay_advance_esn
,
731 .check
= xfrm_replay_check_esn
,
732 .recheck
= xfrm_replay_recheck_esn
,
733 .notify
= xfrm_replay_notify_esn
,
734 .overflow
= xfrm_replay_overflow_esn
,
738 int xfrm_init_replay(struct xfrm_state
*x
)
740 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
743 if (replay_esn
->replay_window
>
744 replay_esn
->bmp_len
* sizeof(__u32
) * 8)
747 if (x
->props
.flags
& XFRM_STATE_ESN
) {
748 if (replay_esn
->replay_window
== 0)
750 x
->repl
= &xfrm_replay_esn
;
752 x
->repl
= &xfrm_replay_bmp
;
755 x
->repl
= &xfrm_replay_legacy
;
760 EXPORT_SYMBOL(xfrm_init_replay
);