diff options
-rw-r--r-- | sbin/isakmpd/ipsec.c | 10 | ||||
-rw-r--r-- | sbin/isakmpd/nat_traversal.c | 54 | ||||
-rw-r--r-- | sbin/isakmpd/nat_traversal.h | 3 | ||||
-rw-r--r-- | sbin/isakmpd/sa.c | 10 | ||||
-rw-r--r-- | sbin/isakmpd/sa.h | 6 | ||||
-rw-r--r-- | sbin/isakmpd/udp_encap.c | 45 |
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 = ▮ + 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 = ▮ + keepalive.iov_len = 1; } - new_iov[0].iov_base = ▮ - 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; } |