aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamal Hadi Salim <hadi@cyberus.ca>2006-03-20 22:15:11 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-20 22:15:11 -0500
commitf8cd54884e675dfaf0c86cc7c088adb6ca9d7638 (patch)
tree7850e8ebebf1f8543c96acdd7c197003b3b4d54c
parentf5539eb8caa52a9198079df767cc1bb5494e69e3 (diff)
[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>
-rw-r--r--include/linux/sysctl.h2
-rw-r--r--include/linux/xfrm.h30
-rw-r--r--include/net/xfrm.h44
-rw-r--r--net/core/sysctl_net_core.c23
-rw-r--r--net/xfrm/xfrm_state.c76
-rw-r--r--net/xfrm/xfrm_user.c4
6 files changed, 176 insertions, 3 deletions
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 6e8880ea49e7..b686548f32e0 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -261,6 +261,8 @@ enum
261 NET_CORE_DEV_WEIGHT=17, 261 NET_CORE_DEV_WEIGHT=17,
262 NET_CORE_SOMAXCONN=18, 262 NET_CORE_SOMAXCONN=18,
263 NET_CORE_BUDGET=19, 263 NET_CORE_BUDGET=19,
264 NET_CORE_AEVENT_ETIME=20,
265 NET_CORE_AEVENT_RSEQTH=21,
264}; 266};
265 267
266/* /proc/sys/net/ethernet */ 268/* /proc/sys/net/ethernet */
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 82fbb758e28f..b54a12940ef6 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -156,6 +156,10 @@ enum {
156 XFRM_MSG_FLUSHPOLICY, 156 XFRM_MSG_FLUSHPOLICY,
157#define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY 157#define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY
158 158
159 XFRM_MSG_NEWAE,
160#define XFRM_MSG_NEWAE XFRM_MSG_NEWAE
161 XFRM_MSG_GETAE,
162#define XFRM_MSG_GETAE XFRM_MSG_GETAE
159 __XFRM_MSG_MAX 163 __XFRM_MSG_MAX
160}; 164};
161#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) 165#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@@ -194,6 +198,21 @@ struct xfrm_encap_tmpl {
194 xfrm_address_t encap_oa; 198 xfrm_address_t encap_oa;
195}; 199};
196 200
201/* AEVENT flags */
202enum xfrm_ae_ftype_t {
203 XFRM_AE_UNSPEC,
204 XFRM_AE_RTHR=1, /* replay threshold*/
205 XFRM_AE_RVAL=2, /* replay value */
206 XFRM_AE_LVAL=4, /* lifetime value */
207 XFRM_AE_ETHR=8, /* expiry timer threshold */
208 XFRM_AE_CR=16, /* Event cause is replay update */
209 XFRM_AE_CE=32, /* Event cause is timer expiry */
210 XFRM_AE_CU=64, /* Event cause is policy update */
211 __XFRM_AE_MAX
212
213#define XFRM_AE_MAX (__XFRM_AE_MAX - 1)
214};
215
197/* Netlink message attributes. */ 216/* Netlink message attributes. */
198enum xfrm_attr_type_t { 217enum xfrm_attr_type_t {
199 XFRMA_UNSPEC, 218 XFRMA_UNSPEC,
@@ -205,6 +224,10 @@ enum xfrm_attr_type_t {
205 XFRMA_SA, 224 XFRMA_SA,
206 XFRMA_POLICY, 225 XFRMA_POLICY,
207 XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */ 226 XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */
227 XFRMA_LTIME_VAL,
228 XFRMA_REPLAY_VAL,
229 XFRMA_REPLAY_THRESH,
230 XFRMA_ETIMER_THRESH,
208 __XFRMA_MAX 231 __XFRMA_MAX
209 232
210#define XFRMA_MAX (__XFRMA_MAX - 1) 233#define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -235,6 +258,11 @@ struct xfrm_usersa_id {
235 __u8 proto; 258 __u8 proto;
236}; 259};
237 260
261struct xfrm_aevent_id {
262 __u32 flags;
263 struct xfrm_usersa_id sa_id;
264};
265
238struct xfrm_userspi_info { 266struct xfrm_userspi_info {
239 struct xfrm_usersa_info info; 267 struct xfrm_usersa_info info;
240 __u32 min; 268 __u32 min;
@@ -306,6 +334,8 @@ enum xfrm_nlgroups {
306#define XFRMNLGRP_SA XFRMNLGRP_SA 334#define XFRMNLGRP_SA XFRMNLGRP_SA
307 XFRMNLGRP_POLICY, 335 XFRMNLGRP_POLICY,
308#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY 336#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY
337 XFRMNLGRP_AEVENTS,
338#define XFRMNLGRP_AEVENTS XFRMNLGRP_AEVENTS
309 __XFRMNLGRP_MAX 339 __XFRMNLGRP_MAX
310}; 340};
311#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1) 341#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 8d362c49b8a9..bc005e62e434 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -20,6 +20,10 @@
20 20
21#define XFRM_ALIGN8(len) (((len) + 7) & ~7) 21#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
22 22
23extern struct sock *xfrm_nl;
24extern u32 sysctl_xfrm_aevent_etime;
25extern u32 sysctl_xfrm_aevent_rseqth;
26
23extern struct semaphore xfrm_cfg_sem; 27extern struct semaphore xfrm_cfg_sem;
24 28
25/* Organization of SPD aka "XFRM rules" 29/* Organization of SPD aka "XFRM rules"
@@ -135,6 +139,16 @@ struct xfrm_state
135 /* State for replay detection */ 139 /* State for replay detection */
136 struct xfrm_replay_state replay; 140 struct xfrm_replay_state replay;
137 141
142 /* Replay detection state at the time we sent the last notification */
143 struct xfrm_replay_state preplay;
144
145 /* Replay detection notification settings */
146 u32 replay_maxage;
147 u32 replay_maxdiff;
148
149 /* Replay detection notification timer */
150 struct timer_list rtimer;
151
138 /* Statistics */ 152 /* Statistics */
139 struct xfrm_stats stats; 153 struct xfrm_stats stats;
140 154
@@ -169,6 +183,7 @@ struct km_event
169 u32 hard; 183 u32 hard;
170 u32 proto; 184 u32 proto;
171 u32 byid; 185 u32 byid;
186 u32 aevent;
172 } data; 187 } data;
173 188
174 u32 seq; 189 u32 seq;
@@ -305,7 +320,21 @@ struct xfrm_policy
305 struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; 320 struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH];
306}; 321};
307 322
308#define XFRM_KM_TIMEOUT 30 323#define XFRM_KM_TIMEOUT 30
324/* which seqno */
325#define XFRM_REPLAY_SEQ 1
326#define XFRM_REPLAY_OSEQ 2
327#define XFRM_REPLAY_SEQ_MASK 3
328/* what happened */
329#define XFRM_REPLAY_UPDATE XFRM_AE_CR
330#define XFRM_REPLAY_TIMEOUT XFRM_AE_CE
331
332/* default aevent timeout in units of 100ms */
333#define XFRM_AE_ETIME 10
334/* Async Event timer multiplier */
335#define XFRM_AE_ETH_M 10
336/* default seq threshold size */
337#define XFRM_AE_SEQT_SIZE 2
309 338
310struct xfrm_mgr 339struct xfrm_mgr
311{ 340{
@@ -865,6 +894,7 @@ extern int xfrm_state_delete(struct xfrm_state *x);
865extern void xfrm_state_flush(u8 proto); 894extern void xfrm_state_flush(u8 proto);
866extern int xfrm_replay_check(struct xfrm_state *x, u32 seq); 895extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
867extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); 896extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
897extern void xfrm_replay_notify(struct xfrm_state *x, int event);
868extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb); 898extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
869extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); 899extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
870extern int xfrm_init_state(struct xfrm_state *x); 900extern int xfrm_init_state(struct xfrm_state *x);
@@ -965,4 +995,16 @@ static inline int xfrm_policy_id2dir(u32 index)
965 return index & 7; 995 return index & 7;
966} 996}
967 997
998static inline int xfrm_aevent_is_on(void)
999{
1000 return netlink_has_listeners(xfrm_nl,XFRMNLGRP_AEVENTS);
1001}
1002
1003static inline void xfrm_aevent_doreplay(struct xfrm_state *x)
1004{
1005 if (xfrm_aevent_is_on())
1006 xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
1007}
1008
1009
968#endif /* _NET_XFRM_H */ 1010#endif /* _NET_XFRM_H */
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 2f278c8e4743..710453656721 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -26,6 +26,11 @@ extern int sysctl_core_destroy_delay;
26extern char sysctl_divert_version[]; 26extern char sysctl_divert_version[];
27#endif /* CONFIG_NET_DIVERT */ 27#endif /* CONFIG_NET_DIVERT */
28 28
29#ifdef CONFIG_XFRM
30extern u32 sysctl_xfrm_aevent_etime;
31extern u32 sysctl_xfrm_aevent_rseqth;
32#endif
33
29ctl_table core_table[] = { 34ctl_table core_table[] = {
30#ifdef CONFIG_NET 35#ifdef CONFIG_NET
31 { 36 {
@@ -111,6 +116,24 @@ ctl_table core_table[] = {
111 .proc_handler = &proc_dostring 116 .proc_handler = &proc_dostring
112 }, 117 },
113#endif /* CONFIG_NET_DIVERT */ 118#endif /* CONFIG_NET_DIVERT */
119#ifdef CONFIG_XFRM
120 {
121 .ctl_name = NET_CORE_AEVENT_ETIME,
122 .procname = "xfrm_aevent_etime",
123 .data = &sysctl_xfrm_aevent_etime,
124 .maxlen = sizeof(u32),
125 .mode = 0644,
126 .proc_handler = &proc_dointvec
127 },
128 {
129 .ctl_name = NET_CORE_AEVENT_RSEQTH,
130 .procname = "xfrm_aevent_rseqth",
131 .data = &sysctl_xfrm_aevent_rseqth,
132 .maxlen = sizeof(u32),
133 .mode = 0644,
134 .proc_handler = &proc_dointvec
135 },
136#endif /* CONFIG_XFRM */
114#endif /* CONFIG_NET */ 137#endif /* CONFIG_NET */
115 { 138 {
116 .ctl_name = NET_CORE_SOMAXCONN, 139 .ctl_name = NET_CORE_SOMAXCONN,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index c656cbaf35e8..8eaee499cad5 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -20,6 +20,8 @@
20#include <linux/module.h> 20#include <linux/module.h>
21#include <asm/uaccess.h> 21#include <asm/uaccess.h>
22 22
23u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
24u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
23/* Each xfrm_state may be linked to two tables: 25/* Each xfrm_state may be linked to two tables:
24 26
25 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) 27 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)
62{ 64{
63 if (del_timer(&x->timer)) 65 if (del_timer(&x->timer))
64 BUG(); 66 BUG();
67 if (del_timer(&x->rtimer))
68 BUG();
65 kfree(x->aalg); 69 kfree(x->aalg);
66 kfree(x->ealg); 70 kfree(x->ealg);
67 kfree(x->calg); 71 kfree(x->calg);
@@ -190,11 +194,16 @@ struct xfrm_state *xfrm_state_alloc(void)
190 init_timer(&x->timer); 194 init_timer(&x->timer);
191 x->timer.function = xfrm_timer_handler; 195 x->timer.function = xfrm_timer_handler;
192 x->timer.data = (unsigned long)x; 196 x->timer.data = (unsigned long)x;
197 init_timer(&x->rtimer);
198 x->rtimer.function = xfrm_replay_timer_handler;
199 x->rtimer.data = (unsigned long)x;
193 x->curlft.add_time = (unsigned long)xtime.tv_sec; 200 x->curlft.add_time = (unsigned long)xtime.tv_sec;
194 x->lft.soft_byte_limit = XFRM_INF; 201 x->lft.soft_byte_limit = XFRM_INF;
195 x->lft.soft_packet_limit = XFRM_INF; 202 x->lft.soft_packet_limit = XFRM_INF;
196 x->lft.hard_byte_limit = XFRM_INF; 203 x->lft.hard_byte_limit = XFRM_INF;
197 x->lft.hard_packet_limit = XFRM_INF; 204 x->lft.hard_packet_limit = XFRM_INF;
205 x->replay_maxage = 0;
206 x->replay_maxdiff = 0;
198 spin_lock_init(&x->lock); 207 spin_lock_init(&x->lock);
199 } 208 }
200 return x; 209 return x;
@@ -228,6 +237,8 @@ static int __xfrm_state_delete(struct xfrm_state *x)
228 spin_unlock(&xfrm_state_lock); 237 spin_unlock(&xfrm_state_lock);
229 if (del_timer(&x->timer)) 238 if (del_timer(&x->timer))
230 __xfrm_state_put(x); 239 __xfrm_state_put(x);
240 if (del_timer(&x->rtimer))
241 __xfrm_state_put(x);
231 242
232 /* The number two in this test is the reference 243 /* The number two in this test is the reference
233 * mentioned in the comment below plus the reference 244 * mentioned in the comment below plus the reference
@@ -426,6 +437,10 @@ static void __xfrm_state_insert(struct xfrm_state *x)
426 if (!mod_timer(&x->timer, jiffies + HZ)) 437 if (!mod_timer(&x->timer, jiffies + HZ))
427 xfrm_state_hold(x); 438 xfrm_state_hold(x);
428 439
440 if (x->replay_maxage &&
441 !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
442 xfrm_state_hold(x);
443
429 wake_up(&km_waitq); 444 wake_up(&km_waitq);
430} 445}
431 446
@@ -762,6 +777,62 @@ out:
762} 777}
763EXPORT_SYMBOL(xfrm_state_walk); 778EXPORT_SYMBOL(xfrm_state_walk);
764 779
780
781void xfrm_replay_notify(struct xfrm_state *x, int event)
782{
783 struct km_event c;
784 /* we send notify messages in case
785 * 1. we updated on of the sequence numbers, and the seqno difference
786 * is at least x->replay_maxdiff, in this case we also update the
787 * timeout of our timer function
788 * 2. if x->replay_maxage has elapsed since last update,
789 * and there were changes
790 *
791 * The state structure must be locked!
792 */
793
794 switch (event) {
795 case XFRM_REPLAY_UPDATE:
796 if (x->replay_maxdiff &&
797 (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
798 (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))
799 return;
800
801 break;
802
803 case XFRM_REPLAY_TIMEOUT:
804 if ((x->replay.seq == x->preplay.seq) &&
805 (x->replay.bitmap == x->preplay.bitmap) &&
806 (x->replay.oseq == x->preplay.oseq))
807 return;
808
809 break;
810 }
811
812 memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
813 c.event = XFRM_MSG_NEWAE;
814 c.data.aevent = event;
815 km_state_notify(x, &c);
816
817resched:
818 if (x->replay_maxage &&
819 !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
820 xfrm_state_hold(x);
821
822}
823
824static void xfrm_replay_timer_handler(unsigned long data)
825{
826 struct xfrm_state *x = (struct xfrm_state*)data;
827
828 spin_lock(&x->lock);
829
830 if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID)
831 xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
832
833 spin_unlock(&x->lock);
834}
835
765int xfrm_replay_check(struct xfrm_state *x, u32 seq) 836int xfrm_replay_check(struct xfrm_state *x, u32 seq)
766{ 837{
767 u32 diff; 838 u32 diff;
@@ -805,6 +876,9 @@ void xfrm_replay_advance(struct xfrm_state *x, u32 seq)
805 diff = x->replay.seq - seq; 876 diff = x->replay.seq - seq;
806 x->replay.bitmap |= (1U << diff); 877 x->replay.bitmap |= (1U << diff);
807 } 878 }
879
880 if (xfrm_aevent_is_on())
881 xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
808} 882}
809EXPORT_SYMBOL(xfrm_replay_advance); 883EXPORT_SYMBOL(xfrm_replay_advance);
810 884
@@ -835,7 +909,7 @@ void km_state_notify(struct xfrm_state *x, struct km_event *c)
835EXPORT_SYMBOL(km_policy_notify); 909EXPORT_SYMBOL(km_policy_notify);
836EXPORT_SYMBOL(km_state_notify); 910EXPORT_SYMBOL(km_state_notify);
837 911
838static void km_state_expired(struct xfrm_state *x, int hard) 912void km_state_expired(struct xfrm_state *x, int hard)
839{ 913{
840 struct km_event c; 914 struct km_event c;
841 915
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 7de17559249a..6f643e58e044 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -28,7 +28,7 @@
28#include <net/netlink.h> 28#include <net/netlink.h>
29#include <asm/uaccess.h> 29#include <asm/uaccess.h>
30 30
31static struct sock *xfrm_nl; 31struct sock *xfrm_nl;
32 32
33static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) 33static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
34{ 34{
@@ -1618,3 +1618,5 @@ module_init(xfrm_user_init);
1618module_exit(xfrm_user_exit); 1618module_exit(xfrm_user_exit);
1619MODULE_LICENSE("GPL"); 1619MODULE_LICENSE("GPL");
1620MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM); 1620MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);
1621EXPORT_SYMBOL(xfrm_nl);
1622