* [RFC] IPSEC failover and replay detection sequence numbers
@ 2004-10-29 10:23 KOVACS Krisztian
2004-10-29 12:58 ` jamal
2004-11-04 14:01 ` [Vpn-failover] [RFC] IPSEC failover - Netlink part Ulrich Weber
0 siblings, 2 replies; 11+ messages in thread
From: KOVACS Krisztian @ 2004-10-29 10:23 UTC (permalink / raw)
To: netdev, ipsec-tools-devel, vpn-failover
[-- Attachment #1: Type: text/plain, Size: 2247 bytes --]
Hi,
While developing an IPSEC failover solution we came to a problem of
replay detection sequence numbers used by IPSEC ESP and AH. To be able
to keep IPSEC SAs alive after a failing over to a slave, the state of
the SAs has to be available on the slave node(s) as well. Except for the
sequence numbers this is not really a problem, since the state of an
already established SA does not change too often.
However, currently getting or setting the replay detection state of an
SA is not possible. Unfortunately the ability to get/set the replay
detection sequence number is not enough, it would be great if the key
management daemon could get state change notifications in certain cases.
The attached patch is an implementation of the concept, and consists
of the following parts:
* xfrm_state replay detection notification facility: calls the
registered callback functions if:
* the input/output sequence number is at least the value
sent in the last notification plus N
* at least T jiffies has elapsed since the last
notification and the sequence numbers have changed since
then
* the PFKEY implementation of the callback: sends notify pfkey
messages (new message type)
* the PFKEY extensions needed to get/set the parameters of the
notification messages (N and T) (new extension header)
* a new PFKEY message to explicitly set the replay detection state
of an already established SA (new message type)
As there are a couple of PFKEY changes which could possibly break
compatibility, I tried to implement these extensions so that they are
completely invisible unless the user-space explicitly requests
notifications to be sent. Both N and T parameters of a new SA default to
zero, and notification-related extension headers are sent only if these
were explicitly set to a non-zero value.
The xfrm-netlink parts are completely missing, but could be added
easily. The corresponding libipsec changes should be trivial as well.
Comments are welcome, especially since this is the first public
release of the patch and I'm not much of an xfrm/pfkey expert... :)
--
Regards,
Krisztian KOVACS
[-- Attachment #2: ipsec_rd_notify_200410251031.patch --]
[-- Type: text/x-patch, Size: 18453 bytes --]
Index: linux-2.6.9/include/linux/pfkeyv2.h
===================================================================
--- linux-2.6.9.orig/include/linux/pfkeyv2.h 2004-10-18 23:54:55.000000000 +0200
+++ linux-2.6.9/include/linux/pfkeyv2.h 2004-10-29 11:12:48.653359687 +0200
@@ -216,6 +216,25 @@
} __attribute__((packed));
/* sizeof(struct sadb_x_nat_t_port) == 8 */
+/* IPSEC failover support sequence number update notification */
+struct sadb_x_saseq {
+ uint16_t sadb_x_saseq_len;
+ uint16_t sadb_x_saseq_exttype;
+ uint32_t sadb_x_saseq_iseq;
+ uint32_t sadb_x_saseq_iwnd;
+ uint32_t sadb_x_saseq_oseq;
+} __attribute__((packed));
+/* sizeof(struct sadb_x_saseq) == 16 */
+
+struct sadb_x_saseq_notify {
+ uint16_t sadb_x_saseq_notify_len;
+ uint16_t sadb_x_saseq_notify_exttype;
+ uint32_t sadb_x_saseq_notify_maxdiff;
+ uint32_t sadb_x_saseq_notify_maxage;
+ uint32_t sadb_x_saseq_notify_reserved;
+} __attribute__((packed));
+/* sizeof(struct sadb_x_saseq_notify) == 16 */
+
/* Message types */
#define SADB_RESERVED 0
#define SADB_GETSPI 1
@@ -241,7 +260,9 @@
#define SADB_X_SPDEXPIRE 21
#define SADB_X_SPDDELETE2 22
#define SADB_X_NAT_T_NEW_MAPPING 23
-#define SADB_MAX 23
+#define SADB_X_SEQNO_NOTIFY 24
+#define SADB_X_SEQNO_UPDATE 25
+#define SADB_MAX 25
/* Security Association flags */
#define SADB_SAFLAGS_PFS 1
@@ -324,7 +345,10 @@
#define SADB_X_EXT_NAT_T_SPORT 21
#define SADB_X_EXT_NAT_T_DPORT 22
#define SADB_X_EXT_NAT_T_OA 23
-#define SADB_EXT_MAX 23
+/* The next two entries are for IPSEC failover sequence number update notifications */
+#define SADB_X_EXT_SASEQ 24
+#define SADB_X_EXT_SASEQ_NOTIFY 25
+#define SADB_EXT_MAX 25
/* Identity Extension values */
#define SADB_IDENTTYPE_RESERVED 0
Index: linux-2.6.9/include/net/xfrm.h
===================================================================
--- linux-2.6.9.orig/include/net/xfrm.h 2004-10-18 23:54:55.000000000 +0200
+++ linux-2.6.9/include/net/xfrm.h 2004-10-29 11:12:48.654359460 +0200
@@ -133,6 +133,16 @@
/* State for replay detection */
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 */
+ __u64 replay_maxage;
+ __u32 replay_maxdiff;
+
+ /* Replay detection notification timer */
+ struct timer_list rtimer;
+
/* Statistics */
struct xfrm_stats stats;
@@ -287,6 +297,15 @@
struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH];
};
+/* which seqno */
+#define XFRM_REPLAY_SEQ 1
+#define XFRM_REPLAY_OSEQ 2
+#define XFRM_REPLAY_SEQ_MASK 3
+/* what happened */
+#define XFRM_REPLAY_UPDATE 4
+#define XFRM_REPLAY_TIMEOUT 8
+#define XFRM_REPLAY_ACTION_MASK 12
+
#define XFRM_KM_TIMEOUT 30
struct xfrm_mgr
@@ -298,6 +317,7 @@
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);
+ int (*notify_seq)(struct xfrm_state *x, int event);
};
extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -812,6 +832,8 @@
extern void xfrm_state_flush(u8 proto);
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_notify(struct xfrm_state *x, int event);
+extern void xfrm_state_replay_update(struct xfrm_state *x, struct xfrm_replay_state *replay);
extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm4_rcv(struct sk_buff *skb);
Index: linux-2.6.9/net/ipv4/ah4.c
===================================================================
--- linux-2.6.9.orig/net/ipv4/ah4.c 2004-10-18 23:55:06.000000000 +0200
+++ linux-2.6.9/net/ipv4/ah4.c 2004-10-29 11:14:00.700963876 +0200
@@ -98,6 +98,7 @@
ah->reserved = 0;
ah->spi = x->id.spi;
ah->seq_no = htonl(++x->replay.oseq);
+ xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
ahp->icv(ahp, skb, ah->auth_data);
top_iph->tos = iph->tos;
Index: linux-2.6.9/net/ipv4/esp4.c
===================================================================
--- linux-2.6.9.orig/net/ipv4/esp4.c 2004-10-18 23:54:32.000000000 +0200
+++ linux-2.6.9/net/ipv4/esp4.c 2004-10-29 11:12:48.656359005 +0200
@@ -98,6 +98,8 @@
esph->spi = x->id.spi;
esph->seq_no = htonl(++x->replay.oseq);
+ xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+
if (esp->conf.ivlen)
crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
Index: linux-2.6.9/net/ipv6/ah6.c
===================================================================
--- linux-2.6.9.orig/net/ipv6/ah6.c 2004-10-18 23:54:39.000000000 +0200
+++ linux-2.6.9/net/ipv6/ah6.c 2004-10-29 11:14:23.076870730 +0200
@@ -214,6 +214,7 @@
ah->reserved = 0;
ah->spi = x->id.spi;
ah->seq_no = htonl(++x->replay.oseq);
+ xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
ahp->icv(ahp, skb, ah->auth_data);
err = 0;
Index: linux-2.6.9/net/ipv6/esp6.c
===================================================================
--- linux-2.6.9.orig/net/ipv6/esp6.c 2004-10-18 23:54:37.000000000 +0200
+++ linux-2.6.9/net/ipv6/esp6.c 2004-10-29 11:12:48.658358550 +0200
@@ -95,6 +95,8 @@
esph->spi = x->id.spi;
esph->seq_no = htonl(++x->replay.oseq);
+ xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+
if (esp->conf.ivlen)
crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
Index: linux-2.6.9/net/key/af_key.c
===================================================================
--- linux-2.6.9.orig/net/key/af_key.c 2004-10-18 23:55:36.000000000 +0200
+++ linux-2.6.9/net/key/af_key.c 2004-10-29 11:12:48.662357640 +0200
@@ -336,6 +336,7 @@
[SADB_X_EXT_NAT_T_SPORT] = (u8) sizeof(struct sadb_x_nat_t_port),
[SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port),
[SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address),
+ [SADB_X_EXT_SASEQ_NOTIFY] = (u8) sizeof(struct sadb_x_saseq_notify),
};
/* Verify sadb_address_{len,prefixlen} against sa_family. */
@@ -606,9 +607,9 @@
sizeof(struct sadb_lifetime) +
((hsc & 1) ? sizeof(struct sadb_lifetime) : 0) +
((hsc & 2) ? sizeof(struct sadb_lifetime) : 0) +
- sizeof(struct sadb_address)*2 +
- sockaddr_size*2 +
- sizeof(struct sadb_x_sa2);
+ sizeof(struct sadb_address)*2 +
+ sockaddr_size*2 +
+ sizeof(struct sadb_x_sa2);
/* identity & sensitivity */
if ((x->props.family == AF_INET &&
@@ -641,6 +642,9 @@
size += sizeof(struct sadb_x_nat_t_port);
}
+ if (x->replay_maxage || x->replay_maxdiff)
+ size += sizeof(struct sadb_x_saseq_notify);
+
skb = alloc_skb(size + 16, GFP_ATOMIC);
if (skb == NULL)
return ERR_PTR(-ENOBUFS);
@@ -892,6 +896,17 @@
n_port->sadb_x_nat_t_port_reserved = 0;
}
+ if (x->replay_maxage || x->replay_maxdiff) {
+ struct sadb_x_saseq_notify *seqn;
+
+ seqn = (struct sadb_x_saseq_notify *) skb_put(skb, sizeof (*seqn));
+ seqn->sadb_x_saseq_notify_len = sizeof(*seqn)/sizeof(uint64_t);
+ seqn->sadb_x_saseq_notify_exttype = SADB_X_EXT_SASEQ_NOTIFY;
+ seqn->sadb_x_saseq_notify_maxage = x->replay_maxage * 10 / HZ;
+ seqn->sadb_x_saseq_notify_maxdiff = x->replay_maxdiff;
+ seqn->sadb_x_saseq_notify_reserved = 0;
+ }
+
return skb;
}
@@ -1091,6 +1106,13 @@
}
}
+ if (ext_hdrs[SADB_X_EXT_SASEQ_NOTIFY-1]) {
+ struct sadb_x_saseq_notify *seqn = ext_hdrs[SADB_X_EXT_SASEQ_NOTIFY-1];
+
+ x->replay_maxage = seqn->sadb_x_saseq_notify_maxage * HZ / 10;
+ x->replay_maxdiff = seqn->sadb_x_saseq_notify_maxdiff;
+ }
+
x->type = xfrm_get_type(proto, x->props.family);
if (x->type == NULL) {
err = -ENOPROTOOPT;
@@ -2122,6 +2144,52 @@
return 0;
}
+static int pfkey_seqno_update(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+{
+ struct xfrm_state *x;
+ struct sadb_x_saseq *seq;
+ struct xfrm_replay_state replay;
+ struct sk_buff *skb_out;
+ struct sadb_msg *hdr_out;
+
+ if (!ext_hdrs[SADB_EXT_SA-1] ||
+ !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
+ ext_hdrs[SADB_EXT_ADDRESS_DST-1]))
+ return -EINVAL;
+
+ x = pfkey_xfrm_state_lookup(hdr, ext_hdrs);
+ if (x == NULL)
+ return -ESRCH;
+
+ seq = ext_hdrs[SADB_X_EXT_SASEQ-1];
+ if (!seq) {
+ xfrm_state_put(x);
+ return -EINVAL;
+ }
+
+ skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL);
+ if (!skb_out) {
+ xfrm_state_put(x);
+ return -ENOBUFS;
+ }
+
+ replay.seq = seq->sadb_x_saseq_iseq;
+ replay.bitmap = seq->sadb_x_saseq_iwnd;
+ replay.oseq = seq->sadb_x_saseq_oseq;
+
+ xfrm_state_replay_update(x, &replay);
+ xfrm_state_put(x);
+
+ hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg));
+ pfkey_hdr_dup(hdr_out, hdr);
+ hdr_out->sadb_msg_errno = (uint8_t) 0;
+ hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
+
+ pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, sk);
+
+ return 0;
+}
+
typedef int (*pfkey_handler)(struct sock *sk, struct sk_buff *skb,
struct sadb_msg *hdr, void **ext_hdrs);
static pfkey_handler pfkey_funcs[SADB_MAX + 1] = {
@@ -2147,6 +2215,7 @@
[SADB_X_SPDFLUSH] = pfkey_spdflush,
[SADB_X_SPDSETIDX] = pfkey_spdadd,
[SADB_X_SPDDELETE2] = pfkey_spdget,
+ [SADB_X_SEQNO_UPDATE] = pfkey_seqno_update,
};
static int pfkey_process(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr)
@@ -2688,6 +2757,134 @@
return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL);
}
+static int pfkey_send_replay_notify(struct xfrm_state *x, int event)
+{
+ struct sk_buff *skb;
+ struct sadb_msg *hdr;
+ struct sadb_sa *sa;
+ struct sadb_address *addr;
+ struct sockaddr_in *sin;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct sockaddr_in6 *sin6;
+#endif
+ struct sadb_x_saseq *seq;
+ int sockaddr_size;
+ int size;
+ __u8 satype = (x->id.proto == IPPROTO_ESP ? SADB_SATYPE_ESP : 0);
+
+ sockaddr_size = pfkey_sockaddr_size(x->props.family);
+ if (!sockaddr_size)
+ return -EINVAL;
+
+ if (!satype)
+ return -EINVAL;
+
+ size = sizeof(struct sadb_msg) +
+ sizeof(struct sadb_sa) +
+ sizeof(struct sadb_address) * 2 +
+ sockaddr_size * 2 +
+ sizeof(struct sadb_x_saseq);
+
+ skb = alloc_skb(size + 16, GFP_ATOMIC);
+ if (skb == NULL)
+ return -ENOMEM;
+
+ hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));
+ hdr->sadb_msg_version = PF_KEY_V2;
+ hdr->sadb_msg_type = SADB_X_SEQNO_NOTIFY;
+ hdr->sadb_msg_satype = satype;
+ hdr->sadb_msg_len = size / sizeof(uint64_t);
+ hdr->sadb_msg_errno = 0;
+ hdr->sadb_msg_reserved = 0;
+ hdr->sadb_msg_seq = x->km.seq;
+ hdr->sadb_msg_pid = 0;
+
+ /* SA */
+ sa = (struct sadb_sa *) skb_put(skb, sizeof(struct sadb_sa));
+ sa->sadb_sa_len = sizeof(struct sadb_sa)/sizeof(uint64_t);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_spi = x->id.spi;
+ sa->sadb_sa_replay = x->props.replay_window;
+ sa->sadb_sa_state = 0;
+ sa->sadb_sa_auth = 0;
+ sa->sadb_sa_encrypt = 0;
+ sa->sadb_sa_flags = 0;
+
+ /* src address */
+ addr = (struct sadb_address *) skb_put(skb,
+ sizeof(struct sadb_address) + sockaddr_size);
+ addr->sadb_address_len =
+ (sizeof(struct sadb_address) + sockaddr_size) / sizeof(uint64_t);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ addr->sadb_address_proto = 0;
+ addr->sadb_address_reserved = 0;
+ if (x->props.family == AF_INET) {
+ addr->sadb_address_prefixlen = 32;
+ sin = (struct sockaddr_in *) (addr + 1);
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = x->props.saddr.a4;
+ sin->sin_port = 0;
+ memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (x->props.family == AF_INET6) {
+ addr->sadb_address_prefixlen = 128;
+
+ sin6 = (struct sockaddr_in6 *) (addr + 1);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ memcpy(&sin6->sin6_addr, x->props.saddr.a6,
+ sizeof(struct in6_addr));
+ sin6->sin6_scope_id = 0;
+ }
+#endif
+ else
+ BUG();
+
+ /* dst address */
+ addr = (struct sadb_address *) skb_put(skb,
+ sizeof(struct sadb_address) + sockaddr_size);
+ addr->sadb_address_len =
+ (sizeof(struct sadb_address) + sockaddr_size) / sizeof(uint64_t);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ addr->sadb_address_proto = 0;
+ addr->sadb_address_reserved = 0;
+ if (x->props.family == AF_INET) {
+ addr->sadb_address_prefixlen = 32;
+ sin = (struct sockaddr_in *) (addr + 1);
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = x->id.daddr.a4;
+ sin->sin_port = 0;
+ memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ else if (x->props.family == AF_INET6) {
+ addr->sadb_address_prefixlen = 128;
+
+ sin6 = (struct sockaddr_in6 *) (addr + 1);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ memcpy(&sin6->sin6_addr, x->id.daddr.a6,
+ sizeof(struct in6_addr));
+ sin6->sin6_scope_id = 0;
+ }
+#endif
+ else
+ BUG();
+
+ /* replay detection sequence numbers */
+ seq = (struct sadb_x_saseq*) skb_put(skb, sizeof(*seq));
+ seq->sadb_x_saseq_len = sizeof(*seq)/sizeof(uint64_t);
+ seq->sadb_x_saseq_exttype = SADB_X_EXT_SASEQ;
+ seq->sadb_x_saseq_iseq = x->replay.seq;
+ seq->sadb_x_saseq_iwnd = x->replay.bitmap;
+ seq->sadb_x_saseq_oseq = x->replay.oseq;
+
+ return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL);
+}
+
static int pfkey_sendmsg(struct kiocb *kiocb,
struct socket *sock, struct msghdr *msg, size_t len)
{
@@ -2856,6 +3053,7 @@
.acquire = pfkey_send_acquire,
.compile_policy = pfkey_compile_policy,
.new_mapping = pfkey_send_new_mapping,
+ .notify_seq = pfkey_send_replay_notify,
};
static void __exit ipsec_pfkey_exit(void)
Index: linux-2.6.9/net/xfrm/xfrm_export.c
===================================================================
--- linux-2.6.9.orig/net/xfrm/xfrm_export.c 2004-10-18 23:54:27.000000000 +0200
+++ linux-2.6.9/net/xfrm/xfrm_export.c 2004-10-29 11:12:48.662357640 +0200
@@ -27,6 +27,8 @@
EXPORT_SYMBOL(xfrm_state_delete_tunnel);
EXPORT_SYMBOL(xfrm_replay_check);
EXPORT_SYMBOL(xfrm_replay_advance);
+EXPORT_SYMBOL(xfrm_replay_notify);
+EXPORT_SYMBOL(xfrm_state_replay_update);
EXPORT_SYMBOL(xfrm_check_selectors);
EXPORT_SYMBOL(__secpath_destroy);
EXPORT_SYMBOL(secpath_dup);
Index: linux-2.6.9/net/xfrm/xfrm_state.c
===================================================================
--- linux-2.6.9.orig/net/xfrm/xfrm_state.c 2004-10-18 23:54:40.000000000 +0200
+++ linux-2.6.9/net/xfrm/xfrm_state.c 2004-10-29 11:12:48.664357185 +0200
@@ -52,6 +52,8 @@
{
if (del_timer(&x->timer))
BUG();
+ if (del_timer(&x->rtimer))
+ BUG();
if (x->aalg)
kfree(x->aalg);
if (x->ealg)
@@ -92,6 +94,20 @@
return secs*HZ;
}
+void xfrm_replay_notify(struct xfrm_state *, int);
+
+static void xfrm_replay_timer_handler(unsigned long data)
+{
+ struct xfrm_state *x = (struct xfrm_state*)data;
+
+ spin_lock(&x->lock);
+
+ if (x->km.state == XFRM_STATE_VALID)
+ xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+
+ spin_unlock(&x->lock);
+}
+
static void xfrm_timer_handler(unsigned long data)
{
struct xfrm_state *x = (struct xfrm_state*)data;
@@ -178,11 +194,16 @@
init_timer(&x->timer);
x->timer.function = xfrm_timer_handler;
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->lft.soft_byte_limit = XFRM_INF;
x->lft.soft_packet_limit = XFRM_INF;
x->lft.hard_byte_limit = XFRM_INF;
x->lft.hard_packet_limit = XFRM_INF;
+ x->replay_maxage = 0;
+ x->replay_maxdiff = 0;
x->lock = SPIN_LOCK_UNLOCKED;
}
return x;
@@ -212,6 +233,8 @@
spin_unlock(&xfrm_state_lock);
if (del_timer(&x->timer))
atomic_dec(&x->refcnt);
+ if (del_timer(&x->rtimer))
+ atomic_dec(&x->refcnt);
/* The number two in this test is the reference
* mentioned in the comment below plus the reference
@@ -377,6 +400,10 @@
if (!mod_timer(&x->timer, jiffies + HZ))
xfrm_state_hold(x);
+ if (x->replay_maxage &&
+ !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+ xfrm_state_hold(x);
+
wake_up(&km_waitq);
}
@@ -696,6 +723,48 @@
}
+void km_replay_notify(struct xfrm_state *, int);
+
+void xfrm_replay_notify(struct xfrm_state *x, int event)
+{
+ /* 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 & XFRM_REPLAY_ACTION_MASK) {
+ 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))
+ goto resched;
+
+ break;
+ }
+
+ memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
+ km_replay_notify(x, event);
+
+resched:
+ if (x->replay_maxage &&
+ !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+ xfrm_state_hold(x);
+
+}
+
int xfrm_replay_check(struct xfrm_state *x, u32 seq)
{
u32 diff;
@@ -738,6 +807,16 @@
diff = x->replay.seq - seq;
x->replay.bitmap |= (1U << diff);
}
+
+ xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+}
+
+void xfrm_state_replay_update(struct xfrm_state *x, struct xfrm_replay_state *replay)
+{
+ spin_lock(&x->lock);
+ memcpy(&x->replay, replay, sizeof(*replay));
+ memcpy(&x->preplay, replay, sizeof(*replay));
+ spin_unlock(&x->lock);
}
int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl)
@@ -819,6 +898,17 @@
wake_up(&km_waitq);
}
+void km_replay_notify(struct xfrm_state *x, int event)
+{
+ struct xfrm_mgr *km;
+
+ read_lock(&xfrm_km_lock);
+ list_for_each_entry(km, &xfrm_km_list, list)
+ if (km->notify_seq)
+ km->notify_seq(x, event);
+ read_unlock(&xfrm_km_lock);
+}
+
int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
{
int err;
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [RFC] IPSEC failover and replay detection sequence numbers
2004-10-29 10:23 [RFC] IPSEC failover and replay detection sequence numbers KOVACS Krisztian
@ 2004-10-29 12:58 ` jamal
2004-10-29 13:24 ` KOVACS Krisztian
2004-11-07 17:42 ` Michael Richardson
2004-11-04 14:01 ` [Vpn-failover] [RFC] IPSEC failover - Netlink part Ulrich Weber
1 sibling, 2 replies; 11+ messages in thread
From: jamal @ 2004-10-29 12:58 UTC (permalink / raw)
To: KOVACS Krisztian; +Cc: netdev, ipsec-tools-devel, vpn-failover
Krisztian,
To take a rough estimate of 5K users, how often do you think
these replay messages will be generated?
Is there a (clever) way to avoid transporting them and still achieve
an accurate failover?
cheers,
jamal
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] IPSEC failover and replay detection sequence numbers
2004-10-29 12:58 ` jamal
@ 2004-10-29 13:24 ` KOVACS Krisztian
2004-10-29 15:01 ` jamal
2004-11-07 17:42 ` Michael Richardson
1 sibling, 1 reply; 11+ messages in thread
From: KOVACS Krisztian @ 2004-10-29 13:24 UTC (permalink / raw)
To: hadi; +Cc: netdev, ipsec-tools-devel, vpn-failover
Hi,
2004-10-29, p keltezéssel 14:58-kor jamal ezt írta:
> To take a rough estimate of 5K users, how often do you think
> these replay messages will be generated?
>
> Is there a (clever) way to avoid transporting them and still achieve
> an accurate failover?
There is, provided that you do not want replay detection to work after
a failover. The more often you would send sequence number updates the
smaller the possible replay window will be. If you sacrifice scalability
you get more accurate replay detection.
To play with numbers: say that you have 5K users, so let's suppose
there are at most 20K IPSEC SAs. If you decide to send an update per
second, that would mean 20K updates/second. If each update message is 20
bytes long, that means that on Ethernet you can transmit all of them in
about 280 packets. That's not too much. (I suppose the 20K pfkey
messages would be much more of a problem, though...)
--
Regards,
Krisztian KOVACS
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] IPSEC failover and replay detection sequence numbers
2004-10-29 13:24 ` KOVACS Krisztian
@ 2004-10-29 15:01 ` jamal
2004-10-29 16:15 ` KOVACS Krisztian
0 siblings, 1 reply; 11+ messages in thread
From: jamal @ 2004-10-29 15:01 UTC (permalink / raw)
To: KOVACS Krisztian; +Cc: netdev, ipsec-tools-devel, vpn-failover
On Fri, 2004-10-29 at 09:24, KOVACS Krisztian wrote:
> Hi,
>
> 2004-10-29, p keltezéssel 14:58-kor jamal ezt írta:
> > To take a rough estimate of 5K users, how often do you think
> > these replay messages will be generated?
> >
> > Is there a (clever) way to avoid transporting them and still achieve
> > an accurate failover?
>
> There is, provided that you do not want replay detection to work after
> a failover. The more often you would send sequence number updates the
> smaller the possible replay window will be. If you sacrifice scalability
> you get more accurate replay detection.
>
ok. It should still get better in a short period of time though.
Moral in my point is i hope you make it an optional feature.
> To play with numbers: say that you have 5K users, so let's suppose
> there are at most 20K IPSEC SAs. If you decide to send an update per
> second, that would mean 20K updates/second. If each update message is 20
> bytes long, that means that on Ethernet you can transmit all of them in
> about 280 packets.
Are you batching?
In my count: Assuming 20bytes is in a packet of its own - your numbers
translate to 20Kpps which is > 10Mbps ;->
I suppose SAs will be much lower rate. So you need probably a dedicated
100Mbps just for the syncing. I would also say SA updates should be
prioritized over replay messages.
> That's not too much. (I suppose the 20K pfkey
> messages would be much more of a problem, though...)
Why not use the netlink events (you mention pfkey).
Batching them with a timeout should help.
cheers,
jamal
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] IPSEC failover and replay detection sequence numbers
2004-10-29 15:01 ` jamal
@ 2004-10-29 16:15 ` KOVACS Krisztian
0 siblings, 0 replies; 11+ messages in thread
From: KOVACS Krisztian @ 2004-10-29 16:15 UTC (permalink / raw)
To: hadi; +Cc: netdev, ipsec-tools-devel, vpn-failover
Hi,
jamal wrote:
> ok. It should still get better in a short period of time though.
> Moral in my point is i hope you make it an optional feature.
Definitely.
>> To play with numbers: say that you have 5K users, so let's suppose
>>there are at most 20K IPSEC SAs. If you decide to send an update per
>>second, that would mean 20K updates/second. If each update message is 20
>>bytes long, that means that on Ethernet you can transmit all of them in
>>about 280 packets.
>
> Are you batching?
Of course! I think it is a must, especially if we use such tiny
messages. But this is dependant on the user-space code of course.
> In my count: Assuming 20bytes is in a packet of its own - your numbers
> translate to 20Kpps which is > 10Mbps ;->
> I suppose SAs will be much lower rate. So you need probably a dedicated
> 100Mbps just for the syncing. I would also say SA updates should be
> prioritized over replay messages.
I think a dedicated 100mbps/1Gbps interface is not a problem anyway...
>>That's not too much. (I suppose the 20K pfkey
>>messages would be much more of a problem, though...)
>
> Why not use the netlink events (you mention pfkey).
>
> Batching them with a timeout should help.
Agreed. However, for the initial tests I chose pfkey because racoon
uses pfkey only, so it would be good enough for me as a prototype. I
think it would not be too much work to implement the netlink interface
as well - with batching included.
--
Regards,
Krisztian KOVACS
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC] IPSEC failover and replay detection sequence numbers
2004-10-29 12:58 ` jamal
2004-10-29 13:24 ` KOVACS Krisztian
@ 2004-11-07 17:42 ` Michael Richardson
1 sibling, 0 replies; 11+ messages in thread
From: Michael Richardson @ 2004-11-07 17:42 UTC (permalink / raw)
To: hadi; +Cc: KOVACS Krisztian, netdev, ipsec-tools-devel, vpn-failover
-----BEGIN PGP SIGNED MESSAGE-----
>>>>> "jamal" == jamal <hadi@cyberus.ca> writes:
jamal> Krisztian,
jamal> To take a rough estimate of 5K users, how often do you think
jamal> these replay messages will be generated?
jamal> Is there a (clever) way to avoid transporting them and still
jamal> achieve an accurate failover?
Yes there are some heuristics one can apply.
First, on receiver, if you are the slave, you need no information at
all. Replay counters monotonically increase, so any packet you get >
than you saw before is okay. As such, you can easily tradeoff risk of
replay attack vs number of messages to carry.
On transmit, you have to be accurate on the lower bound, but if your
lower bound is *too high*, that's okay. there is just a hole in the
replay counter, and that's okay too.
So, once you decide on the update rate master->slave, and if you know
approximately how many packets/second are going through on the master,
you can take packets/second * 1/update-rate and tell the slave to start
at that number if it has to take over.
(Note that you have to acount for packets-in-flight, which may
actually be substantial, and IPsec has no way to know what the RTT is,
unlike TCP. It could steal the info from TCP, if TCP had a session
open, which as a gateway, it would not do..
Some have suggested having IKE keep a TCP session up just for
this information.)
] Train travel features AC outlets with no take-off restrictions| firewalls [
] Michael Richardson, Sandelman Software Works, Ottawa, ON |net architect[
] mcr@sandelman.ottawa.on.ca http://www.sandelman.ottawa.on.ca/ |device driver[
] panic("Just another Debian/notebook using, kernel hacking, security guy"); [
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)
Comment: Finger me for keys
iQCVAwUBQY5ecIqHRg3pndX9AQEl6gP+OeX08RaO60c9BOXqNoqkb6PvUcBX1t9v
mdaNpkUA+iy6RpYQwcBxfN4G4yvwwbO9JDgPRK/k/Wh6zmY4dBLgtiG1tlFaEUcf
6HRBmBSmIbDUpFkAYGdSJuQxhGDas6sxi4MF6tIsaZUtJzqO+Xp5HtrauzTH56VV
vswtfMy8z7k=
=FV58
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Vpn-failover] [RFC] IPSEC failover - Netlink part
2004-10-29 10:23 [RFC] IPSEC failover and replay detection sequence numbers KOVACS Krisztian
2004-10-29 12:58 ` jamal
@ 2004-11-04 14:01 ` Ulrich Weber
2004-11-04 18:15 ` Patrick McHardy
1 sibling, 1 reply; 11+ messages in thread
From: Ulrich Weber @ 2004-11-04 14:01 UTC (permalink / raw)
To: vpn-failover; +Cc: netdev, ipsec-tools-devel
[-- Attachment #1: Type: text/plain, Size: 912 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,
I take the opportunity to post my code as well. At the moment I'm working at
the same as Krisztian. My solutions however is for openswan, which uses
netlink instead of pfkey.
Please find attached the appropriate netlink modifications to
include/linux/xfrm.h and net/xfrm/xfrm_users.c
In theses patches, a new netlink group (XFRMGRP_REPLAY) is added to notify
about seq number changes. Each notify message contains a xfrm_usersa_id
struct with the replay struct attached as rt attribute. In addition, these
replay struct is also attached at ipsec sa dumps.
Any comments are welcome :)
Cheers
~ Ulrich
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFBijYw22t2oTuElzoRAp0LAKCdKc4CgzWqLJLh4/U2oRFA96e49gCgk2R3
Rff8wpPVtUZtlCwJUEnP+34=
=b6vx
-----END PGP SIGNATURE-----
[-- Attachment #2: linux_xfrm.h --]
[-- Type: text/x-chdr, Size: 760 bytes --]
--- linux.org/include/linux/xfrm.h. 2004-10-11 04:57:07.000000000 +0200
+++ linux/include/linux/xfrm.h 2004-10-18 17:00:43.000000000 +0200
@@ -140,6 +140,9 @@
XFRM_MSG_FLUSHPOLICY,
#define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY
+ XFRM_MSG_UPDSEQ,
+#define XFRM_MSG_UPDSEQ XFRM_MSG_UPDSEQ
+
XFRM_MSG_MAX
};
@@ -171,6 +174,7 @@
XFRMA_ALG_COMP, /* struct xfrm_algo */
XFRMA_ENCAP, /* struct xfrm_algo + struct xfrm_encap_tmpl */
XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */
+ XFRMA_REPLAY, /* struct xfrm_replay_state */
__XFRMA_MAX
#define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -258,5 +258,6 @@
#define XFRMGRP_ACQUIRE 1
#define XFRMGRP_EXPIRE 2
+#define XFRMGRP_REPLAY 3
#endif /* _LINUX_XFRM_H */
[-- Attachment #3: xfrm_user.diff --]
[-- Type: text/x-patch, Size: 3725 bytes --]
--- linux.org/net/xfrm/xfrm_user.c 2004-10-18 23:54:32.000000000 +0200
+++ linux/net/xfrm/xfrm_user.c 2004-10-21 16:27:59.000000000 +0200
@@ -240,6 +240,12 @@
if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
goto error;
+ if(xfrma[XFRMA_REPLAY-1]) {
+ struct xfrm_replay_state *replay;
+ replay = RTA_DATA(xfrma[XFRMA_REPLAY - 1]);
+ x->replay = *replay;
+ }
+
err = -ENOENT;
x->type = xfrm_get_type(x->id.proto, x->props.family);
if (x->type == NULL)
@@ -368,6 +375,8 @@
if (x->encap)
RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
+ RTA_PUT(skb, XFRMA_REPLAY, sizeof(x->replay), &x->replay);
+
nlh->nlmsg_len = skb->tail - b;
out:
sp->this_idx++;
@@ -852,6 +861,27 @@
return 0;
}
+static int xfrm_update_seq(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
+{
+ struct xfrm_state *x;
+ struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
+ struct xfrm_replay_state *replay;
+
+ x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
+ if (x == NULL) {
+ printk(KERN_INFO "Found no xfrm state for sa seq update\n");
+ return -ESRCH;
+ }
+
+ if(xfrma[XFRMA_REPLAY-1]) {
+ replay = RTA_DATA(xfrma[XFRMA_REPLAY - 1]);
+ x->replay = *replay;
+ }
+ else return -EINVAL;
+
+ return 0;
+}
+
static const int xfrm_msg_min[(XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)] = {
NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)), /* NEW SA */
NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)), /* DEL SA */
@@ -867,6 +897,7 @@
NLMSG_LENGTH(sizeof(struct xfrm_user_polexpire)), /* POLEXPIRE */
NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush)), /* FLUSH SA */
NLMSG_LENGTH(0), /* FLUSH POLICY */
+ NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)),/* UPD SEQ */
};
static struct xfrm_link {
@@ -893,6 +924,7 @@
{},
{ .doit = xfrm_flush_sa },
{ .doit = xfrm_flush_policy },
+ { .doit = xfrm_update_seq },
};
static int xfrm_done(struct netlink_callback *cb)
@@ -1050,6 +1082,33 @@
return -1;
}
+static int build_replay(struct sk_buff *skb, struct xfrm_state *x, int event)
+{
+ struct xfrm_usersa_id *id;
+ struct nlmsghdr *nlh;
+ unsigned char *b = skb->tail;
+
+ nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_UPDSEQ,
+ sizeof(*id));
+ id = NLMSG_DATA(nlh);
+ nlh->nlmsg_flags = 0;
+
+ id->daddr = x->id.daddr;
+ id->spi = x->id.spi;
+ id->family = x->props.family;
+ id->proto = x->id.proto;
+
+ RTA_PUT(skb, XFRMA_REPLAY, sizeof(x->replay), &x->replay);
+
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+rtattr_failure:
+nlmsg_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
static int xfrm_send_state_notify(struct xfrm_state *x, int hard)
{
struct sk_buff *skb;
@@ -1218,12 +1277,28 @@
return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
}
+static int xfrm_send_replay_notify(struct xfrm_state *x, int event) {
+ struct sk_buff *skb;
+
+ skb = alloc_skb(sizeof(struct xfrm_usersa_id) + sizeof(struct xfrm_replay_state) + 16, GFP_ATOMIC);
+ if (skb == NULL)
+ return -ENOMEM;
+
+ if (build_replay(skb, x, event) < 0)
+ BUG();
+
+ NETLINK_CB(skb).dst_groups = XFRMGRP_REPLAY;
+
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_REPLAY, GFP_ATOMIC);
+}
+
static struct xfrm_mgr netlink_mgr = {
.id = "netlink",
.notify = xfrm_send_state_notify,
.acquire = xfrm_send_acquire,
.compile_policy = xfrm_compile_policy,
.notify_policy = xfrm_send_policy_notify,
+ .notify_seq = xfrm_send_replay_notify,
};
static int __init xfrm_user_init(void)
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [Vpn-failover] [RFC] IPSEC failover - Netlink part
2004-11-04 14:01 ` [Vpn-failover] [RFC] IPSEC failover - Netlink part Ulrich Weber
@ 2004-11-04 18:15 ` Patrick McHardy
2004-11-08 10:31 ` Ulrich Weber
0 siblings, 1 reply; 11+ messages in thread
From: Patrick McHardy @ 2004-11-04 18:15 UTC (permalink / raw)
To: Ulrich Weber; +Cc: vpn-failover, netdev, ipsec-tools-devel
Ulrich Weber wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi,
>
> I take the opportunity to post my code as well. At the moment I'm
> working at
> the same as Krisztian. My solutions however is for openswan, which uses
> netlink instead of pfkey.
>
> Please find attached the appropriate netlink modifications to
> include/linux/xfrm.h and net/xfrm/xfrm_users.c
>
> In theses patches, a new netlink group (XFRMGRP_REPLAY) is added to
> notify
> about seq number changes. Each notify message contains a xfrm_usersa_id
> struct with the replay struct attached as rt attribute. In addition,
> these
> replay struct is also attached at ipsec sa dumps.
>
> Any comments are welcome :)
Some minor bugs, see below.
Regards
Patrick
>------------------------------------------------------------------------
>
>--- linux.org/include/linux/xfrm.h. 2004-10-11 04:57:07.000000000 +0200
>+++ linux/include/linux/xfrm.h 2004-10-18 17:00:43.000000000 +0200
>@@ -140,6 +140,9 @@
> XFRM_MSG_FLUSHPOLICY,
> #define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY
>
>+ XFRM_MSG_UPDSEQ,
>+#define XFRM_MSG_UPDSEQ XFRM_MSG_UPDSEQ
>+
> XFRM_MSG_MAX
> };
>
>@@ -171,6 +174,7 @@
> XFRMA_ALG_COMP, /* struct xfrm_algo */
> XFRMA_ENCAP, /* struct xfrm_algo + struct xfrm_encap_tmpl */
> XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */
>+ XFRMA_REPLAY, /* struct xfrm_replay_state */
> __XFRMA_MAX
>
> #define XFRMA_MAX (__XFRMA_MAX - 1)
>@@ -258,5 +258,6 @@
>
> #define XFRMGRP_ACQUIRE 1
> #define XFRMGRP_EXPIRE 2
>+#define XFRMGRP_REPLAY 3
>
> #endif /* _LINUX_XFRM_H */
>
>
>------------------------------------------------------------------------
>
>--- linux.org/net/xfrm/xfrm_user.c 2004-10-18 23:54:32.000000000 +0200
>+++ linux/net/xfrm/xfrm_user.c 2004-10-21 16:27:59.000000000 +0200
>@@ -240,6 +240,12 @@
> if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
> goto error;
>
>+ if(xfrma[XFRMA_REPLAY-1]) {
>+ struct xfrm_replay_state *replay;
>+ replay = RTA_DATA(xfrma[XFRMA_REPLAY - 1]);
>+ x->replay = *replay;
>+ }
>+
> err = -ENOENT;
> x->type = xfrm_get_type(x->id.proto, x->props.family);
> if (x->type == NULL)
>@@ -368,6 +375,8 @@
> if (x->encap)
> RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
>
>+ RTA_PUT(skb, XFRMA_REPLAY, sizeof(x->replay), &x->replay);
>+
> nlh->nlmsg_len = skb->tail - b;
> out:
> sp->this_idx++;
>@@ -852,6 +861,27 @@
> return 0;
> }
>
>+static int xfrm_update_seq(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
>+{
>+ struct xfrm_state *x;
>+ struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
>
>
>+ struct xfrm_replay_state *replay;
>+
>+ x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
>+ if (x == NULL) {
>+ printk(KERN_INFO "Found no xfrm state for sa seq update\n");
>+ return -ESRCH;
>+ }
>+
>+ if(xfrma[XFRMA_REPLAY-1]) {
>+ replay = RTA_DATA(xfrma[XFRMA_REPLAY - 1]);
>+ x->replay = *replay;
>
>
>+ }
>+ else return -EINVAL;
>
>
^^ leaks xfrm_state reference
>+
>+ return 0;
>
>
^^ same here
>+}
>+
> static const int xfrm_msg_min[(XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)] = {
> NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)), /* NEW SA */
> NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)), /* DEL SA */
>@@ -867,6 +897,7 @@
> NLMSG_LENGTH(sizeof(struct xfrm_user_polexpire)), /* POLEXPIRE */
> NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush)), /* FLUSH SA */
> NLMSG_LENGTH(0), /* FLUSH POLICY */
>+ NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)),/* UPD SEQ */
>
>
^^ what about struct xfrm_replay_state ?
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [Vpn-failover] [RFC] IPSEC failover - Netlink part
2004-11-04 18:15 ` Patrick McHardy
@ 2004-11-08 10:31 ` Ulrich Weber
2004-11-08 16:10 ` Patrick McHardy
0 siblings, 1 reply; 11+ messages in thread
From: Ulrich Weber @ 2004-11-08 10:31 UTC (permalink / raw)
To: Patrick McHardy; +Cc: vpn-failover, netdev, ipsec-tools-devel
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
what did you mean with "leaks xfrm_state reference"? The missing
xfrm_state_put(x) ?
I changed it (see below) to use Krisztian's xfrm_state_replay_update function.
|>
|> + struct xfrm_replay_state *replay;
|> + + x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
|> + if (x == NULL) {
|> + printk(KERN_INFO "Found no xfrm state for sa seq update\n");
|> + return -ESRCH;
|> + }
|> +
|> + if(xfrma[XFRMA_REPLAY-1]) {
|> + replay = RTA_DATA(xfrma[XFRMA_REPLAY - 1]);
|> + x->replay = *replay;
|>
|>
|> + }
|> + else return -EINVAL;
|>
|>
| ^^ leaks xfrm_state reference
|
|> +
|> + return 0;
|>
|>
| ^^ same here
|
|> +} +
|> static const int xfrm_msg_min[(XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)] = {
|> NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)), /* NEW SA */
|> NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)), /* DEL SA */
|> @@ -867,6 +897,7 @@
|> NLMSG_LENGTH(sizeof(struct xfrm_user_polexpire)), /* POLEXPIRE */
|> NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush)), /* FLUSH SA */
|> NLMSG_LENGTH(0), /* FLUSH POLICY */
|> + NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)),/* UPD SEQ */
|>
|>
| ^^ what about struct xfrm_replay_state ?
it's attached as rt attribute, so it should be ok.
- ---
static int xfrm_update_seq(struct sk_buff *skb, struct nlmsghdr *nlh, void
**xfrma)
{
~ struct xfrm_state *x;
~ struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
~ struct xfrm_replay_state *replay;
~ x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
~ if (x == NULL) {
~ printk(KERN_INFO "Found no xfrm state for sa seq update\n");
~ return -ESRCH;
~ }
~ if(xfrma[XFRMA_REPLAY-1]) {
~ replay = RTA_DATA(xfrma[XFRMA_REPLAY - 1]);
~ xfrm_state_replay_update(x, replay);
~ xfrm_state_put(x);
~ }
~ else return -EINVAL;
~ return 0;
}
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFBj0r522t2oTuElzoRAgBWAKCKSQXB2rX9DeMpMwVIMl9mXfmxUQCfeYYY
1d3V4P8C3+d5YgsYpwkFHPQ=
=RihP
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [Vpn-failover] [RFC] IPSEC failover - Netlink part
2004-11-08 10:31 ` Ulrich Weber
@ 2004-11-08 16:10 ` Patrick McHardy
2004-11-09 8:55 ` Ulrich Weber
0 siblings, 1 reply; 11+ messages in thread
From: Patrick McHardy @ 2004-11-08 16:10 UTC (permalink / raw)
To: Ulrich Weber; +Cc: vpn-failover, netdev, ipsec-tools-devel
Ulrich Weber wrote:
> what did you mean with "leaks xfrm_state reference"? The missing
> xfrm_state_put(x) ?
Yes.
> I changed it (see below) to use Krisztian's xfrm_state_replay_update
> function.
Even better.
> |> static const int xfrm_msg_min[(XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)] = {
> |> NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)), /* NEW SA */
> |> NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)), /* DEL SA */
> |> @@ -867,6 +897,7 @@
> |> NLMSG_LENGTH(sizeof(struct xfrm_user_polexpire)), /* POLEXPIRE */
> |> NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush)), /* FLUSH SA */
> |> NLMSG_LENGTH(0), /* FLUSH POLICY */
> |> + NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)),/* UPD SEQ */
> |>
> |>
> | ^^ what about struct xfrm_replay_state ?
> it's attached as rt attribute, so it should be ok.
But you don't check it's size. You need to include it here or check it
when you use it.
Regards
Patrick
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [Vpn-failover] [RFC] IPSEC failover - Netlink part
2004-11-08 16:10 ` Patrick McHardy
@ 2004-11-09 8:55 ` Ulrich Weber
0 siblings, 0 replies; 11+ messages in thread
From: Ulrich Weber @ 2004-11-09 8:55 UTC (permalink / raw)
To: Patrick McHardy; +Cc: vpn-failover, netdev, ipsec-tools-devel
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
|> |> + NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)),/* UPD SEQ */
|> |>
|> |>
|> | ^^ what about struct xfrm_replay_state ?
|> it's attached as rt attribute, so it should be ok.
|
| But you don't check it's size. You need to include it here or check it
| when you use it.
ok i added the following checkt to ensure the right size.
If i add the size of the xfrm_replay_state struct to the above array, the rt
attribute macros wouldnt work anymore.
Cheers
~ Ulrich
- ----
struct rtattr *rt = xfrma[XFRMA_REPLAY-1];
if( xfrma[XFRMA_REPLAY-1] && (rt->rta_len == (sizeof(struct
xfrm_replay_state) + sizeof(struct rtattr)))) {
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFBkIXp22t2oTuElzoRAqsnAJ9QlZuU6wBWtmkzcT8aeb9+AL3nfQCfZUeI
EJh0+e8EOS4/HKiP2Ylu02k=
=roZY
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2004-11-09 8:55 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-10-29 10:23 [RFC] IPSEC failover and replay detection sequence numbers KOVACS Krisztian
2004-10-29 12:58 ` jamal
2004-10-29 13:24 ` KOVACS Krisztian
2004-10-29 15:01 ` jamal
2004-10-29 16:15 ` KOVACS Krisztian
2004-11-07 17:42 ` Michael Richardson
2004-11-04 14:01 ` [Vpn-failover] [RFC] IPSEC failover - Netlink part Ulrich Weber
2004-11-04 18:15 ` Patrick McHardy
2004-11-08 10:31 ` Ulrich Weber
2004-11-08 16:10 ` Patrick McHardy
2004-11-09 8:55 ` Ulrich Weber
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).