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 <fw@strlen.de> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
parent
30ad6a84f6
commit
cfc61c598e
@ -145,6 +145,12 @@ enum {
|
|||||||
XFRM_MODE_FLAG_TUNNEL = 1,
|
XFRM_MODE_FLAG_TUNNEL = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum xfrm_replay_mode {
|
||||||
|
XFRM_REPLAY_MODE_LEGACY,
|
||||||
|
XFRM_REPLAY_MODE_BMP,
|
||||||
|
XFRM_REPLAY_MODE_ESN,
|
||||||
|
};
|
||||||
|
|
||||||
/* Full description of state of transformer. */
|
/* Full description of state of transformer. */
|
||||||
struct xfrm_state {
|
struct xfrm_state {
|
||||||
possible_net_t xs_net;
|
possible_net_t xs_net;
|
||||||
@ -218,6 +224,8 @@ struct xfrm_state {
|
|||||||
/* The functions for replay detection. */
|
/* The functions for replay detection. */
|
||||||
const struct xfrm_replay *repl;
|
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
|
/* internal flag that only holds state for delayed aevent at the
|
||||||
* moment
|
* moment
|
||||||
*/
|
*/
|
||||||
@ -305,7 +313,6 @@ struct xfrm_replay {
|
|||||||
int (*recheck)(struct xfrm_state *x,
|
int (*recheck)(struct xfrm_state *x,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
__be32 net_seq);
|
__be32 net_seq);
|
||||||
void (*notify)(struct xfrm_state *x, int event);
|
|
||||||
int (*overflow)(struct xfrm_state *x, struct sk_buff *skb);
|
int (*overflow)(struct xfrm_state *x, struct sk_buff *skb);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1715,6 +1722,8 @@ static inline int xfrm_policy_id2dir(u32 index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_XFRM
|
#ifdef CONFIG_XFRM
|
||||||
|
void xfrm_replay_notify(struct xfrm_state *x, int event);
|
||||||
|
|
||||||
static inline int xfrm_aevent_is_on(struct net *net)
|
static inline int xfrm_aevent_is_on(struct net *net)
|
||||||
{
|
{
|
||||||
struct sock *nlsk;
|
struct sock *nlsk;
|
||||||
|
@ -34,8 +34,11 @@ u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq)
|
|||||||
return seq_hi;
|
return seq_hi;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(xfrm_replay_seqhi);
|
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;
|
struct km_event c;
|
||||||
/* we send notify messages in case
|
/* 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!
|
* 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) {
|
switch (event) {
|
||||||
case XFRM_REPLAY_UPDATE:
|
case XFRM_REPLAY_UPDATE:
|
||||||
if (!x->replay_maxdiff ||
|
if (!x->replay_maxdiff ||
|
||||||
@ -98,7 +112,7 @@ static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (xfrm_aevent_is_on(net))
|
if (xfrm_aevent_is_on(net))
|
||||||
x->repl->notify(x, XFRM_REPLAY_UPDATE);
|
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
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)))
|
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)
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
if (xfrm_aevent_is_on(net))
|
if (xfrm_aevent_is_on(net))
|
||||||
x->repl->notify(x, XFRM_REPLAY_UPDATE);
|
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
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);
|
replay_esn->bmp[nr] |= (1U << bitnr);
|
||||||
|
|
||||||
if (xfrm_aevent_is_on(xs_net(x)))
|
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)
|
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))
|
if (xfrm_aevent_is_on(net))
|
||||||
x->repl->notify(x, XFRM_REPLAY_UPDATE);
|
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
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);
|
replay_esn->bmp[nr] |= (1U << bitnr);
|
||||||
|
|
||||||
if (xfrm_aevent_is_on(xs_net(x)))
|
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
|
#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;
|
x->replay.oseq = oseq;
|
||||||
|
|
||||||
if (xfrm_aevent_is_on(net))
|
if (xfrm_aevent_is_on(net))
|
||||||
x->repl->notify(x, XFRM_REPLAY_UPDATE);
|
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
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))
|
if (xfrm_aevent_is_on(net))
|
||||||
x->repl->notify(x, XFRM_REPLAY_UPDATE);
|
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@ -674,7 +688,7 @@ static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff
|
|||||||
replay_esn->oseq = oseq;
|
replay_esn->oseq = oseq;
|
||||||
|
|
||||||
if (xfrm_aevent_is_on(net))
|
if (xfrm_aevent_is_on(net))
|
||||||
x->repl->notify(x, XFRM_REPLAY_UPDATE);
|
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@ -684,7 +698,6 @@ static const struct xfrm_replay xfrm_replay_legacy = {
|
|||||||
.advance = xfrm_replay_advance,
|
.advance = xfrm_replay_advance,
|
||||||
.check = xfrm_replay_check,
|
.check = xfrm_replay_check,
|
||||||
.recheck = xfrm_replay_check,
|
.recheck = xfrm_replay_check,
|
||||||
.notify = xfrm_replay_notify,
|
|
||||||
.overflow = xfrm_replay_overflow_offload,
|
.overflow = xfrm_replay_overflow_offload,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -692,7 +705,6 @@ static const struct xfrm_replay xfrm_replay_bmp = {
|
|||||||
.advance = xfrm_replay_advance_bmp,
|
.advance = xfrm_replay_advance_bmp,
|
||||||
.check = xfrm_replay_check_bmp,
|
.check = xfrm_replay_check_bmp,
|
||||||
.recheck = xfrm_replay_check_bmp,
|
.recheck = xfrm_replay_check_bmp,
|
||||||
.notify = xfrm_replay_notify_bmp,
|
|
||||||
.overflow = xfrm_replay_overflow_offload_bmp,
|
.overflow = xfrm_replay_overflow_offload_bmp,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -700,7 +712,6 @@ static const struct xfrm_replay xfrm_replay_esn = {
|
|||||||
.advance = xfrm_replay_advance_esn,
|
.advance = xfrm_replay_advance_esn,
|
||||||
.check = xfrm_replay_check_esn,
|
.check = xfrm_replay_check_esn,
|
||||||
.recheck = xfrm_replay_recheck_esn,
|
.recheck = xfrm_replay_recheck_esn,
|
||||||
.notify = xfrm_replay_notify_esn,
|
|
||||||
.overflow = xfrm_replay_overflow_offload_esn,
|
.overflow = xfrm_replay_overflow_offload_esn,
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
@ -708,7 +719,6 @@ static const struct xfrm_replay xfrm_replay_legacy = {
|
|||||||
.advance = xfrm_replay_advance,
|
.advance = xfrm_replay_advance,
|
||||||
.check = xfrm_replay_check,
|
.check = xfrm_replay_check,
|
||||||
.recheck = xfrm_replay_check,
|
.recheck = xfrm_replay_check,
|
||||||
.notify = xfrm_replay_notify,
|
|
||||||
.overflow = xfrm_replay_overflow,
|
.overflow = xfrm_replay_overflow,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -716,7 +726,6 @@ static const struct xfrm_replay xfrm_replay_bmp = {
|
|||||||
.advance = xfrm_replay_advance_bmp,
|
.advance = xfrm_replay_advance_bmp,
|
||||||
.check = xfrm_replay_check_bmp,
|
.check = xfrm_replay_check_bmp,
|
||||||
.recheck = xfrm_replay_check_bmp,
|
.recheck = xfrm_replay_check_bmp,
|
||||||
.notify = xfrm_replay_notify_bmp,
|
|
||||||
.overflow = xfrm_replay_overflow_bmp,
|
.overflow = xfrm_replay_overflow_bmp,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -724,7 +733,6 @@ static const struct xfrm_replay xfrm_replay_esn = {
|
|||||||
.advance = xfrm_replay_advance_esn,
|
.advance = xfrm_replay_advance_esn,
|
||||||
.check = xfrm_replay_check_esn,
|
.check = xfrm_replay_check_esn,
|
||||||
.recheck = xfrm_replay_recheck_esn,
|
.recheck = xfrm_replay_recheck_esn,
|
||||||
.notify = xfrm_replay_notify_esn,
|
|
||||||
.overflow = xfrm_replay_overflow_esn,
|
.overflow = xfrm_replay_overflow_esn,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -742,11 +750,14 @@ int xfrm_init_replay(struct xfrm_state *x)
|
|||||||
if (replay_esn->replay_window == 0)
|
if (replay_esn->replay_window == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
x->repl = &xfrm_replay_esn;
|
x->repl = &xfrm_replay_esn;
|
||||||
|
x->repl_mode = XFRM_REPLAY_MODE_ESN;
|
||||||
} else {
|
} else {
|
||||||
x->repl = &xfrm_replay_bmp;
|
x->repl = &xfrm_replay_bmp;
|
||||||
|
x->repl_mode = XFRM_REPLAY_MODE_BMP;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
x->repl = &xfrm_replay_legacy;
|
x->repl = &xfrm_replay_legacy;
|
||||||
|
x->repl_mode = XFRM_REPLAY_MODE_LEGACY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2177,7 +2177,7 @@ static void xfrm_replay_timer_handler(struct timer_list *t)
|
|||||||
|
|
||||||
if (x->km.state == XFRM_STATE_VALID) {
|
if (x->km.state == XFRM_STATE_VALID) {
|
||||||
if (xfrm_aevent_is_on(xs_net(x)))
|
if (xfrm_aevent_is_on(xs_net(x)))
|
||||||
x->repl->notify(x, XFRM_REPLAY_TIMEOUT);
|
xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
|
||||||
else
|
else
|
||||||
x->xflags |= XFRM_TIME_DEFER;
|
x->xflags |= XFRM_TIME_DEFER;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user