summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorHakan Olsson <ho@cvs.openbsd.org>2004-08-10 15:59:12 +0000
committerHakan Olsson <ho@cvs.openbsd.org>2004-08-10 15:59:12 +0000
commitad93a395f096ca7b9a0833d0906d723b7880e483 (patch)
tree40283255eb9e94abcc82178a9dbb6c11f09a3932 /sbin
parente6aea2c186d9eef5275040b69b69d4764a29f5b8 (diff)
Better implementation of the Dead Peer Detection protocol, RFC 3706.
hshoexer@ ok.
Diffstat (limited to 'sbin')
-rw-r--r--sbin/isakmpd/dpd.c428
-rw-r--r--sbin/isakmpd/dpd.h14
-rw-r--r--sbin/isakmpd/exchange.c17
-rw-r--r--sbin/isakmpd/ipsec.c40
-rw-r--r--sbin/isakmpd/isakmp_num.cst5
-rw-r--r--sbin/isakmpd/isakmpd.conf.58
-rw-r--r--sbin/isakmpd/message.c66
-rw-r--r--sbin/isakmpd/message.h6
-rw-r--r--sbin/isakmpd/pf_key_v2.c201
-rw-r--r--sbin/isakmpd/pf_key_v2.h14
-rw-r--r--sbin/isakmpd/sa.c6
-rw-r--r--sbin/isakmpd/sa.h47
-rw-r--r--sbin/isakmpd/sysdep.h19
-rw-r--r--sbin/isakmpd/sysdep/bsdi/sysdep.c12
-rw-r--r--sbin/isakmpd/sysdep/darwin/sysdep.c12
-rw-r--r--sbin/isakmpd/sysdep/freebsd/sysdep.c12
-rw-r--r--sbin/isakmpd/sysdep/freeswan/sysdep.c12
-rw-r--r--sbin/isakmpd/sysdep/linux/sysdep.c12
-rw-r--r--sbin/isakmpd/sysdep/netbsd/sysdep.c12
-rw-r--r--sbin/isakmpd/sysdep/openbsd/sysdep.c11
-rw-r--r--sbin/isakmpd/udp_encap.c8
21 files changed, 677 insertions, 285 deletions
diff --git a/sbin/isakmpd/dpd.c b/sbin/isakmpd/dpd.c
index 3bbaf05109d..6eb2ceb97c9 100644
--- a/sbin/isakmpd/dpd.c
+++ b/sbin/isakmpd/dpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dpd.c,v 1.3 2004/08/08 19:11:06 deraadt Exp $ */
+/* $OpenBSD: dpd.c,v 1.4 2004/08/10 15:59:10 ho Exp $ */
/*
* Copyright (c) 2004 Håkan Olsson. All rights reserved.
@@ -29,14 +29,17 @@
#include "sysdep.h"
+#include "conf.h"
#include "dpd.h"
#include "exchange.h"
+#include "hash.h"
#include "ipsec.h"
#include "isakmp_fld.h"
#include "log.h"
#include "message.h"
#include "sa.h"
#include "timer.h"
+#include "transport.h"
#include "util.h"
/* From RFC 3706. */
@@ -51,30 +54,16 @@ static const char dpd_vendor_id[] = {
DPD_MINOR
};
-int16_t script_dpd[] = {
- ISAKMP_PAYLOAD_NOTIFY, /* Initiator -> responder. */
- ISAKMP_PAYLOAD_HASH,
- EXCHANGE_SCRIPT_SWITCH,
- ISAKMP_PAYLOAD_NOTIFY, /* Responder -> initiator. */
- ISAKMP_PAYLOAD_HASH,
- EXCHANGE_SCRIPT_END
-};
-
-static int dpd_initiator_send_notify(struct message *);
-static int dpd_initiator_recv_ack(struct message *);
-static int dpd_responder_recv_notify(struct message *);
-static int dpd_responder_send_ack(struct message *);
-static void dpd_event(void *);
+#define DPD_RETRANS_MAX 5 /* max number of retries. */
+#define DPD_RETRANS_WAIT 5 /* seconds between retries. */
-int (*isakmp_dpd_initiator[])(struct message *) = {
- dpd_initiator_send_notify,
- dpd_initiator_recv_ack
-};
+/* DPD Timer State */
+enum dpd_tstate { DPD_TIMER_NORMAL, DPD_TIMER_CHECK };
-int (*isakmp_dpd_responder[])(struct message *) = {
- dpd_responder_recv_notify,
- dpd_responder_send_ack
-};
+static void dpd_check_event(void *);
+static void dpd_event(void *);
+static u_int32_t dpd_timer_interval(u_int32_t);
+static void dpd_timer_reset(struct sa *, u_int32_t, enum dpd_tstate);
/* Add the DPD VENDOR ID payload. */
int
@@ -127,225 +116,256 @@ dpd_check_vendor_payload(struct message *msg, struct payload *p)
if (memcmp(dpd_vendor_id, pbuf + ISAKMP_GEN_SZ, vlen) == 0) {
/* This peer is DPD capable. */
- msg->exchange->flags |= EXCHANGE_FLAG_DPD_CAP_PEER;
- LOG_DBG((LOG_EXCHANGE, 10, "dpd_check_vendor_payload: "
- "DPD capable peer detected"));
+ if (msg->isakmp_sa) {
+ msg->exchange->flags |= EXCHANGE_FLAG_DPD_CAP_PEER;
+ LOG_DBG((LOG_EXCHANGE, 10, "dpd_check_vendor_payload: "
+ "DPD capable peer detected"));
+ if (dpd_timer_interval(0) != 0) {
+ LOG_DBG((LOG_EXCHANGE, 10,
+ "dpd_check_vendor_payload: enabling"));
+ msg->isakmp_sa->flags |= SA_FLAG_DPD;
+ dpd_timer_reset(msg->isakmp_sa, 0,
+ DPD_TIMER_NORMAL);
+ }
+ }
p->flags |= PL_MARK;
- return;
}
-
return;
}
-static int
-dpd_add_notify(struct message *msg, u_int16_t type, u_int32_t seqno)
+/*
+ * All incoming DPD Notify messages enter here. Message has been validated.
+ */
+void
+dpd_handle_notify(struct message *msg, struct payload *p)
{
- struct sa *isakmp_sa = msg->isakmp_sa;
- char *buf;
- u_int32_t buflen;
-
- if (!isakmp_sa) {
- log_print("dpd_add_notify: no isakmp_sa");
- return -1;
- }
-
- buflen = ISAKMP_NOTIFY_SZ + ISAKMP_HDR_COOKIES_LEN + DPD_SEQNO_SZ;
- buf = malloc(buflen);
- if (!buf) {
- log_error("dpd_add_notify: malloc(%d) failed",
- ISAKMP_NOTIFY_SZ + DPD_SEQNO_SZ);
- return -1;
+ struct sa *isakmp_sa = msg->isakmp_sa;
+ u_int16_t notify = GET_ISAKMP_NOTIFY_MSG_TYPE(p->p);
+ u_int32_t p_seq;
+
+ /* Extract the sequence number. */
+ memcpy(&p_seq, p->p + ISAKMP_NOTIFY_SPI_OFF + ISAKMP_HDR_COOKIES_LEN,
+ sizeof p_seq);
+ p_seq = ntohl(p_seq);
+
+ LOG_DBG((LOG_MESSAGE, 40, "dpd_handle_notify: got %s seq %u",
+ constant_name(isakmp_notify_cst, notify), p_seq));
+
+ switch (notify) {
+ case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE:
+ /* The other peer wants to know we're alive. */
+ if (p_seq <= isakmp_sa->dpd_rseq) {
+ log_print("dpd_handle_notify: bad R_U_THERE seqno "
+ "%u <= %u", p_seq, isakmp_sa->dpd_rseq);
+ return;
+ }
+ isakmp_sa->dpd_rseq = p_seq;
+ message_send_dpd_notify(isakmp_sa,
+ ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK, p_seq);
+ break;
+
+ case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK:
+ /* This should be a response to a R_U_THERE we've sent. */
+ if (isakmp_sa->dpd_seq != p_seq) {
+ log_print("dpd_handle_notify: got bad ACK seqno %u, "
+ "expected %u", p_seq, isakmp_sa->dpd_seq);
+ /* XXX Give up? Retry? */
+ return;
+ }
+ break;
+ default:
}
- SET_ISAKMP_NOTIFY_DOI(buf, IPSEC_DOI_IPSEC);
- SET_ISAKMP_NOTIFY_PROTO(buf, ISAKMP_PROTO_ISAKMP);
- SET_ISAKMP_NOTIFY_SPI_SZ(buf, ISAKMP_HDR_COOKIES_LEN);
- SET_ISAKMP_NOTIFY_MSG_TYPE(buf, type);
- memcpy(buf + ISAKMP_NOTIFY_SPI_OFF, isakmp_sa->cookies,
- ISAKMP_HDR_COOKIES_LEN);
-
- memcpy(buf + ISAKMP_NOTIFY_SPI_OFF + ISAKMP_HDR_COOKIES_LEN, &seqno,
- sizeof (u_int32_t));
-
- if (message_add_payload(msg, ISAKMP_PAYLOAD_NOTIFY, buf, buflen, 1)) {
- free(buf);
- return -1;
- }
+ /* Mark handled. */
+ p->flags |= PL_MARK;
- return 0;
+ /* The other peer is alive, so we can safely wait a while longer. */
+ if (isakmp_sa->flags & SA_FLAG_DPD)
+ dpd_timer_reset(isakmp_sa, 0, DPD_TIMER_NORMAL);
}
-static int
-dpd_initiator_send_notify(struct message *msg)
+/* Calculate the time until next DPD exchange. */
+static u_int32_t
+dpd_timer_interval(u_int32_t offset)
{
- if (!msg->isakmp_sa) {
- log_print("dpd_initiator_send_notify: no isakmp_sa");
- return -1;
- }
-
- if (msg->isakmp_sa->dpd_seq == 0) {
- /* RFC 3706: first seq# should be random, with MSB zero. */
- getrandom((u_int8_t *)&msg->isakmp_sa->seq,
- sizeof msg->isakmp_sa->seq);
- msg->isakmp_sa->dpd_seq &= 0x7FFF;
- } else
- msg->isakmp_sa->dpd_seq++;
-
- return dpd_add_notify(msg, ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE,
- msg->isakmp_sa->dpd_seq);
+ int32_t v = 0;
+
+#ifdef notyet
+ v = ...; /* XXX Per-peer specified DPD intervals? */
+#endif
+ if (!v)
+ v = conf_get_num("General", "DPD-check-interval", 0);
+ if (v < 1)
+ return 0; /* DPD-Check-Interval < 1 means disable DPD */
+
+ v -= offset;
+ return v < 1 ? 1 : v;
}
-static int
-dpd_initiator_recv_ack(struct message *msg)
+static void
+dpd_timer_reset(struct sa *sa, u_int32_t time_passed, enum dpd_tstate mode)
{
- struct payload *p = payload_first(msg, ISAKMP_PAYLOAD_NOTIFY);
- struct sa *isakmp_sa = msg->isakmp_sa;
- struct timeval tv;
- u_int32_t rseq;
+ struct timeval tv;
- if (msg->exchange->phase != 2) {
- message_drop(msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE, 0, 1,
- 0);
- return -1;
- }
-
- if (GET_ISAKMP_NOTIFY_MSG_TYPE(p->p)
- != ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK) {
- message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
- return -1;
- }
-
- /* Presumably, we've been through message_validate_notify(). */
+ if (sa->dpd_event)
+ timer_remove_event(sa->dpd_event);
- /* Validate the SPI. Perhaps move to message_validate_notify(). */
- if (memcmp(p->p + ISAKMP_NOTIFY_SPI_OFF, isakmp_sa->cookies,
- ISAKMP_HDR_COOKIES_LEN) != 0) {
- log_print("dpd_initiator_recv_ack: bad cookies");
- message_drop(msg, ISAKMP_NOTIFY_INVALID_SPI, 0, 1, 0);
- return -1;
- }
-
- /* Check the seqno. */
- memcpy(p->p + ISAKMP_NOTIFY_SPI_OFF + ISAKMP_HDR_COOKIES_LEN, &rseq,
- sizeof rseq);
- rseq = ntohl(rseq);
-
- if (isakmp_sa->seq != rseq) {
- log_print("dpd_initiator_recv_ack: bad seqno %u, expected %u",
- rseq, isakmp_sa->seq);
- message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
- return -1;
- }
-
- /* Peer is alive. Reset timer. */
gettimeofday(&tv, 0);
- tv.tv_sec += DPD_DEFAULT_WORRY_METRIC; /* XXX Configurable */
-
- isakmp_sa->dpd_nextev = timer_add_event("dpd_event", dpd_event,
- isakmp_sa, &tv);
- if (!isakmp_sa->dpd_nextev)
- log_print("dpd_initiator_recv_ack: timer_add_event "
- "failed");
- else
- sa_reference(isakmp_sa);
-
- /* Mark handled. */
- p->flags |= PL_MARK;
-
- return 0;
+ switch (mode) {
+ case DPD_TIMER_NORMAL:
+ tv.tv_sec += dpd_timer_interval(time_passed);
+ sa->dpd_event = timer_add_event("dpd_event", dpd_event, sa,
+ &tv);
+ break;
+ case DPD_TIMER_CHECK:
+ tv.tv_sec += DPD_RETRANS_WAIT;
+ sa->dpd_event = timer_add_event("dpd_check_event",
+ dpd_check_event, sa, &tv);
+ break;
+ default:
+ }
+ if (!sa->dpd_event)
+ log_print("dpd_timer_reset: timer_add_event failed");
}
+/* Helper function for dpd_exchange_finalization(). */
static int
-dpd_responder_recv_notify(struct message *msg)
+dpd_find_sa(struct sa *sa, void *v_sa)
{
- struct payload *p = payload_first(msg, ISAKMP_PAYLOAD_NOTIFY);
- struct sa *isakmp_sa = msg->isakmp_sa;
- struct timeval tv;
- u_int32_t rseq;
+ struct sa *isakmp_sa = v_sa;
- if (msg->exchange->phase != 2) {
- message_drop(msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE, 0, 1,
- 0);
- return -1;
- }
+ return (sa->phase == 2 &&
+ memcmp(sa->id_i, isakmp_sa->id_i, sa->id_i_len) == 0 &&
+ memcmp(sa->id_r, isakmp_sa->id_r, sa->id_r_len) == 0);
+}
- if (GET_ISAKMP_NOTIFY_MSG_TYPE(p->p) !=
- ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE) {
- message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
- return -1;
- }
+struct dpd_args {
+ struct sa *isakmp_sa;
+ u_int32_t interval;
+};
- /* Presumably, we've gone through message_validate_notify(). */
- /* XXX */
+/* Helper function for dpd_event(). */
+static int
+dpd_check_time(struct sa *sa, void *v_arg)
+{
+ struct dpd_args *args = v_arg;
+ struct sockaddr *dst;
+ struct proto *proto;
+ struct sa_kinfo *ksa;
+ struct timeval tv;
- /* Validate the SPI. Perhaps move to message_validate_notify(). */
- if (memcmp(p->p + ISAKMP_NOTIFY_SPI_OFF, isakmp_sa->cookies,
- ISAKMP_HDR_COOKIES_LEN) != 0) {
- log_print("dpd_initiator_recv_notify: bad cookies");
- message_drop(msg, ISAKMP_NOTIFY_INVALID_SPI, 0, 1, 0);
- return -1;
- }
+ if (sa->phase == 1 || (args->isakmp_sa->flags & SA_FLAG_DPD) == 0 ||
+ dpd_find_sa(sa, args->isakmp_sa) == 0)
+ return 0;
- /* Get the seqno. */
- memcpy(p->p + ISAKMP_NOTIFY_SPI_OFF + ISAKMP_HDR_COOKIES_LEN, &rseq,
- sizeof rseq);
- rseq = ntohl(rseq);
+ proto = TAILQ_FIRST(&sa->protos);
+ if (!proto || !proto->data)
+ return 0;
+ sa->transport->vtbl->get_src(sa->transport, &dst);
- /* Check increasing seqno. */
- if (rseq <= isakmp_sa->dpd_rseq) {
- log_print("dpd_initiator_recv_notify: bad seqno (%u <= %u)",
- rseq, isakmp_sa->dpd_rseq);
- message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
- return -1;
- }
- isakmp_sa->dpd_rseq = rseq;
+ gettimeofday(&tv, 0);
+ ksa = sysdep_ipsec_get_kernel_sa(proto->spi[1], proto->spi_sz[1],
+ proto->proto, dst);
- /*
- * Ok, now we know the peer is alive, in case we're wondering.
- * If so, reset timers, etc... here.
- */
- if (isakmp_sa->dpd_nextev) {
- timer_remove_event(isakmp_sa->dpd_nextev);
- sa_release(isakmp_sa);
-
- gettimeofday(&tv, 0);
- tv.tv_sec += DPD_DEFAULT_WORRY_METRIC; /* XXX Configurable */
-
- isakmp_sa->dpd_nextev = timer_add_event("dpd_event", dpd_event,
- isakmp_sa, &tv);
- if (!isakmp_sa->dpd_nextev)
- log_print("dpd_responder_recv_notify: timer_add_event "
- "failed");
- else
- sa_reference(isakmp_sa);
- }
+ if (!ksa || !ksa->last_used)
+ return 0;
- /* Mark handled. */
- p->flags |= PL_MARK;
+ LOG_DBG((LOG_MESSAGE, 80, "dpd_check_time: "
+ "SA %p last use %u second(s) ago", sa,
+ (u_int32_t)(tv.tv_sec - ksa->last_used)));
+ if ((u_int32_t)(tv.tv_sec - ksa->last_used) < args->interval) {
+ args->interval = (u_int32_t)(tv.tv_sec - ksa->last_used);
+ return 1;
+ }
+
return 0;
}
-
-static int
-dpd_responder_send_ack(struct message *msg)
+
+/* Called by the timer. */
+static void
+dpd_event(void *v_sa)
{
- if (!msg->isakmp_sa)
- return -1;
+ struct sa *isakmp_sa = v_sa;
+ struct dpd_args args;
+#if defined (USE_DEBUG)
+ struct sockaddr *dst;
+ char *addr;
+#endif
+
+ isakmp_sa->dpd_event = 0;
+
+ /* Check if there's been any incoming SA activity since last time. */
+ args.isakmp_sa = isakmp_sa;
+ args.interval = dpd_timer_interval(0);
+ if (sa_find(dpd_check_time, &args)) {
+ if (args.interval > dpd_timer_interval(0))
+ args.interval = 0;
+ dpd_timer_reset(isakmp_sa, args.interval, DPD_TIMER_NORMAL);
+ return;
+ }
- return dpd_add_notify(msg, ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK,
- msg->isakmp_sa->dpd_rseq);
+ /* No activity seen, do a DPD exchange. */
+ if (isakmp_sa->dpd_seq == 0) {
+ /*
+ * RFC 3706: first seq# should be random, with MSB zero,
+ * otherwise we just increment it.
+ */
+ getrandom((u_int8_t *)&isakmp_sa->dpd_seq,
+ sizeof isakmp_sa->dpd_seq);
+ isakmp_sa->dpd_seq &= 0x7FFF;
+ } else
+ isakmp_sa->dpd_seq++;
+
+#if defined (USE_DEBUG)
+ isakmp_sa->transport->vtbl->get_dst(isakmp_sa->transport, &dst);
+ if (sockaddr2text(dst, &addr, 0) == -1)
+ addr = 0;
+ LOG_DBG((LOG_MESSAGE, 30, "dpd_event: sending R_U_THERE to %s seq %u",
+ addr ? addr : "<unknown>", isakmp_sa->dpd_seq));
+ if (addr)
+ free(addr);
+#endif
+ message_send_dpd_notify(isakmp_sa, ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE,
+ isakmp_sa->dpd_seq);
+
+ /* And set the short timer. */
+ dpd_timer_reset(isakmp_sa, 0, DPD_TIMER_CHECK);
}
+/*
+ * Called by the timer. If this function is called, it means we did not
+ * recieve any R_U_THERE_ACK confirmation from the other peer.
+ */
static void
-dpd_event(void *v_sa)
+dpd_check_event(void *v_sa)
{
- struct sa *sa = v_sa;
-
- sa->dpd_nextev = 0;
- sa_release(sa);
-
- if ((sa->flags & SA_FLAG_DPD) == 0)
+ struct sa *isakmp_sa = v_sa;
+ struct sa *sa;
+
+ isakmp_sa->dpd_event = 0;
+
+ if (++isakmp_sa->dpd_failcount < DPD_RETRANS_MAX) {
+ LOG_DBG((LOG_MESSAGE, 10, "dpd_check_event: "
+ "peer not responding, retry %u of %u",
+ isakmp_sa->dpd_failcount, DPD_RETRANS_MAX));
+ message_send_dpd_notify(isakmp_sa,
+ ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE, isakmp_sa->dpd_seq);
+ dpd_timer_reset(isakmp_sa, 0, DPD_TIMER_CHECK);
return;
-
- /* Create a new DPD exchange. XXX */
+ }
+
+ /*
+ * Peer is considered dead. Delete all SAs created under isakmp_sa.
+ */
+ LOG_DBG((LOG_MESSAGE, 10, "dpd_check_event: peer is dead, "
+ "deleting all SAs connected to SA %p", isakmp_sa));
+ while ((sa = sa_find(dpd_find_sa, isakmp_sa)) != 0) {
+ LOG_DBG((LOG_MESSAGE, 30, "dpd_check_event: deleting SA %p",
+ sa));
+ sa_delete(sa, 0);
+ }
+ LOG_DBG((LOG_MESSAGE, 30, "dpd_check_event: deleting ISAKMP SA %p",
+ isakmp_sa));
+ sa_delete(isakmp_sa, 0);
}
diff --git a/sbin/isakmpd/dpd.h b/sbin/isakmpd/dpd.h
index 6b6f1210deb..fa62c5b08b7 100644
--- a/sbin/isakmpd/dpd.h
+++ b/sbin/isakmpd/dpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dpd.h,v 1.1 2004/06/20 15:20:06 ho Exp $ */
+/* $OpenBSD: dpd.h,v 1.2 2004/08/10 15:59:10 ho Exp $ */
/*
* Copyright (c) 2004 Håkan Olsson. All rights reserved.
@@ -27,16 +27,12 @@
#ifndef _DPD_H_
#define _DPD_H_
-#define DPD_DEFAULT_WORRY_METRIC 300 /* seconds */
-
struct message;
struct payload;
+struct sa;
-int dpd_add_vendor_payload(struct message *);
-void dpd_check_vendor_payload(struct message *, struct payload *);
-
-extern int (*isakmp_dpd_initiator[])(struct message *);
-extern int (*isakmp_dpd_responder[])(struct message *);
-extern int16_t script_dpd[];
+int dpd_add_vendor_payload(struct message *);
+void dpd_check_vendor_payload(struct message *, struct payload *);
+void dpd_handle_notify(struct message *, struct payload *);
#endif /* _DPD_H_ */
diff --git a/sbin/isakmpd/exchange.c b/sbin/isakmpd/exchange.c
index 2d2073c52bf..2deec9cc793 100644
--- a/sbin/isakmpd/exchange.c
+++ b/sbin/isakmpd/exchange.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exchange.c,v 1.101 2004/08/08 19:11:06 deraadt Exp $ */
+/* $OpenBSD: exchange.c,v 1.102 2004/08/10 15:59:10 ho Exp $ */
/* $EOM: exchange.c,v 1.143 2000/12/04 00:02:25 angelos Exp $ */
/*
@@ -47,9 +47,6 @@
#include "cookie.h"
#include "crypto.h"
#include "doi.h"
-#ifdef USE_DPD
-#include "dpd.h"
-#endif
#include "exchange.h"
#include "ipsec_num.h"
#include "isakmp.h"
@@ -190,10 +187,6 @@ exchange_script(struct exchange *exchange)
case ISAKMP_EXCH_TRANSACTION:
return script_transaction;
#endif
-#ifdef USE_DPD
- case ISAKMP_EXCH_DPD:
- return script_dpd;
-#endif
default:
if (exchange->type >= ISAKMP_EXCH_DOI_MIN &&
exchange->type <= ISAKMP_EXCH_DOI_MAX)
@@ -854,10 +847,9 @@ exchange_establish_p1(struct transport *t, u_int8_t type, u_int32_t doi,
}
msg->exchange = exchange;
- /* Do not create SA for an information, transaction or DPD exchange. */
+ /* Do not create SA for an information or transaction exchange. */
if (exchange->type != ISAKMP_EXCH_INFO
- && exchange->type != ISAKMP_EXCH_TRANSACTION
- && exchange->type != ISAKMP_EXCH_DPD) {
+ && exchange->type != ISAKMP_EXCH_TRANSACTION) {
/*
* Don't install a transport into this SA as it will be an
* INADDR_ANY address in the local end, which is not good at
@@ -970,8 +962,7 @@ exchange_establish_p2(struct sa *isakmp_sa, u_int8_t type, char *name,
* XXX How to handle new group mode?
*/
if (exchange->type != ISAKMP_EXCH_INFO &&
- exchange->type != ISAKMP_EXCH_TRANSACTION &&
- exchange->type != ISAKMP_EXCH_DPD) {
+ exchange->type != ISAKMP_EXCH_TRANSACTION) {
/* XXX Number of SAs should come from the args structure. */
for (i = 0; i < 1; i++)
if (sa_create(exchange, isakmp_sa->transport)) {
diff --git a/sbin/isakmpd/ipsec.c b/sbin/isakmpd/ipsec.c
index a1537912a7b..8a80719e3bd 100644
--- a/sbin/isakmpd/ipsec.c
+++ b/sbin/isakmpd/ipsec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsec.c,v 1.102 2004/08/08 19:11:06 deraadt Exp $ */
+/* $OpenBSD: ipsec.c,v 1.103 2004/08/10 15:59:10 ho Exp $ */
/* $EOM: ipsec.c,v 1.143 2000/12/11 23:57:42 niklas Exp $ */
/*
@@ -47,6 +47,9 @@
#include "crypto.h"
#include "dh.h"
#include "doi.h"
+#if defined (USE_DPD)
+#include "dpd.h"
+#endif
#include "exchange.h"
#include "hash.h"
#include "ike_aggressive.h"
@@ -928,11 +931,13 @@ ipsec_initiator(struct message *msg)
/* Check that the SA is coherent with the IKE rules. */
if (exchange->type != ISAKMP_EXCH_TRANSACTION
- && ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT
- && exchange->type != ISAKMP_EXCH_AGGRESSIVE
- && exchange->type != ISAKMP_EXCH_INFO)
- || (exchange->phase == 2 && exchange->type != IKE_EXCH_QUICK_MODE
- && exchange->type != ISAKMP_EXCH_INFO))) {
+ && ((exchange->phase == 1 &&
+ exchange->type != ISAKMP_EXCH_ID_PROT &&
+ exchange->type != ISAKMP_EXCH_AGGRESSIVE &&
+ exchange->type != ISAKMP_EXCH_INFO)
+ || (exchange->phase == 2 &&
+ exchange->type != IKE_EXCH_QUICK_MODE &&
+ exchange->type != ISAKMP_EXCH_INFO))) {
log_print("ipsec_initiator: unsupported exchange type %d "
"in phase %d", exchange->type, exchange->phase);
return -1;
@@ -1023,11 +1028,13 @@ ipsec_responder(struct message *msg)
/* Check that a new exchange is coherent with the IKE rules. */
if (exchange->step == 0 && exchange->type != ISAKMP_EXCH_TRANSACTION
- && ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT
- && exchange->type != ISAKMP_EXCH_AGGRESSIVE
- && exchange->type != ISAKMP_EXCH_INFO)
- || (exchange->phase == 2 && exchange->type ==
- ISAKMP_EXCH_ID_PROT))) {
+ && ((exchange->phase == 1 &&
+ exchange->type != ISAKMP_EXCH_ID_PROT &&
+ exchange->type != ISAKMP_EXCH_AGGRESSIVE &&
+ exchange->type != ISAKMP_EXCH_INFO)
+ || (exchange->phase == 2 &&
+ exchange->type != IKE_EXCH_QUICK_MODE &&
+ exchange->type != ISAKMP_EXCH_INFO))) {
message_drop(msg, ISAKMP_NOTIFY_UNSUPPORTED_EXCHANGE_TYPE,
0, 1, 0);
return -1;
@@ -1038,19 +1045,16 @@ ipsec_responder(struct message *msg)
case ISAKMP_EXCH_ID_PROT:
script = ike_main_mode_responder;
break;
-
#ifdef USE_AGGRESSIVE
case ISAKMP_EXCH_AGGRESSIVE:
script = ike_aggressive_responder;
break;
#endif
-
#ifdef USE_ISAKMP_CFG
case ISAKMP_EXCH_TRANSACTION:
script = isakmp_cfg_responder;
break;
#endif
-
case ISAKMP_EXCH_INFO:
for (p = payload_first(msg, ISAKMP_PAYLOAD_NOTIFY); p;
p = TAILQ_NEXT(p, link)) {
@@ -1064,6 +1068,13 @@ ipsec_responder(struct message *msg)
/* Handled by leftover logic. */
break;
+#if defined (USE_DPD)
+ case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE:
+ case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK:
+ dpd_handle_notify(msg, p);
+ break;
+#endif
+
default:
p->flags |= PL_MARK;
break;
@@ -1074,7 +1085,6 @@ ipsec_responder(struct message *msg)
* If any DELETEs are in here, let the logic of leftover
* payloads deal with them.
*/
-
return 0;
case IKE_EXCH_QUICK_MODE:
diff --git a/sbin/isakmpd/isakmp_num.cst b/sbin/isakmpd/isakmp_num.cst
index 24d994abbfa..45d3963bc90 100644
--- a/sbin/isakmpd/isakmp_num.cst
+++ b/sbin/isakmpd/isakmp_num.cst
@@ -1,4 +1,4 @@
-# $OpenBSD: isakmp_num.cst,v 1.9 2004/06/20 15:20:07 ho Exp $
+# $OpenBSD: isakmp_num.cst,v 1.10 2004/08/10 15:59:10 ho Exp $
# $EOM: isakmp_num.cst,v 1.3 2000/05/17 03:09:50 angelos Exp $
#
@@ -78,8 +78,7 @@ ISAKMP_EXCH
INFO 5
# XXX the following are not quite legitimate according to the IETF process
TRANSACTION 6
- DPD 7
- FUTURE_MIN 8
+ FUTURE_MIN 7
FUTURE_MAX 31
DOI_MIN 32
DOI_MAX 255
diff --git a/sbin/isakmpd/isakmpd.conf.5 b/sbin/isakmpd/isakmpd.conf.5
index c1020578876..db3dd7869df 100644
--- a/sbin/isakmpd/isakmpd.conf.5
+++ b/sbin/isakmpd/isakmpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: isakmpd.conf.5,v 1.93 2004/07/08 10:37:12 jmc Exp $
+.\" $OpenBSD: isakmpd.conf.5,v 1.94 2004/08/10 15:59:10 ho Exp $
.\" $EOM: isakmpd.conf.5,v 1.57 2000/12/21 14:43:17 ho Exp $
.\"
.\" Copyright (c) 1998, 1999, 2000 Niklas Hallqvist. All rights reserved.
@@ -170,7 +170,11 @@ Thus
.Nm isakmpd
only takes care of the SA establishment.
.It Em Check-interval
-The interval between watchdog checks of connections we want up at all times.
+The interval between watchdog checks of connections we want up at all
+times.
+.It Em DPD-check-interval
+The interval between RFC 3706 (Dead Peer Detection) messages.
+The default value is 0 (zero), which means DPD is disabled.
.It Em Exchange-max-time
How many seconds should an exchange maximally take to set up before we
give up.
diff --git a/sbin/isakmpd/message.c b/sbin/isakmpd/message.c
index 313f2379a2e..4b99e400004 100644
--- a/sbin/isakmpd/message.c
+++ b/sbin/isakmpd/message.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: message.c,v 1.86 2004/08/08 19:11:06 deraadt Exp $ */
+/* $OpenBSD: message.c,v 1.87 2004/08/10 15:59:10 ho Exp $ */
/* $EOM: message.c,v 1.156 2000/10/10 12:36:39 provos Exp $ */
/*
@@ -888,7 +888,16 @@ message_validate_notify(struct message *msg, struct payload *p)
message_free(msg);
return -1;
}
- /* XXX Validate the SPI. */
+
+ /* Validate the SPI. XXX Just ISAKMP for now. */
+ if (proto == ISAKMP_PROTO_ISAKMP &&
+ GET_ISAKMP_NOTIFY_SPI_SZ(p->p) == ISAKMP_HDR_COOKIES_LEN &&
+ memcmp(p->p + ISAKMP_NOTIFY_SPI_OFF, msg->isakmp_sa->cookies,
+ ISAKMP_HDR_COOKIES_LEN) != 0) {
+ log_print("message_validate_notify: bad cookies");
+ message_drop(msg, ISAKMP_NOTIFY_INVALID_SPI, 0, 1, 0);
+ return -1;
+ }
if (type < ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE
|| (type >= ISAKMP_NOTIFY_RESERVED_MIN
@@ -904,6 +913,7 @@ message_validate_notify(struct message *msg, struct payload *p)
message_free(msg);
return -1;
}
+
return 0;
}
@@ -1521,6 +1531,8 @@ message_send(struct message *msg)
&& exchange->flags & EXCHANGE_FLAG_ENCRYPT) {
if (!exchange->keystate) {
exchange->keystate = exchange->doi->get_keystate(msg);
+ if (!exchange->keystate)
+ return;
exchange->crypto = exchange->keystate->xf;
exchange->flags |= EXCHANGE_FLAG_ENCRYPT;
}
@@ -1647,6 +1659,13 @@ struct info_args {
u_int16_t nspis;
u_int8_t *spis;
} d;
+#if defined (USE_DPD)
+ struct {
+ u_int16_t msg_type;
+ u_int8_t *spi;
+ u_int32_t seq;
+ } dpd;
+#endif
} u;
};
@@ -1714,12 +1733,30 @@ message_send_delete(struct sa *sa)
}
}
+#if defined (USE_DPD)
+void
+message_send_dpd_notify(struct sa* isakmp_sa, u_int16_t notify, u_int32_t seq)
+{
+ struct info_args args;
+
+ args.discr = 'P';
+ args.doi = IPSEC_DOI_IPSEC;
+ args.proto = ISAKMP_PROTO_ISAKMP;
+ args.spi_sz = ISAKMP_HDR_COOKIES_LEN;
+ args.u.dpd.msg_type = notify;
+ args.u.dpd.spi = isakmp_sa->cookies;
+ args.u.dpd.seq = htonl(seq);
+
+ exchange_establish_p2(isakmp_sa, ISAKMP_EXCH_INFO, 0, &args, 0, 0);
+}
+#endif
+
/* Build the informational message into MSG. */
int
message_send_info(struct message *msg)
{
u_int8_t *buf;
- size_t sz;
+ size_t sz = 0;
struct info_args *args = msg->extra;
u_int8_t payload;
@@ -1728,8 +1765,21 @@ message_send_info(struct message *msg)
if (msg->exchange->doi->informational_pre_hook(msg))
return -1;
- sz = (args->discr == 'N' ? ISAKMP_NOTIFY_SPI_OFF + args->spi_sz
- : ISAKMP_DELETE_SPI_OFF + args->u.d.nspis * args->spi_sz);
+ switch (args->discr) {
+#if defined (USE_DPD)
+ case 'P':
+ sz = sizeof args->u.dpd.seq;
+ /* FALLTHROUGH */
+#endif
+ case 'N':
+ sz += ISAKMP_NOTIFY_SPI_OFF + args->spi_sz;
+ break;
+ case 'D':
+ default: /* Silence gcc */
+ sz = ISAKMP_DELETE_SPI_OFF + args->u.d.nspis * args->spi_sz;
+ break;
+ }
+
buf = calloc(1, sz);
if (!buf) {
log_error("message_send_info: calloc (1, %lu) failed",
@@ -1738,6 +1788,12 @@ message_send_info(struct message *msg)
return -1;
}
switch (args->discr) {
+#if defined (USE_DPD)
+ case 'P':
+ memcpy(buf + ISAKMP_NOTIFY_SPI_OFF + args->spi_sz,
+ &args->u.dpd.seq, sizeof args->u.dpd.seq);
+ /* FALLTHROUGH */
+#endif
case 'N':
/* Build the NOTIFY payload. */
payload = ISAKMP_PAYLOAD_NOTIFY;
diff --git a/sbin/isakmpd/message.h b/sbin/isakmpd/message.h
index 63d05d9f7d3..14b1d9a9977 100644
--- a/sbin/isakmpd/message.h
+++ b/sbin/isakmpd/message.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: message.h,v 1.21 2004/06/20 17:17:35 ho Exp $ */
+/* $OpenBSD: message.h,v 1.22 2004/08/10 15:59:10 ho Exp $ */
/* $EOM: message.h,v 1.51 2000/10/10 12:36:39 provos Exp $ */
/*
@@ -198,4 +198,8 @@ extern void message_setup_header(struct message *, u_int8_t, u_int8_t,
struct payload *payload_first(struct message *, u_int8_t);
struct payload *payload_last(struct message *, u_int8_t);
+#if defined (USE_DPD)
+extern void message_send_dpd_notify(struct sa*, u_int16_t, u_int32_t);
+#endif
+
#endif /* _MESSAGE_H_ */
diff --git a/sbin/isakmpd/pf_key_v2.c b/sbin/isakmpd/pf_key_v2.c
index e89ba626eb7..41637f51cf4 100644
--- a/sbin/isakmpd/pf_key_v2.c
+++ b/sbin/isakmpd/pf_key_v2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_key_v2.c,v 1.147 2004/08/08 19:11:06 deraadt Exp $ */
+/* $OpenBSD: pf_key_v2.c,v 1.148 2004/08/10 15:59:10 ho Exp $ */
/* $EOM: pf_key_v2.c,v 1.79 2000/12/12 00:33:19 niklas Exp $ */
/*
@@ -680,7 +680,7 @@ pf_key_v2_get_spi(size_t *sz, u_int8_t proto, struct sockaddr *src,
break;
}
if (pf_key_v2_msg_add(getspi, (struct sadb_ext *) addr,
- PF_KEY_V2_NODE_MALLOCED) == -1)
+ PF_KEY_V2_NODE_MALLOCED) == -1)
goto cleanup;
addr = 0;
@@ -777,6 +777,203 @@ cleanup:
return 0;
}
+/* Fetch SA information from the kernel. XXX OpenBSD only? */
+struct sa_kinfo *
+pf_key_v2_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto,
+ struct sockaddr *dst)
+{
+ struct sadb_msg msg;
+ struct sadb_sa *ssa;
+ struct sadb_address *addr = 0;
+ struct sockaddr *sa;
+ struct sadb_lifetime *life;
+ struct pf_key_v2_msg *gettdb = 0, *ret = 0;
+ struct pf_key_v2_node *ext;
+ static struct sa_kinfo ksa;
+#if defined (SADB_X_EXT_UDPENCAP)
+ struct sadb_x_udpencap *udpencap;
+#endif
+ int len, err;
+
+ if (spi_sz != sizeof (ssa->sadb_sa_spi))
+ return 0;
+
+ msg.sadb_msg_type = SADB_GET;
+ switch (proto) {
+ case IPSEC_PROTO_IPSEC_ESP:
+ msg.sadb_msg_satype = SADB_SATYPE_ESP;
+ break;
+ case IPSEC_PROTO_IPSEC_AH:
+ msg.sadb_msg_satype = SADB_SATYPE_AH;
+ break;
+#ifdef SADB_X_SATYPE_IPCOMP
+ case IPSEC_PROTO_IPCOMP:
+ msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP;
+ break;
+#endif
+ default:
+ log_print("pf_key_v2_get_kernel_sa: invalid proto %d", proto);
+ goto cleanup;
+ }
+
+ gettdb = pf_key_v2_msg_new(&msg, 0);
+ if (!gettdb)
+ goto cleanup;
+
+ /* SPI */
+ ssa = (struct sadb_sa *)calloc(1, sizeof *ssa);
+ if (!ssa) {
+ log_print("pf_key_v2_get_kernel_sa: calloc(1, %lu) failed",
+ (unsigned long)sizeof *ssa);
+ goto cleanup;
+ }
+
+ ssa->sadb_sa_exttype = SADB_EXT_SA;
+ ssa->sadb_sa_len = sizeof *ssa / PF_KEY_V2_CHUNK;
+ memcpy(&ssa->sadb_sa_spi, spi, sizeof ssa->sadb_sa_spi);
+ ssa->sadb_sa_state = SADB_SASTATE_MATURE;
+ if (pf_key_v2_msg_add(gettdb, (struct sadb_ext *)ssa,
+ PF_KEY_V2_NODE_MALLOCED) == -1)
+ goto cleanup;
+ ssa = 0;
+
+ /* XXX KAME SADB_X_EXT_xyz here? */
+
+ /* Address */
+ len =
+ sizeof(struct sadb_address) + PF_KEY_V2_ROUND(sysdep_sa_len(dst));
+ addr = calloc(1, len);
+ if (!addr)
+ goto cleanup;
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ addr->sadb_address_len = len / PF_KEY_V2_CHUNK;
+#ifndef __OpenBSD__
+ addr->sadb_address_proto = 0;
+ addr->sadb_address_prefixlen = 0;
+#endif
+ addr->sadb_address_reserved = 0;
+ memcpy(addr + 1, dst, sysdep_sa_len(dst));
+ switch (((struct sockaddr *) (addr + 1))->sa_family) {
+ case AF_INET:
+ ((struct sockaddr_in *) (addr + 1))->sin_port = 0;
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0;
+ break;
+ }
+ if (pf_key_v2_msg_add(gettdb, (struct sadb_ext *)addr,
+ PF_KEY_V2_NODE_MALLOCED) == -1)
+ goto cleanup;
+ addr = 0;
+
+ ret = pf_key_v2_call(gettdb);
+ pf_key_v2_msg_free(gettdb);
+ gettdb = 0;
+ if (!ret)
+ goto cleanup;
+ err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno;
+ if (err) {
+ log_print("pf_key_v2_get_kernel_sa: SADB_GET: %s",
+ strerror(err));
+ goto cleanup;
+ }
+
+ /* Extract the data. */
+ memset(&ksa, 0, sizeof ksa);
+
+ ext = pf_key_v2_find_ext(ret, SADB_EXT_SA);
+ if (!ext)
+ goto cleanup;
+
+ ssa = (struct sadb_sa *)ext;
+ ksa.spi = ssa->sadb_sa_spi;
+ ksa.wnd = ssa->sadb_sa_replay;
+ ksa.flags = ssa->sadb_sa_flags;
+
+ ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_CURRENT);
+ if (ext) {
+ life = (struct sadb_lifetime *)ext->seg;
+ ksa.cur_allocations = life->sadb_lifetime_allocations;
+ ksa.cur_bytes = life->sadb_lifetime_bytes;
+ ksa.first_use = life->sadb_lifetime_usetime;
+ ksa.established = life->sadb_lifetime_addtime;
+ }
+
+ ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_SOFT);
+ if (ext) {
+ life = (struct sadb_lifetime *)ext->seg;
+ ksa.soft_allocations = life->sadb_lifetime_allocations;
+ ksa.soft_bytes = life->sadb_lifetime_bytes;
+ ksa.soft_timeout = life->sadb_lifetime_addtime;
+ ksa.soft_first_use = life->sadb_lifetime_usetime;
+ }
+
+ ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_HARD);
+ if (ext) {
+ life = (struct sadb_lifetime *)ext->seg;
+ ksa.exp_allocations = life->sadb_lifetime_allocations;
+ ksa.exp_bytes = life->sadb_lifetime_bytes;
+ ksa.exp_timeout = life->sadb_lifetime_addtime;
+ ksa.exp_first_use = life->sadb_lifetime_usetime;
+ }
+
+#if defined (SADB_X_EXT_LIFETIME_LASTUSE)
+ ext = pf_key_v2_find_ext(ret, SADB_X_EXT_LIFETIME_LASTUSE);
+ if (ext) {
+ life = (struct sadb_lifetime *)ext->seg;
+ ksa.last_used = life->sadb_lifetime_usetime;
+ }
+#endif
+
+ ext = pf_key_v2_find_ext(ret, SADB_EXT_ADDRESS_SRC);
+ if (ext) {
+ sa = (struct sockaddr *)ext->seg;
+ memcpy(&ksa.src, sa,
+ sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6));
+ }
+
+ ext = pf_key_v2_find_ext(ret, SADB_EXT_ADDRESS_DST);
+ if (ext) {
+ sa = (struct sockaddr *)ext->seg;
+ memcpy(&ksa.dst, sa,
+ sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6));
+ }
+
+ ext = pf_key_v2_find_ext(ret, SADB_EXT_ADDRESS_PROXY);
+ if (ext) {
+ sa = (struct sockaddr *)ext->seg;
+ memcpy(sa, &ksa.proxy,
+ sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6));
+ }
+
+#if defined (SADB_X_EXT_UDPENCAP)
+ ext = pf_key_v2_find_ext(ret, SADB_X_EXT_UDPENCAP);
+ if (ext) {
+ udpencap = (struct sadb_x_udpencap *)ext->seg;
+ ksa.udpencap_port = udpencap->sadb_x_udpencap_port;
+ }
+#endif
+
+ pf_key_v2_msg_free(ret);
+
+ LOG_DBG_BUF((LOG_SYSDEP, 50, "pf_key_v2_get_kernel_sa: spi", spi,
+ spi_sz));
+
+ return &ksa;
+
+ cleanup:
+ if (addr)
+ free (addr);
+ if (gettdb)
+ pf_key_v2_msg_free(gettdb);
+ if (ret)
+ pf_key_v2_msg_free(ret);
+ return 0;
+}
+
static void
pf_key_v2_setup_sockaddr(void *res, struct sockaddr *src,
struct sockaddr *dst, in_port_t port, int ingress)
diff --git a/sbin/isakmpd/pf_key_v2.h b/sbin/isakmpd/pf_key_v2.h
index 374c07f3d56..8eaed1a8b45 100644
--- a/sbin/isakmpd/pf_key_v2.h
+++ b/sbin/isakmpd/pf_key_v2.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_key_v2.h,v 1.11 2004/06/26 06:07:03 hshoexer Exp $ */
+/* $OpenBSD: pf_key_v2.h,v 1.12 2004/08/10 15:59:10 ho Exp $ */
/* $EOM: pf_key_v2.h,v 1.4 2000/12/04 04:46:35 angelos Exp $ */
/*
@@ -38,6 +38,7 @@
struct proto;
struct sa;
struct sockaddr;
+struct kernel_sa;
extern int pf_key_v2_socket;
@@ -45,13 +46,16 @@ extern void pf_key_v2_connection_check(char *);
extern int pf_key_v2_delete_spi(struct sa *, struct proto *, int);
extern int pf_key_v2_enable_sa(struct sa *, struct sa *);
extern int pf_key_v2_enable_spi(in_addr_t, in_addr_t, in_addr_t,
- in_addr_t, u_int8_t *, u_int8_t, in_addr_t);
+ in_addr_t, u_int8_t *, u_int8_t, in_addr_t);
+extern struct sa_kinfo *pf_key_v2_get_kernel_sa(u_int8_t *, size_t, u_int8_t,
+ struct sockaddr *);
extern u_int8_t *pf_key_v2_get_spi(size_t *, u_int8_t, struct sockaddr *,
- struct sockaddr *, u_int32_t);
+ struct sockaddr *, u_int32_t);
extern int pf_key_v2_group_spis(struct sa *, struct proto *,
- struct proto *, int);
+ struct proto *, int);
extern void pf_key_v2_handler(int);
extern int pf_key_v2_open(void);
-extern int pf_key_v2_set_spi(struct sa *, struct proto *, int, struct sa *);
+extern int pf_key_v2_set_spi(struct sa *, struct proto *, int,
+ struct sa *);
#endif /* _PF_KEY_V2_H_ */
diff --git a/sbin/isakmpd/sa.c b/sbin/isakmpd/sa.c
index 977c7e00e91..14c78576687 100644
--- a/sbin/isakmpd/sa.c
+++ b/sbin/isakmpd/sa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sa.c,v 1.85 2004/08/08 19:11:06 deraadt Exp $ */
+/* $OpenBSD: sa.c,v 1.86 2004/08/10 15:59:10 ho Exp $ */
/* $EOM: sa.c,v 1.112 2000/12/12 00:22:52 niklas Exp $ */
/*
@@ -799,8 +799,8 @@ sa_release(struct sa *sa)
timer_remove_event(sa->nat_t_keepalive);
#endif
#if defined (USE_DPD)
- if (sa->dpd_nextev)
- timer_remove_event(sa->dpd_nextev);
+ if (sa->dpd_event)
+ timer_remove_event(sa->dpd_event);
#endif
if (sa->transport)
transport_release(sa->transport);
diff --git a/sbin/isakmpd/sa.h b/sbin/isakmpd/sa.h
index c0635dc43bf..4f6100f83a7 100644
--- a/sbin/isakmpd/sa.h
+++ b/sbin/isakmpd/sa.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sa.h,v 1.40 2004/06/21 23:27:10 ho Exp $ */
+/* $OpenBSD: sa.h,v 1.41 2004/08/10 15:59:10 ho Exp $ */
/* $EOM: sa.h,v 1.58 2000/10/10 12:39:01 provos Exp $ */
/*
@@ -212,7 +212,8 @@ struct sa {
/* IKE DPD (RFC3706) message sequence number. */
u_int32_t dpd_seq; /* sent */
u_int32_t dpd_rseq; /* recieved */
- struct event *dpd_nextev; /* time of next event */
+ u_int32_t dpd_failcount; /* # of subsequent failures */
+ struct event *dpd_event; /* time of next event */
#endif
};
@@ -272,4 +273,46 @@ extern void sa_report(void);
extern void sa_dump(int, int, char *, struct sa *);
extern void sa_report_all(FILE *);
extern int sa_setup_expirations(struct sa *);
+
+/*
+ * This structure contains most of the data of the in-kernel SA.
+ * Currently only used to collect the tdb_last_used time for DPD.
+ */
+struct sa_kinfo {
+ u_int32_t flags; /* /usr/include/netinet/ip_ipsp.h */
+
+ u_int32_t exp_allocations;
+ u_int32_t soft_allocations;
+ u_int32_t cur_allocations;
+
+ u_int64_t exp_bytes;
+ u_int64_t soft_bytes;
+ u_int64_t cur_bytes;
+
+ u_int64_t exp_timeout;
+ u_int64_t soft_timeout;
+
+ u_int64_t first_use;
+ u_int64_t established;
+ u_int64_t soft_first_use;
+ u_int64_t exp_first_use;
+
+ u_int64_t last_used;
+ u_int64_t last_marked;
+
+ struct sockaddr_storage dst;
+ struct sockaddr_storage src;
+ struct sockaddr_storage proxy;
+
+ u_int32_t spi;
+ u_int32_t rpl;
+ u_int16_t udpencap_port;
+ u_int16_t amxkeylen;
+ u_int16_t emxkeylen;
+ u_int16_t ivlen;
+ u_int8_t sproto;
+ u_int8_t wnd;
+ u_int8_t satype;
+};
+
#endif /* _SA_H_ */
diff --git a/sbin/isakmpd/sysdep.h b/sbin/isakmpd/sysdep.h
index 7bc7826f283..50de8191d09 100644
--- a/sbin/isakmpd/sysdep.h
+++ b/sbin/isakmpd/sysdep.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysdep.h,v 1.18 2004/08/08 19:11:06 deraadt Exp $ */
+/* $OpenBSD: sysdep.h,v 1.19 2004/08/10 15:59:10 ho Exp $ */
/* $EOM: sysdep.h,v 1.17 2000/12/04 04:46:35 angelos Exp $ */
/*
@@ -50,15 +50,14 @@ extern int sysdep_cleartext(int, int);
extern void sysdep_connection_check(char *);
extern int sysdep_ipsec_delete_spi(struct sa *, struct proto *, int);
extern int sysdep_ipsec_enable_sa(struct sa *, struct sa *);
-extern u_int8_t *
-sysdep_ipsec_get_spi(size_t *, u_int8_t, struct sockaddr *,
- struct sockaddr *, u_int32_t);
-extern int
-sysdep_ipsec_group_spis(struct sa *, struct proto *,
- struct proto *, int);
-extern int
-sysdep_ipsec_set_spi(struct sa *, struct proto *, int,
- struct sa *);
+extern u_int8_t *sysdep_ipsec_get_spi(size_t *, u_int8_t, struct sockaddr *,
+ struct sockaddr *, u_int32_t);
+extern struct sa_kinfo *sysdep_ipsec_get_kernel_sa(u_int8_t *, size_t,
+ u_int8_t, struct sockaddr *);
+extern int sysdep_ipsec_group_spis(struct sa *, struct proto *,
+ struct proto *, int);
+extern int sysdep_ipsec_set_spi(struct sa *, struct proto *, int,
+ struct sa *);
extern char *sysdep_progname(void);
extern u_int32_t sysdep_random(void);
extern u_int8_t sysdep_sa_len(struct sockaddr *);
diff --git a/sbin/isakmpd/sysdep/bsdi/sysdep.c b/sbin/isakmpd/sysdep/bsdi/sysdep.c
index ba6e7c5c7cf..99715d55e55 100644
--- a/sbin/isakmpd/sysdep/bsdi/sysdep.c
+++ b/sbin/isakmpd/sysdep/bsdi/sysdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysdep.c,v 1.11 2003/06/03 14:53:11 ho Exp $ */
+/* $OpenBSD: sysdep.c,v 1.12 2004/08/10 15:59:10 ho Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -121,6 +121,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src,
return KEY_API (get_spi) (sz, proto, src, dst, seq);
}
+struct sa_kinfo *
+sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto,
+ struct sockaddr *dst)
+{
+ if (app_none)
+ return 0;
+ /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */
+ return 0;
+}
+
/* Force communication on socket FD to go in the clear. */
int
sysdep_cleartext (int fd, int af)
diff --git a/sbin/isakmpd/sysdep/darwin/sysdep.c b/sbin/isakmpd/sysdep/darwin/sysdep.c
index d09002bb72e..cd61d5ae84c 100644
--- a/sbin/isakmpd/sysdep/darwin/sysdep.c
+++ b/sbin/isakmpd/sysdep/darwin/sysdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysdep.c,v 1.2 2003/06/03 14:53:11 ho Exp $ */
+/* $OpenBSD: sysdep.c,v 1.3 2004/08/10 15:59:10 ho Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -124,6 +124,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src,
return KEY_API (get_spi) (sz, proto, src, dst, seq);
}
+struct sa_kinfo *
+sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto,
+ struct sockaddr *dst)
+{
+ if (app_none)
+ return 0;
+ /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */
+ return 0;
+}
+
/* Force communication on socket FD to go in the clear. */
int
sysdep_cleartext (int fd, int af)
diff --git a/sbin/isakmpd/sysdep/freebsd/sysdep.c b/sbin/isakmpd/sysdep/freebsd/sysdep.c
index 62043d8f6ed..2679fc814c6 100644
--- a/sbin/isakmpd/sysdep/freebsd/sysdep.c
+++ b/sbin/isakmpd/sysdep/freebsd/sysdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysdep.c,v 1.12 2003/06/03 14:53:11 ho Exp $ */
+/* $OpenBSD: sysdep.c,v 1.13 2004/08/10 15:59:10 ho Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -124,6 +124,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src,
return KEY_API (get_spi) (sz, proto, src, dst, seq);
}
+struct sa_kinfo *
+sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto,
+ struct sockaddr *dst)
+{
+ if (app_none)
+ return 0;
+ /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */
+ return 0;
+}
+
/* Force communication on socket FD to go in the clear. */
int
sysdep_cleartext (int fd, int af)
diff --git a/sbin/isakmpd/sysdep/freeswan/sysdep.c b/sbin/isakmpd/sysdep/freeswan/sysdep.c
index afba442aa4c..9e99d7e0c68 100644
--- a/sbin/isakmpd/sysdep/freeswan/sysdep.c
+++ b/sbin/isakmpd/sysdep/freeswan/sysdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysdep.c,v 1.2 2003/06/03 14:53:11 ho Exp $ */
+/* $OpenBSD: sysdep.c,v 1.3 2004/08/10 15:59:10 ho Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -142,6 +142,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src,
return klips_get_spi (sz, proto, src, dst, seq);
}
+struct sa_kinfo *
+sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto,
+ struct sockaddr *dst)
+{
+ if (app_none)
+ return 0;
+ /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */
+ return 0;
+}
+
int
sysdep_cleartext (int fd, int af)
{
diff --git a/sbin/isakmpd/sysdep/linux/sysdep.c b/sbin/isakmpd/sysdep/linux/sysdep.c
index 927b2059c22..4eab40b3878 100644
--- a/sbin/isakmpd/sysdep/linux/sysdep.c
+++ b/sbin/isakmpd/sysdep/linux/sysdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysdep.c,v 1.15 2003/12/14 14:34:58 ho Exp $ */
+/* $OpenBSD: sysdep.c,v 1.16 2004/08/10 15:59:10 ho Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -132,6 +132,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src,
return KEY_API (get_spi) (sz, proto, src, dst, seq);
}
+struct sa_kinfo *
+sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto,
+ struct sockaddr *dst)
+{
+ if (app_none)
+ return 0;
+ /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */
+ return 0;
+}
+
/* Force communication on socket FD to go in the clear. */
int
sysdep_cleartext (int fd, int af)
diff --git a/sbin/isakmpd/sysdep/netbsd/sysdep.c b/sbin/isakmpd/sysdep/netbsd/sysdep.c
index 3d3d1103f81..272071561ec 100644
--- a/sbin/isakmpd/sysdep/netbsd/sysdep.c
+++ b/sbin/isakmpd/sysdep/netbsd/sysdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysdep.c,v 1.12 2003/06/03 14:53:11 ho Exp $ */
+/* $OpenBSD: sysdep.c,v 1.13 2004/08/10 15:59:10 ho Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -121,6 +121,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src,
return KEY_API (get_spi) (sz, proto, src, dst, seq);
}
+struct sa_kinfo *
+sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto,
+ struct sockaddr *dst)
+{
+ if (app_none)
+ return 0;
+ /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */
+ return 0;
+}
+
/* Force communication on socket FD to go in the clear. */
int
sysdep_cleartext (int fd, int af)
diff --git a/sbin/isakmpd/sysdep/openbsd/sysdep.c b/sbin/isakmpd/sysdep/openbsd/sysdep.c
index fc4b14d8af2..f59922fde23 100644
--- a/sbin/isakmpd/sysdep/openbsd/sysdep.c
+++ b/sbin/isakmpd/sysdep/openbsd/sysdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysdep.c,v 1.27 2004/06/26 06:07:03 hshoexer Exp $ */
+/* $OpenBSD: sysdep.c,v 1.28 2004/08/10 15:59:11 ho Exp $ */
/* $EOM: sysdep.c,v 1.9 2000/12/04 04:46:35 angelos Exp $ */
/*
@@ -133,6 +133,15 @@ sysdep_ipsec_get_spi(size_t *sz, u_int8_t proto, struct sockaddr *src,
return KEY_API(get_spi)(sz, proto, src, dst, seq);
}
+struct sa_kinfo *
+sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto,
+ struct sockaddr *dst)
+{
+ if (app_none)
+ return 0;
+ return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst);
+}
+
/* Force communication on socket FD to go in the clear. */
int
sysdep_cleartext(int fd, int af)
diff --git a/sbin/isakmpd/udp_encap.c b/sbin/isakmpd/udp_encap.c
index a01cbf78e59..3acd1ca98e1 100644
--- a/sbin/isakmpd/udp_encap.c
+++ b/sbin/isakmpd/udp_encap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_encap.c,v 1.6 2004/08/08 19:11:06 deraadt Exp $ */
+/* $OpenBSD: udp_encap.c,v 1.7 2004/08/10 15:59:10 ho Exp $ */
/*
* Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved.
@@ -381,7 +381,7 @@ udp_encap_handle_message(struct transport *t)
/* Check NULL-ESP marker. */
if (n < (ssize_t)sizeof(u_int32_t) || *(u_int32_t *)buf != 0) {
/* Should never happen. */
- log_print ("udp_encap_handle_message: "
+ log_print("udp_encap_handle_message: "
"Null-ESP marker not NULL or short message");
return;
}
@@ -389,11 +389,11 @@ udp_encap_handle_message(struct transport *t)
msg = message_alloc(t, buf + sizeof (u_int32_t),
n - sizeof (u_int32_t));
if (!msg) {
- log_error ("failed to allocate message structure, dropping "
+ log_error("failed to allocate message structure, dropping "
"packet received on transport %p", u);
return;
}
- message_recv (msg);
+ message_recv(msg);
}
/*