From cfc61c598e43772cc4f76b8fc40c5ec70675716b Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 18 Jun 2021 15:51:56 +0200 Subject: xfrm: replay: avoid xfrm replay notify indirection replay protection is implemented using a callback structure and then called via x->repl->notify(), x->repl->recheck(), and so on. all the differect functions are always built-in, so this could be direct calls instead. This first patch prepares for removal of the x->repl structure. Add an enum with the three available replay modes to the xfrm_state structure and then replace all x->repl->notify() calls by the new xfrm_replay_notify() helper. The helper checks the enum internally to adapt behaviour as needed. Signed-off-by: Florian Westphal Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_replay.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'net/xfrm/xfrm_replay.c') diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index c6a4338a0d08..5feeb65f00b3 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -34,8 +34,11 @@ u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq) return seq_hi; } EXPORT_SYMBOL(xfrm_replay_seqhi); -; -static void xfrm_replay_notify(struct xfrm_state *x, int event) + +static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event); +static void xfrm_replay_notify_esn(struct xfrm_state *x, int event); + +void xfrm_replay_notify(struct xfrm_state *x, int event) { struct km_event c; /* we send notify messages in case @@ -48,6 +51,17 @@ static void xfrm_replay_notify(struct xfrm_state *x, int event) * The state structure must be locked! */ + switch (x->repl_mode) { + case XFRM_REPLAY_MODE_LEGACY: + break; + case XFRM_REPLAY_MODE_BMP: + xfrm_replay_notify_bmp(x, event); + return; + case XFRM_REPLAY_MODE_ESN: + xfrm_replay_notify_esn(x, event); + return; + } + switch (event) { case XFRM_REPLAY_UPDATE: if (!x->replay_maxdiff || @@ -98,7 +112,7 @@ static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb) return err; } if (xfrm_aevent_is_on(net)) - x->repl->notify(x, XFRM_REPLAY_UPDATE); + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } return err; @@ -157,7 +171,7 @@ static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq) } if (xfrm_aevent_is_on(xs_net(x))) - x->repl->notify(x, XFRM_REPLAY_UPDATE); + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb) @@ -178,7 +192,7 @@ static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb) return err; } if (xfrm_aevent_is_on(net)) - x->repl->notify(x, XFRM_REPLAY_UPDATE); + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } return err; @@ -273,7 +287,7 @@ static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq) replay_esn->bmp[nr] |= (1U << bitnr); if (xfrm_aevent_is_on(xs_net(x))) - x->repl->notify(x, XFRM_REPLAY_UPDATE); + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event) @@ -416,7 +430,7 @@ static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb) } } if (xfrm_aevent_is_on(net)) - x->repl->notify(x, XFRM_REPLAY_UPDATE); + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } return err; @@ -548,7 +562,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) replay_esn->bmp[nr] |= (1U << bitnr); if (xfrm_aevent_is_on(xs_net(x))) - x->repl->notify(x, XFRM_REPLAY_UPDATE); + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } #ifdef CONFIG_XFRM_OFFLOAD @@ -585,7 +599,7 @@ static int xfrm_replay_overflow_offload(struct xfrm_state *x, struct sk_buff *sk x->replay.oseq = oseq; if (xfrm_aevent_is_on(net)) - x->repl->notify(x, XFRM_REPLAY_UPDATE); + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } return err; @@ -625,7 +639,7 @@ static int xfrm_replay_overflow_offload_bmp(struct xfrm_state *x, struct sk_buff } if (xfrm_aevent_is_on(net)) - x->repl->notify(x, XFRM_REPLAY_UPDATE); + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } return err; @@ -674,7 +688,7 @@ static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff replay_esn->oseq = oseq; if (xfrm_aevent_is_on(net)) - x->repl->notify(x, XFRM_REPLAY_UPDATE); + xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } return err; @@ -684,7 +698,6 @@ static const struct xfrm_replay xfrm_replay_legacy = { .advance = xfrm_replay_advance, .check = xfrm_replay_check, .recheck = xfrm_replay_check, - .notify = xfrm_replay_notify, .overflow = xfrm_replay_overflow_offload, }; @@ -692,7 +705,6 @@ static const struct xfrm_replay xfrm_replay_bmp = { .advance = xfrm_replay_advance_bmp, .check = xfrm_replay_check_bmp, .recheck = xfrm_replay_check_bmp, - .notify = xfrm_replay_notify_bmp, .overflow = xfrm_replay_overflow_offload_bmp, }; @@ -700,7 +712,6 @@ static const struct xfrm_replay xfrm_replay_esn = { .advance = xfrm_replay_advance_esn, .check = xfrm_replay_check_esn, .recheck = xfrm_replay_recheck_esn, - .notify = xfrm_replay_notify_esn, .overflow = xfrm_replay_overflow_offload_esn, }; #else @@ -708,7 +719,6 @@ static const struct xfrm_replay xfrm_replay_legacy = { .advance = xfrm_replay_advance, .check = xfrm_replay_check, .recheck = xfrm_replay_check, - .notify = xfrm_replay_notify, .overflow = xfrm_replay_overflow, }; @@ -716,7 +726,6 @@ static const struct xfrm_replay xfrm_replay_bmp = { .advance = xfrm_replay_advance_bmp, .check = xfrm_replay_check_bmp, .recheck = xfrm_replay_check_bmp, - .notify = xfrm_replay_notify_bmp, .overflow = xfrm_replay_overflow_bmp, }; @@ -724,7 +733,6 @@ static const struct xfrm_replay xfrm_replay_esn = { .advance = xfrm_replay_advance_esn, .check = xfrm_replay_check_esn, .recheck = xfrm_replay_recheck_esn, - .notify = xfrm_replay_notify_esn, .overflow = xfrm_replay_overflow_esn, }; #endif @@ -742,11 +750,14 @@ int xfrm_init_replay(struct xfrm_state *x) if (replay_esn->replay_window == 0) return -EINVAL; x->repl = &xfrm_replay_esn; + x->repl_mode = XFRM_REPLAY_MODE_ESN; } else { x->repl = &xfrm_replay_bmp; + x->repl_mode = XFRM_REPLAY_MODE_BMP; } } else { x->repl = &xfrm_replay_legacy; + x->repl_mode = XFRM_REPLAY_MODE_LEGACY; } return 0; -- cgit v1.2.3 From c7f877833c9f361be8e88d6b140d8314e80892aa Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 18 Jun 2021 15:51:57 +0200 Subject: xfrm: replay: remove advance indirection Similar to other patches: add a new helper to avoid an indirection. v2: fix 'net/xfrm/xfrm_replay.c:519:13: warning: 'seq' may be used uninitialized in this function' warning. Signed-off-by: Florian Westphal Signed-off-by: Steffen Klassert --- include/net/xfrm.h | 2 +- net/xfrm/xfrm_input.c | 2 +- net/xfrm/xfrm_replay.c | 24 +++++++++++++++--------- 3 files changed, 17 insertions(+), 11 deletions(-) (limited to 'net/xfrm/xfrm_replay.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 9a79e41defa7..a7f997b13198 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -306,7 +306,6 @@ struct km_event { }; struct xfrm_replay { - void (*advance)(struct xfrm_state *x, __be32 net_seq); int (*check)(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); @@ -1722,6 +1721,7 @@ static inline int xfrm_policy_id2dir(u32 index) } #ifdef CONFIG_XFRM +void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq); void xfrm_replay_notify(struct xfrm_state *x, int event); static inline int xfrm_aevent_is_on(struct net *net) diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 1158cd0311d7..c8971e4b33ab 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -665,7 +665,7 @@ resume: goto drop_unlock; } - x->repl->advance(x, seq); + xfrm_replay_advance(x, seq); x->curlft.bytes += skb->len; x->curlft.packets++; diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 5feeb65f00b3..9565b0f7d380 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -150,14 +150,26 @@ err: return -EINVAL; } -static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq) +static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq); +static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq); + +void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq) { - u32 diff; - u32 seq = ntohl(net_seq); + u32 diff, seq; + + switch (x->repl_mode) { + case XFRM_REPLAY_MODE_LEGACY: + break; + case XFRM_REPLAY_MODE_BMP: + return xfrm_replay_advance_bmp(x, net_seq); + case XFRM_REPLAY_MODE_ESN: + return xfrm_replay_advance_esn(x, net_seq); + } if (!x->props.replay_window) return; + seq = ntohl(net_seq); if (seq > x->replay.seq) { diff = seq - x->replay.seq; if (diff < x->props.replay_window) @@ -695,42 +707,36 @@ static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff } static const struct xfrm_replay xfrm_replay_legacy = { - .advance = xfrm_replay_advance, .check = xfrm_replay_check, .recheck = xfrm_replay_check, .overflow = xfrm_replay_overflow_offload, }; static const struct xfrm_replay xfrm_replay_bmp = { - .advance = xfrm_replay_advance_bmp, .check = xfrm_replay_check_bmp, .recheck = xfrm_replay_check_bmp, .overflow = xfrm_replay_overflow_offload_bmp, }; static const struct xfrm_replay xfrm_replay_esn = { - .advance = xfrm_replay_advance_esn, .check = xfrm_replay_check_esn, .recheck = xfrm_replay_recheck_esn, .overflow = xfrm_replay_overflow_offload_esn, }; #else static const struct xfrm_replay xfrm_replay_legacy = { - .advance = xfrm_replay_advance, .check = xfrm_replay_check, .recheck = xfrm_replay_check, .overflow = xfrm_replay_overflow, }; static const struct xfrm_replay xfrm_replay_bmp = { - .advance = xfrm_replay_advance_bmp, .check = xfrm_replay_check_bmp, .recheck = xfrm_replay_check_bmp, .overflow = xfrm_replay_overflow_bmp, }; static const struct xfrm_replay xfrm_replay_esn = { - .advance = xfrm_replay_advance_esn, .check = xfrm_replay_check_esn, .recheck = xfrm_replay_recheck_esn, .overflow = xfrm_replay_overflow_esn, -- cgit v1.2.3 From 25cfb8bc97c2b8447f86b1ad376ee672b6b173d4 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 18 Jun 2021 15:51:58 +0200 Subject: xfrm: replay: remove recheck indirection Adds new xfrm_replay_recheck() helper and calls it from xfrm input path instead of the indirection. Signed-off-by: Florian Westphal Signed-off-by: Steffen Klassert --- include/net/xfrm.h | 4 +--- net/xfrm/xfrm_input.c | 2 +- net/xfrm/xfrm_replay.c | 22 ++++++++++++++++------ 3 files changed, 18 insertions(+), 10 deletions(-) (limited to 'net/xfrm/xfrm_replay.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index a7f997b13198..3a219b34cb8c 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -309,9 +309,6 @@ struct xfrm_replay { int (*check)(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); - int (*recheck)(struct xfrm_state *x, - struct sk_buff *skb, - __be32 net_seq); int (*overflow)(struct xfrm_state *x, struct sk_buff *skb); }; @@ -1723,6 +1720,7 @@ static inline int xfrm_policy_id2dir(u32 index) #ifdef CONFIG_XFRM void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq); void xfrm_replay_notify(struct xfrm_state *x, int event); +int xfrm_replay_recheck(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); static inline int xfrm_aevent_is_on(struct net *net) { diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index c8971e4b33ab..8046ef1a6680 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -660,7 +660,7 @@ resume: /* only the first xfrm gets the encap type */ encap_type = 0; - if (x->repl->recheck(x, skb, seq)) { + if (xfrm_replay_recheck(x, skb, seq)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); goto drop_unlock; } diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 9565b0f7d380..59391dc80fa3 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -519,6 +519,22 @@ static int xfrm_replay_recheck_esn(struct xfrm_state *x, return xfrm_replay_check_esn(x, skb, net_seq); } +int xfrm_replay_recheck(struct xfrm_state *x, + struct sk_buff *skb, __be32 net_seq) +{ + switch (x->repl_mode) { + case XFRM_REPLAY_MODE_LEGACY: + break; + case XFRM_REPLAY_MODE_BMP: + /* no special recheck treatment */ + return xfrm_replay_check_bmp(x, skb, net_seq); + case XFRM_REPLAY_MODE_ESN: + return xfrm_replay_recheck_esn(x, skb, net_seq); + } + + return xfrm_replay_check(x, skb, net_seq); +} + static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) { unsigned int bitnr, nr, i; @@ -708,37 +724,31 @@ static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff static const struct xfrm_replay xfrm_replay_legacy = { .check = xfrm_replay_check, - .recheck = xfrm_replay_check, .overflow = xfrm_replay_overflow_offload, }; static const struct xfrm_replay xfrm_replay_bmp = { .check = xfrm_replay_check_bmp, - .recheck = xfrm_replay_check_bmp, .overflow = xfrm_replay_overflow_offload_bmp, }; static const struct xfrm_replay xfrm_replay_esn = { .check = xfrm_replay_check_esn, - .recheck = xfrm_replay_recheck_esn, .overflow = xfrm_replay_overflow_offload_esn, }; #else static const struct xfrm_replay xfrm_replay_legacy = { .check = xfrm_replay_check, - .recheck = xfrm_replay_check, .overflow = xfrm_replay_overflow, }; static const struct xfrm_replay xfrm_replay_bmp = { .check = xfrm_replay_check_bmp, - .recheck = xfrm_replay_check_bmp, .overflow = xfrm_replay_overflow_bmp, }; static const struct xfrm_replay xfrm_replay_esn = { .check = xfrm_replay_check_esn, - .recheck = xfrm_replay_recheck_esn, .overflow = xfrm_replay_overflow_esn, }; #endif -- cgit v1.2.3 From adfc2fdbae30d42edebad01d0ea1eed43036f1fe Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 18 Jun 2021 15:51:59 +0200 Subject: xfrm: replay: avoid replay indirection Add and use xfrm_replay_check helper instead of indirection. Signed-off-by: Florian Westphal Signed-off-by: Steffen Klassert --- include/net/xfrm.h | 4 +--- net/xfrm/xfrm_input.c | 2 +- net/xfrm/xfrm_replay.c | 27 ++++++++++++++++++--------- 3 files changed, 20 insertions(+), 13 deletions(-) (limited to 'net/xfrm/xfrm_replay.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 3a219b34cb8c..0206d80ec291 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -306,9 +306,6 @@ struct km_event { }; struct xfrm_replay { - int (*check)(struct xfrm_state *x, - struct sk_buff *skb, - __be32 net_seq); int (*overflow)(struct xfrm_state *x, struct sk_buff *skb); }; @@ -1719,6 +1716,7 @@ static inline int xfrm_policy_id2dir(u32 index) #ifdef CONFIG_XFRM void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq); +int xfrm_replay_check(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); void xfrm_replay_notify(struct xfrm_state *x, int event); int xfrm_replay_recheck(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 8046ef1a6680..3df0861d4390 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -612,7 +612,7 @@ lock: goto drop_unlock; } - if (x->repl->check(x, skb, seq)) { + if (xfrm_replay_check(x, skb, seq)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); goto drop_unlock; } diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 59391dc80fa3..e8703aa8d06a 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -118,8 +118,8 @@ static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb) return err; } -static int xfrm_replay_check(struct xfrm_state *x, - struct sk_buff *skb, __be32 net_seq) +static int xfrm_replay_check_legacy(struct xfrm_state *x, + struct sk_buff *skb, __be32 net_seq) { u32 diff; u32 seq = ntohl(net_seq); @@ -507,6 +507,21 @@ err: return -EINVAL; } +int xfrm_replay_check(struct xfrm_state *x, + struct sk_buff *skb, __be32 net_seq) +{ + switch (x->repl_mode) { + case XFRM_REPLAY_MODE_LEGACY: + break; + case XFRM_REPLAY_MODE_BMP: + return xfrm_replay_check_bmp(x, skb, net_seq); + case XFRM_REPLAY_MODE_ESN: + return xfrm_replay_check_esn(x, skb, net_seq); + } + + return xfrm_replay_check_legacy(x, skb, net_seq); +} + static int xfrm_replay_recheck_esn(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq) { @@ -532,7 +547,7 @@ int xfrm_replay_recheck(struct xfrm_state *x, return xfrm_replay_recheck_esn(x, skb, net_seq); } - return xfrm_replay_check(x, skb, net_seq); + return xfrm_replay_check_legacy(x, skb, net_seq); } static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) @@ -723,32 +738,26 @@ static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff } static const struct xfrm_replay xfrm_replay_legacy = { - .check = xfrm_replay_check, .overflow = xfrm_replay_overflow_offload, }; static const struct xfrm_replay xfrm_replay_bmp = { - .check = xfrm_replay_check_bmp, .overflow = xfrm_replay_overflow_offload_bmp, }; static const struct xfrm_replay xfrm_replay_esn = { - .check = xfrm_replay_check_esn, .overflow = xfrm_replay_overflow_offload_esn, }; #else static const struct xfrm_replay xfrm_replay_legacy = { - .check = xfrm_replay_check, .overflow = xfrm_replay_overflow, }; static const struct xfrm_replay xfrm_replay_bmp = { - .check = xfrm_replay_check_bmp, .overflow = xfrm_replay_overflow_bmp, }; static const struct xfrm_replay xfrm_replay_esn = { - .check = xfrm_replay_check_esn, .overflow = xfrm_replay_overflow_esn, }; #endif -- cgit v1.2.3 From b5a1d1fe0cbb9d20ba661134a09561af1dc9ebf5 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 18 Jun 2021 15:52:00 +0200 Subject: xfrm: replay: remove last replay indirection This replaces the overflow indirection with the new xfrm_replay_overflow helper. After this, the 'repl' pointer in xfrm_state is no longer needed and can be removed as well. xfrm_replay_overflow() is added in two incarnations, one is used when the kernel is compiled with xfrm hardware offload support enabled, the other when its disabled. Signed-off-by: Florian Westphal Signed-off-by: Steffen Klassert --- include/net/xfrm.h | 8 +------- net/xfrm/xfrm_output.c | 2 +- net/xfrm/xfrm_replay.c | 51 +++++++++++++++++++++++++------------------------- 3 files changed, 28 insertions(+), 33 deletions(-) (limited to 'net/xfrm/xfrm_replay.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 0206d80ec291..d2a0559c255f 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -221,9 +221,6 @@ struct xfrm_state { struct xfrm_replay_state preplay; struct xfrm_replay_state_esn *preplay_esn; - /* The functions for replay detection. */ - const struct xfrm_replay *repl; - /* replay detection mode */ enum xfrm_replay_mode repl_mode; /* internal flag that only holds state for delayed aevent at the @@ -305,10 +302,6 @@ struct km_event { struct net *net; }; -struct xfrm_replay { - int (*overflow)(struct xfrm_state *x, struct sk_buff *skb); -}; - struct xfrm_if_cb { struct xfrm_if *(*decode_session)(struct sk_buff *skb, unsigned short family); @@ -1718,6 +1711,7 @@ static inline int xfrm_policy_id2dir(u32 index) void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq); int xfrm_replay_check(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); void xfrm_replay_notify(struct xfrm_state *x, int event); +int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb); int xfrm_replay_recheck(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); static inline int xfrm_aevent_is_on(struct net *net) diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 0b2975ef0668..527da58464f3 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -525,7 +525,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) goto error; } - err = x->repl->overflow(x, skb); + err = xfrm_replay_overflow(x, skb); if (err) { XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATESEQERROR); goto error; diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index e8703aa8d06a..9277d81b344c 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -95,7 +95,7 @@ void xfrm_replay_notify(struct xfrm_state *x, int event) x->xflags &= ~XFRM_TIME_DEFER; } -static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb) +static int __xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb) { int err = 0; struct net *net = xs_net(x); @@ -617,7 +617,7 @@ static int xfrm_replay_overflow_offload(struct xfrm_state *x, struct sk_buff *sk __u32 oseq = x->replay.oseq; if (!xo) - return xfrm_replay_overflow(x, skb); + return __xfrm_replay_overflow(x, skb); if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { if (!skb_is_gso(skb)) { @@ -737,29 +737,33 @@ static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff return err; } -static const struct xfrm_replay xfrm_replay_legacy = { - .overflow = xfrm_replay_overflow_offload, -}; - -static const struct xfrm_replay xfrm_replay_bmp = { - .overflow = xfrm_replay_overflow_offload_bmp, -}; +int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb) +{ + switch (x->repl_mode) { + case XFRM_REPLAY_MODE_LEGACY: + break; + case XFRM_REPLAY_MODE_BMP: + return xfrm_replay_overflow_offload_bmp(x, skb); + case XFRM_REPLAY_MODE_ESN: + return xfrm_replay_overflow_offload_esn(x, skb); + } -static const struct xfrm_replay xfrm_replay_esn = { - .overflow = xfrm_replay_overflow_offload_esn, -}; + return xfrm_replay_overflow_offload(x, skb); +} #else -static const struct xfrm_replay xfrm_replay_legacy = { - .overflow = xfrm_replay_overflow, -}; - -static const struct xfrm_replay xfrm_replay_bmp = { - .overflow = xfrm_replay_overflow_bmp, -}; +int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb) +{ + switch (x->repl_mode) { + case XFRM_REPLAY_MODE_LEGACY: + break; + case XFRM_REPLAY_MODE_BMP: + return xfrm_replay_overflow_bmp(x, skb); + case XFRM_REPLAY_MODE_ESN: + return xfrm_replay_overflow_esn(x, skb); + } -static const struct xfrm_replay xfrm_replay_esn = { - .overflow = xfrm_replay_overflow_esn, -}; + return __xfrm_replay_overflow(x, skb); +} #endif int xfrm_init_replay(struct xfrm_state *x) @@ -774,14 +778,11 @@ int xfrm_init_replay(struct xfrm_state *x) if (x->props.flags & XFRM_STATE_ESN) { if (replay_esn->replay_window == 0) return -EINVAL; - x->repl = &xfrm_replay_esn; x->repl_mode = XFRM_REPLAY_MODE_ESN; } else { - x->repl = &xfrm_replay_bmp; x->repl_mode = XFRM_REPLAY_MODE_BMP; } } else { - x->repl = &xfrm_replay_legacy; x->repl_mode = XFRM_REPLAY_MODE_LEGACY; } -- cgit v1.2.3