aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
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 /net/xfrm/xfrm_state.c
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>
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c76
1 files changed, 75 insertions, 1 deletions
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