mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
[IPSEC]: Sync series - core changes
This patch provides the core functionality needed for sync events for ipsec. Derived work of Krisztian KOVACS <hidden@balabit.hu> Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f5539eb8ca
commit
f8cd54884e
6 changed files with 176 additions and 3 deletions
|
@ -261,6 +261,8 @@ enum
|
||||||
NET_CORE_DEV_WEIGHT=17,
|
NET_CORE_DEV_WEIGHT=17,
|
||||||
NET_CORE_SOMAXCONN=18,
|
NET_CORE_SOMAXCONN=18,
|
||||||
NET_CORE_BUDGET=19,
|
NET_CORE_BUDGET=19,
|
||||||
|
NET_CORE_AEVENT_ETIME=20,
|
||||||
|
NET_CORE_AEVENT_RSEQTH=21,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* /proc/sys/net/ethernet */
|
/* /proc/sys/net/ethernet */
|
||||||
|
|
|
@ -156,6 +156,10 @@ enum {
|
||||||
XFRM_MSG_FLUSHPOLICY,
|
XFRM_MSG_FLUSHPOLICY,
|
||||||
#define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY
|
#define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY
|
||||||
|
|
||||||
|
XFRM_MSG_NEWAE,
|
||||||
|
#define XFRM_MSG_NEWAE XFRM_MSG_NEWAE
|
||||||
|
XFRM_MSG_GETAE,
|
||||||
|
#define XFRM_MSG_GETAE XFRM_MSG_GETAE
|
||||||
__XFRM_MSG_MAX
|
__XFRM_MSG_MAX
|
||||||
};
|
};
|
||||||
#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
|
#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
|
||||||
|
@ -194,6 +198,21 @@ struct xfrm_encap_tmpl {
|
||||||
xfrm_address_t encap_oa;
|
xfrm_address_t encap_oa;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* AEVENT flags */
|
||||||
|
enum xfrm_ae_ftype_t {
|
||||||
|
XFRM_AE_UNSPEC,
|
||||||
|
XFRM_AE_RTHR=1, /* replay threshold*/
|
||||||
|
XFRM_AE_RVAL=2, /* replay value */
|
||||||
|
XFRM_AE_LVAL=4, /* lifetime value */
|
||||||
|
XFRM_AE_ETHR=8, /* expiry timer threshold */
|
||||||
|
XFRM_AE_CR=16, /* Event cause is replay update */
|
||||||
|
XFRM_AE_CE=32, /* Event cause is timer expiry */
|
||||||
|
XFRM_AE_CU=64, /* Event cause is policy update */
|
||||||
|
__XFRM_AE_MAX
|
||||||
|
|
||||||
|
#define XFRM_AE_MAX (__XFRM_AE_MAX - 1)
|
||||||
|
};
|
||||||
|
|
||||||
/* Netlink message attributes. */
|
/* Netlink message attributes. */
|
||||||
enum xfrm_attr_type_t {
|
enum xfrm_attr_type_t {
|
||||||
XFRMA_UNSPEC,
|
XFRMA_UNSPEC,
|
||||||
|
@ -205,6 +224,10 @@ enum xfrm_attr_type_t {
|
||||||
XFRMA_SA,
|
XFRMA_SA,
|
||||||
XFRMA_POLICY,
|
XFRMA_POLICY,
|
||||||
XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */
|
XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */
|
||||||
|
XFRMA_LTIME_VAL,
|
||||||
|
XFRMA_REPLAY_VAL,
|
||||||
|
XFRMA_REPLAY_THRESH,
|
||||||
|
XFRMA_ETIMER_THRESH,
|
||||||
__XFRMA_MAX
|
__XFRMA_MAX
|
||||||
|
|
||||||
#define XFRMA_MAX (__XFRMA_MAX - 1)
|
#define XFRMA_MAX (__XFRMA_MAX - 1)
|
||||||
|
@ -235,6 +258,11 @@ struct xfrm_usersa_id {
|
||||||
__u8 proto;
|
__u8 proto;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xfrm_aevent_id {
|
||||||
|
__u32 flags;
|
||||||
|
struct xfrm_usersa_id sa_id;
|
||||||
|
};
|
||||||
|
|
||||||
struct xfrm_userspi_info {
|
struct xfrm_userspi_info {
|
||||||
struct xfrm_usersa_info info;
|
struct xfrm_usersa_info info;
|
||||||
__u32 min;
|
__u32 min;
|
||||||
|
@ -306,6 +334,8 @@ enum xfrm_nlgroups {
|
||||||
#define XFRMNLGRP_SA XFRMNLGRP_SA
|
#define XFRMNLGRP_SA XFRMNLGRP_SA
|
||||||
XFRMNLGRP_POLICY,
|
XFRMNLGRP_POLICY,
|
||||||
#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY
|
#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY
|
||||||
|
XFRMNLGRP_AEVENTS,
|
||||||
|
#define XFRMNLGRP_AEVENTS XFRMNLGRP_AEVENTS
|
||||||
__XFRMNLGRP_MAX
|
__XFRMNLGRP_MAX
|
||||||
};
|
};
|
||||||
#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1)
|
#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1)
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
|
|
||||||
#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
|
#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
|
||||||
|
|
||||||
|
extern struct sock *xfrm_nl;
|
||||||
|
extern u32 sysctl_xfrm_aevent_etime;
|
||||||
|
extern u32 sysctl_xfrm_aevent_rseqth;
|
||||||
|
|
||||||
extern struct semaphore xfrm_cfg_sem;
|
extern struct semaphore xfrm_cfg_sem;
|
||||||
|
|
||||||
/* Organization of SPD aka "XFRM rules"
|
/* Organization of SPD aka "XFRM rules"
|
||||||
|
@ -135,6 +139,16 @@ struct xfrm_state
|
||||||
/* State for replay detection */
|
/* State for replay detection */
|
||||||
struct xfrm_replay_state replay;
|
struct xfrm_replay_state replay;
|
||||||
|
|
||||||
|
/* Replay detection state at the time we sent the last notification */
|
||||||
|
struct xfrm_replay_state preplay;
|
||||||
|
|
||||||
|
/* Replay detection notification settings */
|
||||||
|
u32 replay_maxage;
|
||||||
|
u32 replay_maxdiff;
|
||||||
|
|
||||||
|
/* Replay detection notification timer */
|
||||||
|
struct timer_list rtimer;
|
||||||
|
|
||||||
/* Statistics */
|
/* Statistics */
|
||||||
struct xfrm_stats stats;
|
struct xfrm_stats stats;
|
||||||
|
|
||||||
|
@ -169,6 +183,7 @@ struct km_event
|
||||||
u32 hard;
|
u32 hard;
|
||||||
u32 proto;
|
u32 proto;
|
||||||
u32 byid;
|
u32 byid;
|
||||||
|
u32 aevent;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
u32 seq;
|
u32 seq;
|
||||||
|
@ -306,6 +321,20 @@ struct xfrm_policy
|
||||||
};
|
};
|
||||||
|
|
||||||
#define XFRM_KM_TIMEOUT 30
|
#define XFRM_KM_TIMEOUT 30
|
||||||
|
/* which seqno */
|
||||||
|
#define XFRM_REPLAY_SEQ 1
|
||||||
|
#define XFRM_REPLAY_OSEQ 2
|
||||||
|
#define XFRM_REPLAY_SEQ_MASK 3
|
||||||
|
/* what happened */
|
||||||
|
#define XFRM_REPLAY_UPDATE XFRM_AE_CR
|
||||||
|
#define XFRM_REPLAY_TIMEOUT XFRM_AE_CE
|
||||||
|
|
||||||
|
/* default aevent timeout in units of 100ms */
|
||||||
|
#define XFRM_AE_ETIME 10
|
||||||
|
/* Async Event timer multiplier */
|
||||||
|
#define XFRM_AE_ETH_M 10
|
||||||
|
/* default seq threshold size */
|
||||||
|
#define XFRM_AE_SEQT_SIZE 2
|
||||||
|
|
||||||
struct xfrm_mgr
|
struct xfrm_mgr
|
||||||
{
|
{
|
||||||
|
@ -865,6 +894,7 @@ extern int xfrm_state_delete(struct xfrm_state *x);
|
||||||
extern void xfrm_state_flush(u8 proto);
|
extern void xfrm_state_flush(u8 proto);
|
||||||
extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
|
extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
|
||||||
extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
|
extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
|
||||||
|
extern void xfrm_replay_notify(struct xfrm_state *x, int event);
|
||||||
extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
|
extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
|
||||||
extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
|
extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
|
||||||
extern int xfrm_init_state(struct xfrm_state *x);
|
extern int xfrm_init_state(struct xfrm_state *x);
|
||||||
|
@ -965,4 +995,16 @@ static inline int xfrm_policy_id2dir(u32 index)
|
||||||
return index & 7;
|
return index & 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int xfrm_aevent_is_on(void)
|
||||||
|
{
|
||||||
|
return netlink_has_listeners(xfrm_nl,XFRMNLGRP_AEVENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void xfrm_aevent_doreplay(struct xfrm_state *x)
|
||||||
|
{
|
||||||
|
if (xfrm_aevent_is_on())
|
||||||
|
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NET_XFRM_H */
|
#endif /* _NET_XFRM_H */
|
||||||
|
|
|
@ -26,6 +26,11 @@ extern int sysctl_core_destroy_delay;
|
||||||
extern char sysctl_divert_version[];
|
extern char sysctl_divert_version[];
|
||||||
#endif /* CONFIG_NET_DIVERT */
|
#endif /* CONFIG_NET_DIVERT */
|
||||||
|
|
||||||
|
#ifdef CONFIG_XFRM
|
||||||
|
extern u32 sysctl_xfrm_aevent_etime;
|
||||||
|
extern u32 sysctl_xfrm_aevent_rseqth;
|
||||||
|
#endif
|
||||||
|
|
||||||
ctl_table core_table[] = {
|
ctl_table core_table[] = {
|
||||||
#ifdef CONFIG_NET
|
#ifdef CONFIG_NET
|
||||||
{
|
{
|
||||||
|
@ -111,6 +116,24 @@ ctl_table core_table[] = {
|
||||||
.proc_handler = &proc_dostring
|
.proc_handler = &proc_dostring
|
||||||
},
|
},
|
||||||
#endif /* CONFIG_NET_DIVERT */
|
#endif /* CONFIG_NET_DIVERT */
|
||||||
|
#ifdef CONFIG_XFRM
|
||||||
|
{
|
||||||
|
.ctl_name = NET_CORE_AEVENT_ETIME,
|
||||||
|
.procname = "xfrm_aevent_etime",
|
||||||
|
.data = &sysctl_xfrm_aevent_etime,
|
||||||
|
.maxlen = sizeof(u32),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = &proc_dointvec
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctl_name = NET_CORE_AEVENT_RSEQTH,
|
||||||
|
.procname = "xfrm_aevent_rseqth",
|
||||||
|
.data = &sysctl_xfrm_aevent_rseqth,
|
||||||
|
.maxlen = sizeof(u32),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = &proc_dointvec
|
||||||
|
},
|
||||||
|
#endif /* CONFIG_XFRM */
|
||||||
#endif /* CONFIG_NET */
|
#endif /* CONFIG_NET */
|
||||||
{
|
{
|
||||||
.ctl_name = NET_CORE_SOMAXCONN,
|
.ctl_name = NET_CORE_SOMAXCONN,
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
|
u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
|
||||||
|
u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
|
||||||
/* Each xfrm_state may be linked to two tables:
|
/* Each xfrm_state may be linked to two tables:
|
||||||
|
|
||||||
1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
|
1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
|
||||||
|
@ -62,6 +64,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
|
||||||
{
|
{
|
||||||
if (del_timer(&x->timer))
|
if (del_timer(&x->timer))
|
||||||
BUG();
|
BUG();
|
||||||
|
if (del_timer(&x->rtimer))
|
||||||
|
BUG();
|
||||||
kfree(x->aalg);
|
kfree(x->aalg);
|
||||||
kfree(x->ealg);
|
kfree(x->ealg);
|
||||||
kfree(x->calg);
|
kfree(x->calg);
|
||||||
|
@ -190,11 +194,16 @@ struct xfrm_state *xfrm_state_alloc(void)
|
||||||
init_timer(&x->timer);
|
init_timer(&x->timer);
|
||||||
x->timer.function = xfrm_timer_handler;
|
x->timer.function = xfrm_timer_handler;
|
||||||
x->timer.data = (unsigned long)x;
|
x->timer.data = (unsigned long)x;
|
||||||
|
init_timer(&x->rtimer);
|
||||||
|
x->rtimer.function = xfrm_replay_timer_handler;
|
||||||
|
x->rtimer.data = (unsigned long)x;
|
||||||
x->curlft.add_time = (unsigned long)xtime.tv_sec;
|
x->curlft.add_time = (unsigned long)xtime.tv_sec;
|
||||||
x->lft.soft_byte_limit = XFRM_INF;
|
x->lft.soft_byte_limit = XFRM_INF;
|
||||||
x->lft.soft_packet_limit = XFRM_INF;
|
x->lft.soft_packet_limit = XFRM_INF;
|
||||||
x->lft.hard_byte_limit = XFRM_INF;
|
x->lft.hard_byte_limit = XFRM_INF;
|
||||||
x->lft.hard_packet_limit = XFRM_INF;
|
x->lft.hard_packet_limit = XFRM_INF;
|
||||||
|
x->replay_maxage = 0;
|
||||||
|
x->replay_maxdiff = 0;
|
||||||
spin_lock_init(&x->lock);
|
spin_lock_init(&x->lock);
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
|
@ -228,6 +237,8 @@ static int __xfrm_state_delete(struct xfrm_state *x)
|
||||||
spin_unlock(&xfrm_state_lock);
|
spin_unlock(&xfrm_state_lock);
|
||||||
if (del_timer(&x->timer))
|
if (del_timer(&x->timer))
|
||||||
__xfrm_state_put(x);
|
__xfrm_state_put(x);
|
||||||
|
if (del_timer(&x->rtimer))
|
||||||
|
__xfrm_state_put(x);
|
||||||
|
|
||||||
/* The number two in this test is the reference
|
/* The number two in this test is the reference
|
||||||
* mentioned in the comment below plus the reference
|
* mentioned in the comment below plus the reference
|
||||||
|
@ -426,6 +437,10 @@ static void __xfrm_state_insert(struct xfrm_state *x)
|
||||||
if (!mod_timer(&x->timer, jiffies + HZ))
|
if (!mod_timer(&x->timer, jiffies + HZ))
|
||||||
xfrm_state_hold(x);
|
xfrm_state_hold(x);
|
||||||
|
|
||||||
|
if (x->replay_maxage &&
|
||||||
|
!mod_timer(&x->rtimer, jiffies + x->replay_maxage))
|
||||||
|
xfrm_state_hold(x);
|
||||||
|
|
||||||
wake_up(&km_waitq);
|
wake_up(&km_waitq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,6 +777,62 @@ out:
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(xfrm_state_walk);
|
EXPORT_SYMBOL(xfrm_state_walk);
|
||||||
|
|
||||||
|
|
||||||
|
void xfrm_replay_notify(struct xfrm_state *x, int event)
|
||||||
|
{
|
||||||
|
struct km_event c;
|
||||||
|
/* we send notify messages in case
|
||||||
|
* 1. we updated on of the sequence numbers, and the seqno difference
|
||||||
|
* is at least x->replay_maxdiff, in this case we also update the
|
||||||
|
* timeout of our timer function
|
||||||
|
* 2. if x->replay_maxage has elapsed since last update,
|
||||||
|
* and there were changes
|
||||||
|
*
|
||||||
|
* The state structure must be locked!
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case XFRM_REPLAY_UPDATE:
|
||||||
|
if (x->replay_maxdiff &&
|
||||||
|
(x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
|
||||||
|
(x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))
|
||||||
|
return;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XFRM_REPLAY_TIMEOUT:
|
||||||
|
if ((x->replay.seq == x->preplay.seq) &&
|
||||||
|
(x->replay.bitmap == x->preplay.bitmap) &&
|
||||||
|
(x->replay.oseq == x->preplay.oseq))
|
||||||
|
return;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
|
||||||
|
c.event = XFRM_MSG_NEWAE;
|
||||||
|
c.data.aevent = event;
|
||||||
|
km_state_notify(x, &c);
|
||||||
|
|
||||||
|
resched:
|
||||||
|
if (x->replay_maxage &&
|
||||||
|
!mod_timer(&x->rtimer, jiffies + x->replay_maxage))
|
||||||
|
xfrm_state_hold(x);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xfrm_replay_timer_handler(unsigned long data)
|
||||||
|
{
|
||||||
|
struct xfrm_state *x = (struct xfrm_state*)data;
|
||||||
|
|
||||||
|
spin_lock(&x->lock);
|
||||||
|
|
||||||
|
if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID)
|
||||||
|
xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
|
||||||
|
|
||||||
|
spin_unlock(&x->lock);
|
||||||
|
}
|
||||||
|
|
||||||
int xfrm_replay_check(struct xfrm_state *x, u32 seq)
|
int xfrm_replay_check(struct xfrm_state *x, u32 seq)
|
||||||
{
|
{
|
||||||
u32 diff;
|
u32 diff;
|
||||||
|
@ -805,6 +876,9 @@ void xfrm_replay_advance(struct xfrm_state *x, u32 seq)
|
||||||
diff = x->replay.seq - seq;
|
diff = x->replay.seq - seq;
|
||||||
x->replay.bitmap |= (1U << diff);
|
x->replay.bitmap |= (1U << diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xfrm_aevent_is_on())
|
||||||
|
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(xfrm_replay_advance);
|
EXPORT_SYMBOL(xfrm_replay_advance);
|
||||||
|
|
||||||
|
@ -835,7 +909,7 @@ void km_state_notify(struct xfrm_state *x, struct km_event *c)
|
||||||
EXPORT_SYMBOL(km_policy_notify);
|
EXPORT_SYMBOL(km_policy_notify);
|
||||||
EXPORT_SYMBOL(km_state_notify);
|
EXPORT_SYMBOL(km_state_notify);
|
||||||
|
|
||||||
static void km_state_expired(struct xfrm_state *x, int hard)
|
void km_state_expired(struct xfrm_state *x, int hard)
|
||||||
{
|
{
|
||||||
struct km_event c;
|
struct km_event c;
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <net/netlink.h>
|
#include <net/netlink.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
static struct sock *xfrm_nl;
|
struct sock *xfrm_nl;
|
||||||
|
|
||||||
static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
|
static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
|
||||||
{
|
{
|
||||||
|
@ -1618,3 +1618,5 @@ module_init(xfrm_user_init);
|
||||||
module_exit(xfrm_user_exit);
|
module_exit(xfrm_user_exit);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);
|
MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);
|
||||||
|
EXPORT_SYMBOL(xfrm_nl);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue