diff options
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_state.c | 76 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 4 |
2 files changed, 78 insertions, 2 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 | ||
23 | u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME; | ||
24 | u32 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 | } |
763 | EXPORT_SYMBOL(xfrm_state_walk); | 778 | EXPORT_SYMBOL(xfrm_state_walk); |
764 | 779 | ||
780 | |||
781 | void 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 | |||
817 | resched: | ||
818 | if (x->replay_maxage && | ||
819 | !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) | ||
820 | xfrm_state_hold(x); | ||
821 | |||
822 | } | ||
823 | |||
824 | static 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 | |||
765 | int xfrm_replay_check(struct xfrm_state *x, u32 seq) | 836 | int 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 | } |
809 | EXPORT_SYMBOL(xfrm_replay_advance); | 883 | EXPORT_SYMBOL(xfrm_replay_advance); |
810 | 884 | ||
@@ -835,7 +909,7 @@ void km_state_notify(struct xfrm_state *x, struct km_event *c) | |||
835 | EXPORT_SYMBOL(km_policy_notify); | 909 | EXPORT_SYMBOL(km_policy_notify); |
836 | EXPORT_SYMBOL(km_state_notify); | 910 | EXPORT_SYMBOL(km_state_notify); |
837 | 911 | ||
838 | static void km_state_expired(struct xfrm_state *x, int hard) | 912 | void 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 | ||
31 | static struct sock *xfrm_nl; | 31 | struct sock *xfrm_nl; |
32 | 32 | ||
33 | static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) | 33 | static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) |
34 | { | 34 | { |
@@ -1618,3 +1618,5 @@ module_init(xfrm_user_init); | |||
1618 | module_exit(xfrm_user_exit); | 1618 | module_exit(xfrm_user_exit); |
1619 | MODULE_LICENSE("GPL"); | 1619 | MODULE_LICENSE("GPL"); |
1620 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM); | 1620 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM); |
1621 | EXPORT_SYMBOL(xfrm_nl); | ||
1622 | |||