summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1999-06-02 06:31:38 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1999-06-02 06:31:38 +0000
commit2b676f350cc1924807d84c10db98496102b1e91d (patch)
tree20bfb862f72b39e689febc7d3cd90924747f39cb /sbin
parentbca265bb9f5518313f60b3b969aab23edc86c814 (diff)
Merge with EOM 1.14
author: ho We do not require flags on implicit passive connections. author: ho Fix bug in matching IDs. Cleanup debugging. author: ho bug fix of decode_id function. author: ho Temp. add some more debugging around setup of passive connection author: ho Add more debugging output and correct connection_report author: niklas Some extra error checking, documentation and style wrt connections author: ho More passive connection support author: niklas Small bugfixes and style nits author: ho Expand the passive connection mechanism. author: niklas Some more #if 0 stuff for passive connections author: ho Commit to embryonic code for passive connections author: niklas Some type pedantery. Comment style nits. author: ho Add connections_report and connection_reinit
Diffstat (limited to 'sbin')
-rw-r--r--sbin/isakmpd/connection.c305
1 files changed, 300 insertions, 5 deletions
diff --git a/sbin/isakmpd/connection.c b/sbin/isakmpd/connection.c
index 8614b0023e1..69daecd049b 100644
--- a/sbin/isakmpd/connection.c
+++ b/sbin/isakmpd/connection.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: connection.c,v 1.1 1999/05/02 05:52:48 niklas Exp $ */
-/* $EOM: connection.c,v 1.1 1999/05/01 20:21:09 niklas Exp $ */
+/* $OpenBSD: connection.c,v 1.2 1999/06/02 06:31:37 niklas Exp $ */
+/* $EOM: connection.c,v 1.14 1999/06/01 18:28:44 ho Exp $ */
/*
* Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
@@ -43,8 +43,14 @@
#include "conf.h"
#include "connection.h"
+#include "ipsec.h"
+
+/* XXX isakmp.h only required for compare_ids() and decode_ids(). */
+#include "isakmp.h"
+
#include "log.h"
#include "timer.h"
+#include "util.h"
/* How often should we check that connections we require to be up, are up? */
#define CHECK_INTERVAL 60
@@ -56,7 +62,23 @@ struct connection
struct event *ev;
};
+struct connection_passive
+{
+ TAILQ_ENTRY (connection_passive) link;
+ char *name;
+ u_int8_t *local_id, *remote_id;
+ size_t local_sz, remote_sz;
+
+#if 0
+ /* XXX Potential additions to 'connection_passive'. */
+ char *isakmp_peer;
+ struct sa *sa; /* XXX "Soft" ref to active sa? */
+ struct timeval sa_expiration; /* XXX *sa may expire. */
+#endif
+};
+
TAILQ_HEAD (connection_head, connection) connections;
+TAILQ_HEAD (passive_head, connection_passive) connections_passive;
/*
* This is where we setup all the connections we want there right from the
@@ -65,10 +87,18 @@ TAILQ_HEAD (connection_head, connection) connections;
void
connection_init ()
{
- struct conf_list *conns;
- struct conf_list_node *conn;
+ struct conf_list *conns, *attrs;
+ struct conf_list_node *conn, *attr;
+
+ /*
+ * Passive connections normally include: all "active" connections that
+ * are not flagged "Active-Only", plus all connections listed in
+ * the 'Passive-Connections' list.
+ */
TAILQ_INIT (&connections);
+ TAILQ_INIT (&connections_passive);
+
conns = conf_get_list ("Phase 2", "Connections");
if (conns)
{
@@ -77,10 +107,41 @@ connection_init ()
{
if (connection_setup (conn->field))
log_print ("connection_init: could not setup \"%s\"", conn->field);
- continue;
+
+ /* XXX Break/abort here if connection_setup failed? */
+
+ /*
+ * XXX This code (i.e. the attribute lookup) seems like a
+ * likely candidate for factoring out into a function of its
+ * own.
+ */
+ attrs = conf_get_list (conn->field, "Flags");
+ if (attrs)
+ for (attr = TAILQ_FIRST (&attrs->fields); attr;
+ attr = TAILQ_NEXT (attr, link))
+ if (strcasecmp ("active-only", attr->field) == 0)
+ break;
+ if (!attrs || (attrs && !attr))
+ if (connection_record_passive (conn->field))
+ log_print ("connection_init: could not record "
+ "connection \"%s\"", conn->field);
+ if (attrs)
+ conf_free_list (attrs);
+
}
conf_free_list (conns);
}
+
+ conns = conf_get_list ("Phase 2", "Passive-Connections");
+ if (conns)
+ {
+ for (conn = TAILQ_FIRST (&conns->fields); conn;
+ conn = TAILQ_NEXT (conn, link))
+ if (connection_record_passive (conn->field))
+ log_print ("connection_init: could not record passive "
+ "connection \"%s\"", conn->field);
+ conf_free_list (conns);
+ }
}
/* Check the connection in VCONN and schedule another check later. */
@@ -111,6 +172,66 @@ connection_lookup (char *name)
return 0;
}
+/* Find the passive connection named NAME. */
+static struct connection_passive *
+connection_passive_lookup_by_name (char *name)
+{
+ struct connection_passive *conn;
+
+ for (conn = TAILQ_FIRST (&connections_passive); conn;
+ conn = TAILQ_NEXT (conn, link))
+ if (strcasecmp (conn->name, name) == 0)
+ return conn;
+ return 0;
+}
+
+/*
+ * IDs of different types cannot be the same.
+ * XXX Rename to ipsec_compare_id, and move to ipsec.c ?
+ */
+static int
+compare_ids (u_int8_t *id1, u_int8_t *id2, size_t idlen)
+{
+ int id1_type, id2_type;
+
+ id1_type = GET_ISAKMP_ID_TYPE (id1);
+ id2_type = GET_ISAKMP_ID_TYPE (id2);
+
+ return id1_type == id2_type ?
+ memcmp (id1 + ISAKMP_ID_DATA_OFF,
+ id2 + ISAKMP_ID_DATA_OFF,
+ idlen - ISAKMP_ID_DATA_OFF) : -1;
+}
+
+/* Find the connection named with matching IDs. */
+char *
+connection_passive_lookup_by_ids (u_int8_t *id1, u_int8_t *id2)
+{
+ struct connection_passive *conn;
+
+ for (conn = TAILQ_FIRST (&connections_passive); conn;
+ conn = TAILQ_NEXT (conn, link))
+ {
+ /*
+ * If both IDs match what we have saved, return the name. Don't bother
+ * in which order they are.
+ */
+ if ((compare_ids (id1, conn->local_id, conn->local_sz) == 0 &&
+ compare_ids (id2, conn->remote_id, conn->remote_sz) == 0) ||
+ (compare_ids (id1, conn->remote_id, conn->remote_sz) == 0 &&
+ compare_ids (id2, conn->local_id, conn->local_sz) == 0))
+ {
+ log_debug (LOG_MISC, 60,
+ "connection_passive_lookup_by_ids: returned \"%s\"",
+ conn->name);
+ return conn->name;
+ }
+ }
+ log_debug (LOG_MISC, 60,
+ "connection_passive_lookup_by_ids: no match");
+ return 0;
+}
+
/*
* Setup NAME to be a connection that should be up "always", i.e. if it dies,
* for whatever reason, it should be tried to be brought up, over and over
@@ -166,6 +287,70 @@ connection_setup (char *name)
return -1;
}
+int
+connection_record_passive (char *name)
+{
+ struct connection_passive *conn;
+ char *local_id, *remote_id;
+
+ if (connection_passive_lookup_by_name (name))
+ {
+ log_debug (LOG_MISC, 10,
+ "connection_record_passive: cannot add \"%s\" twice",
+ name);
+ return 0;
+ }
+
+ local_id = conf_get_str (name, "Local-ID");
+ remote_id = conf_get_str (name, "Remote-ID");
+ if (!local_id || !remote_id)
+ {
+ log_print ("connection_record_passive: "
+ "\"Local-ID\" or \"Remote-ID\" is missing from section [%s]",
+ name);
+ return -1;
+ }
+
+ conn = calloc (1, sizeof *conn);
+ if (!conn)
+ {
+ log_error ("connection_record_passive: calloc (1, %d) failed",
+ sizeof *conn);
+ return -1;
+ }
+
+ conn->name = strdup (name);
+ if (!conn->name)
+ {
+ log_error ("connection_record_passive: strdup (\"%s\") failed", name);
+ goto fail;
+ }
+
+ /* XXX IPSec DOI-specific. */
+ conn->local_id = ipsec_build_id (local_id, &conn->local_sz);
+ if (!conn->local_id)
+ goto fail;
+
+ conn->remote_id = ipsec_build_id (remote_id, &conn->remote_sz);
+ if (!conn->remote_id)
+ goto fail;
+
+ TAILQ_INSERT_TAIL (&connections_passive, conn, link);
+
+ log_debug (LOG_MISC, 60,
+ "connection_record_passive: passive connection \"%s\" "
+ "added", conn->name);
+ return 0;
+
+ fail:
+ if (conn->local_id)
+ free (conn->local_id);
+ if (conn->name)
+ free (conn->name);
+ free (conn);
+ return -1;
+}
+
/* Remove the connection named NAME. */
void
connection_teardown (char *name)
@@ -181,3 +366,113 @@ connection_teardown (char *name)
free (conn->name);
free (conn);
}
+
+/* Remove the passive connection named NAME. */
+void
+connection_passive_teardown (char *name)
+{
+ struct connection_passive *conn;
+
+ conn = connection_passive_lookup_by_name (name);
+ if (!conn)
+ return;
+
+ TAILQ_REMOVE (&connections_passive, conn, link);
+ free (conn->name);
+ free (conn->local_id);
+ free (conn->remote_id);
+ free (conn);
+}
+
+/*
+ * XXX Perhaps move this outside connection.c (ipsec.c?)
+ * Perhaps rewrite without the duplicated code.
+ */
+static char *
+decode_ids (char *fmt, u_int8_t *id1, u_int8_t *id2)
+{
+ int id_type;
+ static char result[1024];
+ char s_id1[256], s_id2[256];
+
+ id_type = GET_ISAKMP_ID_TYPE (id1);
+ switch (id_type)
+ {
+ case IPSEC_ID_IPV4_ADDR:
+ snprintf (s_id1, 256, "%08x", decode_32 (id1 + ISAKMP_ID_DATA_OFF));
+ break;
+ case IPSEC_ID_IPV4_ADDR_SUBNET:
+ snprintf (s_id1, 256, "%08x", decode_32 (id1 + ISAKMP_ID_DATA_OFF));
+ snprintf (s_id1 + strlen(s_id1), 256, "/%08x",
+ decode_32 (id1 + ISAKMP_ID_DATA_OFF + 4));
+ break;
+ /* XXX - IPV6 et al */
+ default:
+ strcpy (s_id1, "<notype>");
+ break;
+ }
+
+ id_type = GET_ISAKMP_ID_TYPE (id2);
+ switch (id_type)
+ {
+ case IPSEC_ID_IPV4_ADDR:
+ snprintf (s_id2, 256, "%08x", decode_32 (id2 + ISAKMP_ID_DATA_OFF));
+ break;
+ case IPSEC_ID_IPV4_ADDR_SUBNET:
+ snprintf (s_id2, 256, "%08x", decode_32 (id2 + ISAKMP_ID_DATA_OFF));
+ snprintf (s_id2 + strlen(s_id2), 256, "/%08x",
+ decode_32 (id2 + ISAKMP_ID_DATA_OFF + 4));
+ break;
+ /* XXX - IPV6 et al */
+ default:
+ strcpy (s_id2, "<notype>");
+ break;
+ }
+
+ snprintf (result, 1024, fmt, s_id1, s_id2);
+ return result;
+}
+
+void
+connection_report (void)
+{
+ struct connection *conn;
+ struct connection_passive *pconn;
+ struct timeval now;
+
+ gettimeofday (&now, 0);
+ for (conn = TAILQ_FIRST (&connections); conn; conn = TAILQ_NEXT (conn, link))
+ log_debug (LOG_REPORT, 0,
+ "connection_report: connection %s next check %ld seconds",
+ (conn->name ? conn->name : "<unnamed>"),
+ (long)conn->ev - now.tv_sec);
+ for (pconn = TAILQ_FIRST (&connections_passive); pconn;
+ pconn = TAILQ_NEXT (pconn, link))
+ log_debug (LOG_REPORT, 0,
+ "connection_report: passive connection %s %s", pconn->name,
+ decode_ids ("local_id %s remote_id %s", pconn->local_id,
+ pconn->remote_id));
+}
+
+/* Reinit all connections (SIGHUP handling). */
+void
+connection_reinit (void)
+{
+ struct connection *conn;
+ struct connection_passive *pconn;
+
+ log_debug (LOG_MISC, 30,
+ "connection_reinit: reinitializing connection list");
+
+ /* Remove all present connections. */
+
+ for (conn = TAILQ_FIRST (&connections); conn; conn = TAILQ_NEXT (conn, link))
+ connection_teardown (conn->name);
+
+ for (pconn = TAILQ_FIRST (&connections_passive); pconn;
+ pconn = TAILQ_NEXT (pconn, link))
+ connection_passive_teardown (pconn->name);
+
+ /* Setup new connections, as the (new) config directs. */
+ connection_init ();
+}