[IPSEC 4/4] Policy Expiration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Dave:
  
This patch finally adds policy expiration.

Note that it resends soft policy expire messages every 30 seconds.  This
is needed as when "soft use expire" is used for dead peer detection,
a lost message could lead to a dead peer that isn't discovered until the
SAs expire.

I've only implemented notification for XFRM as I didn't want to just add
another PFKEY extension in case it collides with something else.  Of
course it could be easily done for PFKEY with an extension too.
-- 
Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ )
Email:  Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: kernel-source-2.5/include/linux/xfrm.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/linux/xfrm.h,v
retrieving revision 1.3
diff -u -r1.3 xfrm.h
--- kernel-source-2.5/include/linux/xfrm.h	2 Jul 2003 09:14:19 -0000	1.3
+++ kernel-source-2.5/include/linux/xfrm.h	5 Jul 2003 10:22:52 -0000
@@ -119,7 +119,9 @@
 #define XFRM_MSG_UPDPOLICY	(XFRM_MSG_BASE + 9)
 #define XFRM_MSG_UPDSA		(XFRM_MSG_BASE + 10)
 
-#define XFRM_MSG_MAX		(XFRM_MSG_UPDSA+1)
+#define XFRM_MSG_POLEXPIRE	(XFRM_MSG_BASE + 11)
+
+#define XFRM_MSG_MAX		(XFRM_MSG_POLEXPIRE+1)
 
 struct xfrm_user_tmpl {
 	struct xfrm_id		id;
@@ -214,6 +216,11 @@
 
 struct xfrm_user_expire {
 	struct xfrm_usersa_info		state;
+	__u8				hard;
+};
+
+struct xfrm_user_polexpire {
+	struct xfrm_userpolicy_info	pol;
 	__u8				hard;
 };
 
Index: kernel-source-2.5/include/net/xfrm.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/xfrm.h,v
retrieving revision 1.10
diff -u -r1.10 xfrm.h
--- kernel-source-2.5/include/net/xfrm.h	5 Jul 2003 07:58:16 -0000	1.10
+++ kernel-source-2.5/include/net/xfrm.h	5 Jul 2003 11:04:32 -0000
@@ -289,6 +289,8 @@
 	struct xfrm_tmpl       	xfrm_vec[XFRM_MAX_DEPTH];
 };
 
+#define XFRM_KM_TIMEOUT		30
+
 struct xfrm_mgr
 {
 	struct list_head	list;
@@ -297,6 +299,7 @@
 	int			(*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
 	struct xfrm_policy	*(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir);
 	int			(*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
+	int			(*notify_policy)(struct xfrm_policy *x, int dir, int event);
 };
 
 extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -814,6 +817,7 @@
 extern void km_state_expired(struct xfrm_state *x, int hard);
 extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *pol);
 extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
+extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard);
 
 extern void xfrm4_input_init(void);
 extern void xfrm6_input_init(void);
Index: kernel-source-2.5/net/xfrm/xfrm_policy.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_policy.c,v
retrieving revision 1.16
diff -u -r1.16 xfrm_policy.c
--- kernel-source-2.5/net/xfrm/xfrm_policy.c	5 Jul 2003 07:36:20 -0000	1.16
+++ kernel-source-2.5/net/xfrm/xfrm_policy.c	5 Jul 2003 12:05:44 -0000
@@ -141,10 +141,14 @@
 	struct xfrm_policy *xp = (struct xfrm_policy*)data;
 	unsigned long now = (unsigned long)xtime.tv_sec;
 	long next = LONG_MAX;
+	int warn = 0;
+	int dir;
 
 	if (xp->dead)
 		goto out;
 
+	dir = xp->index & 7;
+
 	if (xp->lft.hard_add_expires_seconds) {
 		long tmo = xp->lft.hard_add_expires_seconds +
 			xp->curlft.add_time - now;
@@ -153,6 +157,37 @@
 		if (tmo < next)
 			next = tmo;
 	}
