summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHakan Olsson <ho@cvs.openbsd.org>2004-06-21 23:27:11 +0000
committerHakan Olsson <ho@cvs.openbsd.org>2004-06-21 23:27:11 +0000
commit19361778431fa0cc1cf73abf7ffecf3142793f9b (patch)
treebd35225f6031d82bef0fce4af0afd5dfd17fc49e
parentc35a3cc1f50889911a74c83ea50c365a41f09b11 (diff)
Implement NAT-T keepalive messages.
-rw-r--r--sbin/isakmpd/ipsec.c10
-rw-r--r--sbin/isakmpd/nat_traversal.c54
-rw-r--r--sbin/isakmpd/nat_traversal.h3
-rw-r--r--sbin/isakmpd/sa.c10
-rw-r--r--sbin/isakmpd/sa.h6
-rw-r--r--sbin/isakmpd/udp_encap.c45
6 files changed, 106 insertions, 22 deletions
diff --git a/sbin/isakmpd/ipsec.c b/sbin/isakmpd/ipsec.c
index 52f9e35071f..1ebbffc77a0 100644
--- a/sbin/isakmpd/ipsec.c
+++ b/sbin/isakmpd/ipsec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsec.c,v 1.99 2004/06/21 18:29:06 ho Exp $ */
+/* $OpenBSD: ipsec.c,v 1.100 2004/06/21 23:27:10 ho Exp $ */
/* $EOM: ipsec.c,v 1.143 2000/12/11 23:57:42 niklas Exp $ */
/*
@@ -62,6 +62,9 @@
#include "log.h"
#include "math_group.h"
#include "message.h"
+#if defined (USE_NAT_TRAVERSAL)
+#include "nat_traversal.h"
+#endif
#include "prf.h"
#include "sa.h"
#include "timer.h"
@@ -312,6 +315,11 @@ ipsec_finalize_exchange(struct message *msg)
*/
if (isakmp_sa->seconds)
sa_setup_expirations(isakmp_sa);
+
+#if defined (USE_NAT_TRAVERSAL)
+ if (isakmp_sa->flags & SA_FLAG_NAT_T_KEEPALIVE)
+ nat_t_setup_keepalive(isakmp_sa);
+#endif
break;
}
break;
diff --git a/sbin/isakmpd/nat_traversal.c b/sbin/isakmpd/nat_traversal.c
index 50b1c12c8c7..11950d9c8bb 100644
--- a/sbin/isakmpd/nat_traversal.c
+++ b/sbin/isakmpd/nat_traversal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nat_traversal.c,v 1.2 2004/06/20 17:17:35 ho Exp $ */
+/* $OpenBSD: nat_traversal.c,v 1.3 2004/06/21 23:27:10 ho Exp $ */
/*
* Copyright (c) 2004 Håkan Olsson. All rights reserved.
@@ -29,6 +29,7 @@
#include "sysdep.h"
+#include "conf.h"
#include "exchange.h"
#include "hash.h"
#include "ipsec.h"
@@ -41,8 +42,10 @@
#include "nat_traversal.h"
#include "prf.h"
#include "sa.h"
+#include "timer.h"
#include "transport.h"
#include "util.h"
+#include "virtual.h"
/*
* XXX According to draft-ietf-ipsec-nat-t-ike-07.txt, the NAT-T
@@ -62,6 +65,9 @@ static const char *isakmp_nat_t_cap_text[] = {
#endif
};
+/* In seconds. Recommended in draft-ietf-ipsec-udp-encaps-09. */
+#define NAT_T_KEEPALIVE_INTERVAL 20
+
/* The MD5 hashes of the above strings is put in this array. */
static char **nat_t_hashes;
static size_t nat_t_hashsize;
@@ -382,3 +388,49 @@ nat_t_exchange_check_nat_d(struct message *msg)
"nat_t_exchange_check_nat_d: NAT detected"));
return 1;
}
+
+static void
+nat_t_send_keepalive(void *v_arg)
+{
+ struct sa *sa = (struct sa *)v_arg;
+ struct transport *t;
+ struct timeval now;
+ int interval;
+
+ /* Send the keepalive message. */
+ t = ((struct virtual_transport *)sa->transport)->encap;
+ t->vtbl->send_message(NULL, t);
+
+ /* Set new timer. */
+ interval = conf_get_num("General", "NAT-T-Keepalive", 0);
+ if (interval < 1)
+ interval = NAT_T_KEEPALIVE_INTERVAL;
+ gettimeofday(&now, 0);
+ now.tv_sec += interval;
+
+ sa->nat_t_keepalive = timer_add_event("nat_t_send_keepalive",
+ nat_t_send_keepalive, v_arg, &now);
+ if (!sa->nat_t_keepalive)
+ log_print("nat_t_send_keepalive: "
+ "timer_add_event() failed, will send no more keepalives");
+}
+
+void
+nat_t_setup_keepalive(struct sa *sa)
+{
+ struct sockaddr *src;
+ struct timeval now;
+
+ sa->transport->vtbl->get_src(sa->transport, &src);
+ if (!virtual_listen_lookup(src))
+ return;
+
+ gettimeofday(&now, 0);
+ now.tv_sec += NAT_T_KEEPALIVE_INTERVAL;
+
+ sa->nat_t_keepalive = timer_add_event("nat_t_send_keepalive",
+ nat_t_send_keepalive, sa, &now);
+ if (!sa->nat_t_keepalive)
+ log_print("nat_t_setup_keepalive: "
+ "timer_add_event() failed, will not send keepalives");
+}
diff --git a/sbin/isakmpd/nat_traversal.h b/sbin/isakmpd/nat_traversal.h
index ecb5d6008b1..f31da981b67 100644
--- a/sbin/isakmpd/nat_traversal.h
+++ b/sbin/isakmpd/nat_traversal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nat_traversal.h,v 1.1 2004/06/20 15:24:05 ho Exp $ */
+/* $OpenBSD: nat_traversal.h,v 1.2 2004/06/21 23:27:10 ho Exp $ */
/*
* Copyright (c) 2004 Håkan Olsson. All rights reserved.
@@ -32,5 +32,6 @@ int nat_t_add_vendor_payloads(struct message *);
void nat_t_check_vendor_payload(struct message *, struct payload *);
int nat_t_exchange_add_nat_d(struct message *);
int nat_t_exchange_check_nat_d(struct message *);
+void nat_t_setup_keepalive(struct sa *);
#endif /* _NAT_TRAVERSAL_H_ */
diff --git a/sbin/isakmpd/sa.c b/sbin/isakmpd/sa.c
index feed2c79d76..ec0af7d4bff 100644
--- a/sbin/isakmpd/sa.c
+++ b/sbin/isakmpd/sa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sa.c,v 1.82 2004/05/23 18:17:56 hshoexer Exp $ */
+/* $OpenBSD: sa.c,v 1.83 2004/06/21 23:27:10 ho Exp $ */
/* $EOM: sa.c,v 1.112 2000/12/12 00:22:52 niklas Exp $ */
/*
@@ -794,6 +794,14 @@ sa_release(struct sa *sa)
free(sa->name);
if (sa->keystate)
free(sa->keystate);
+#if defined (USE_NAT_TRAVERSAL)
+ if (sa->nat_t_keepalive)
+ timer_remove_event(sa->nat_t_keepalive);
+#endif
+#if defined (USE_DPD)
+ if (sa->dpd_nextev)
+ timer_remove_event(sa->dpd_nextev);
+#endif
if (sa->transport)
transport_release(sa->transport);
free(sa);
diff --git a/sbin/isakmpd/sa.h b/sbin/isakmpd/sa.h
index 1457d0ecc88..c0635dc43bf 100644
--- a/sbin/isakmpd/sa.h
+++ b/sbin/isakmpd/sa.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sa.h,v 1.39 2004/06/21 13:09:00 ho Exp $ */
+/* $OpenBSD: sa.h,v 1.40 2004/06/21 23:27:10 ho Exp $ */
/* $EOM: sa.h,v 1.58 2000/10/10 12:39:01 provos Exp $ */
/*
@@ -204,6 +204,10 @@ struct sa {
struct event *soft_death;
struct event *death;
+#if defined (USE_NAT_TRAVERSAL)
+ struct event *nat_t_keepalive;
+#endif
+
#if defined (USE_DPD)
/* IKE DPD (RFC3706) message sequence number. */
u_int32_t dpd_seq; /* sent */
diff --git a/sbin/isakmpd/udp_encap.c b/sbin/isakmpd/udp_encap.c
index d6cebf473f5..e9ef4c0a3e7 100644
--- a/sbin/isakmpd/udp_encap.c
+++ b/sbin/isakmpd/udp_encap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_encap.c,v 1.2 2004/06/21 13:09:01 ho Exp $ */
+/* $OpenBSD: udp_encap.c,v 1.3 2004/06/21 23:27:10 ho Exp $ */
/*
* Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved.
@@ -417,27 +417,38 @@ udp_encap_handle_message(struct transport *t)
message_recv (msg);
}
-/* Physically send the message MSG over its associated transport. */
+/*
+ * Physically send the message MSG over its associated transport.
+ * Special: if 'msg' is NULL, send a NAT-T keepalive message.
+ */
static int
udp_encap_send_message(struct message *msg, struct transport *t)
{
struct udp_transport *u = (struct udp_transport *)t;
struct msghdr m;
- struct iovec *new_iov;
+ struct iovec *new_iov = 0, keepalive;
ssize_t n;
u_int32_t marker = 0; /* NULL-ESP Marker */
- /* Construct new iov array, prefixing NULL-ESP Marker. */
- new_iov = (struct iovec *)calloc (msg->iovlen + 1, sizeof *new_iov);
- if (!new_iov) {
- log_error ("udp_encap_send_message: calloc (%lu, %lu) failed",
- (unsigned long)msg->iovlen + 1,
- (unsigned long)sizeof *new_iov);
- return -1;
+ if (msg) {
+ /* Construct new iov array, prefixing NULL-ESP Marker. */
+ new_iov = (struct iovec *)calloc (msg->iovlen + 1,
+ sizeof *new_iov);
+ if (!new_iov) {
+ log_error ("udp_encap_send_message: "
+ "calloc (%lu, %lu) failed",
+ (unsigned long)msg->iovlen + 1,
+ (unsigned long)sizeof *new_iov);
+ return -1;
+ }
+ new_iov[0].iov_base = &marker;
+ new_iov[0].iov_len = IPSEC_SPI_SIZE;
+ memcpy (new_iov + 1, msg->iov, msg->iovlen * sizeof *new_iov);
+ } else {
+ marker = ~marker;
+ keepalive.iov_base = &marker;
+ keepalive.iov_len = 1;
}
- new_iov[0].iov_base = &marker;
- new_iov[0].iov_len = IPSEC_SPI_SIZE;
- memcpy (new_iov + 1, msg->iov, msg->iovlen * sizeof *new_iov);
/*
* Sending on connected sockets requires that no destination address is
@@ -445,18 +456,18 @@ udp_encap_send_message(struct message *msg, struct transport *t)
*/
m.msg_name = (caddr_t)u->dst;
m.msg_namelen = sysdep_sa_len (u->dst);
- m.msg_iov = new_iov;
- m.msg_iovlen = msg->iovlen + 1;
+ m.msg_iov = msg ? new_iov : &keepalive;
+ m.msg_iovlen = msg ? msg->iovlen + 1 : 1;
m.msg_control = 0;
m.msg_controllen = 0;
m.msg_flags = 0;
n = sendmsg (u->s, &m, 0);
+ if (msg)
+ free (new_iov);
if (n == -1) {
/* XXX We should check whether the address has gone away */
log_error ("sendmsg (%d, %p, %d)", u->s, &m, 0);
- free (new_iov);
return -1;
}
- free (new_iov);
return 0;
}