+	if (xp->lft.hard_use_expires_seconds) {
+		long tmo = xp->lft.hard_use_expires_seconds +
+			(xp->curlft.use_time ? : xp->curlft.add_time) - now;
+		if (tmo <= 0)
+			goto expired;
+		if (tmo < next)
+			next = tmo;
+	}
+	if (xp->lft.soft_add_expires_seconds) {
+		long tmo = xp->lft.soft_add_expires_seconds +
+			xp->curlft.add_time - now;
+		if (tmo <= 0) {
+			warn = 1;
+			tmo = XFRM_KM_TIMEOUT;
+		}
+		if (tmo < next)
+			next = tmo;
+	}
+	if (xp->lft.soft_use_expires_seconds) {
+		long tmo = xp->lft.soft_use_expires_seconds +
+			(xp->curlft.use_time ? : xp->curlft.add_time) - now;
+		if (tmo <= 0) {
+			warn = 1;
+			tmo = XFRM_KM_TIMEOUT;
+		}
+		if (tmo < next)
+			next = tmo;
+	}
+
+	if (warn)
+		km_policy_expired(xp, dir, 0);
 	if (next != LONG_MAX &&
 	    !mod_timer(&xp->timer, jiffies + make_jiffies(next)))
 		xfrm_pol_hold(xp);
@@ -162,7 +197,8 @@
 	return;
 
 expired:
-	xfrm_policy_delete(xp, xp->index & 7);
+	km_policy_expired(xp, dir, 1);
+	xfrm_policy_delete(xp, dir);
 	xfrm_pol_put(xp);
 }
 
@@ -314,8 +350,7 @@
 	policy->index = delpol ? delpol->index : xfrm_gen_index(dir);
 	policy->curlft.add_time = (unsigned long)xtime.tv_sec;
 	policy->curlft.use_time = 0;
-	if (policy->lft.hard_add_expires_seconds &&
-	    !mod_timer(&policy->timer, jiffies + HZ))
+	if (!mod_timer(&policy->timer, jiffies + HZ))
 		xfrm_pol_hold(policy);
 	write_unlock_bh(&xfrm_policy_lock);
 
Index: kernel-source-2.5/net/xfrm/xfrm_state.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_state.c,v
retrieving revision 1.5
diff -u -r1.5 xfrm_state.c
--- kernel-source-2.5/net/xfrm/xfrm_state.c	5 Jul 2003 07:58:16 -0000	1.5
+++ kernel-source-2.5/net/xfrm/xfrm_state.c	5 Jul 2003 11:04:17 -0000
@@ -796,6 +796,20 @@
 	return err;
 }
 
+void km_policy_expired(struct xfrm_policy *pol, int dir, int hard)
+{
+	struct xfrm_mgr *km;
+
+	read_lock(&xfrm_km_lock);
+	list_for_each_entry(km, &xfrm_km_list, list)
+		if (km->notify_policy)
+			km->notify_policy(pol, dir, hard);
+	read_unlock(&xfrm_km_lock);
+
+	if (hard)
+		wake_up(&km_waitq);
+}
+
 int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen)
 {
 	int err;
Index: kernel-source-2.5/net/xfrm/xfrm_user.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_user.c,v
retrieving revision 1.8
diff -u -r1.8 xfrm_user.c
--- kernel-source-2.5/net/xfrm/xfrm_user.c	5 Jul 2003 05:11:55 -0000	1.8
+++ kernel-source-2.5/net/xfrm/xfrm_user.c	5 Jul 2003 10:41:36 -0000
@@ -993,7 +993,7 @@
 	return -1;
 }
 
-static int xfrm_send_notify(struct xfrm_state *x, int hard)
+static int xfrm_send_state_notify(struct xfrm_state *x, int hard)
 {
 	struct sk_buff *skb;
 
@@ -1119,11 +1119,56 @@
 	return xp;
 }
 
+static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
+			   int dir, int hard)
+{
+	struct xfrm_user_polexpire *upe;
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
+
+	nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe));
+	upe = NLMSG_DATA(nlh);
+	nlh->nlmsg_flags = 0;
+
+	copy_to_user_policy(xp, &upe->pol, dir);
+	if (copy_to_user_tmpl(xp, skb) < 0)
+		goto nlmsg_failure;
+	upe->hard = !!hard;
+
+	nlh->nlmsg_len = skb->tail - b;
+	return skb->len;
+
+nlmsg_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard)
+{
+	struct sk_buff *skb;
+	size_t len;
+
+	len = sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr;
+	len = RTA_ALIGN(RTA_LENGTH(len));
+	len += NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)));
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	if (build_polexpire(skb, xp, dir, hard) < 0)
+		BUG();
+
+	NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
+
+	return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
+}
+
 static struct xfrm_mgr netlink_mgr = {
 	.id		= "netlink",
-	.notify		= xfrm_send_notify,
+	.notify		= xfrm_send_state_notify,
 	.acquire	= xfrm_send_acquire,
 	.compile_policy	= xfrm_compile_policy,
+	.notify_policy	= xfrm_send_policy_notify,
 };
 
 static int __init xfrm_user_init(void)

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux