xref: /openbsd-src/sbin/isakmpd/connection.c (revision 2f1aa25b0f696ec888d7fe80b22e760eed552d21)
1*2f1aa25bSmpi /* $OpenBSD: connection.c,v 1.41 2018/01/15 09:54:48 mpi Exp $	 */
240f7ee3dSniklas /* $EOM: connection.c,v 1.28 2000/11/23 12:21:18 niklas Exp $	 */
35ddb0317Sniklas 
45ddb0317Sniklas /*
542af7185Sniklas  * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist.  All rights reserved.
622d612abSniklas  * Copyright (c) 1999 Hakan Olsson.  All rights reserved.
75ddb0317Sniklas  *
85ddb0317Sniklas  * Redistribution and use in source and binary forms, with or without
95ddb0317Sniklas  * modification, are permitted provided that the following conditions
105ddb0317Sniklas  * are met:
115ddb0317Sniklas  * 1. Redistributions of source code must retain the above copyright
125ddb0317Sniklas  *    notice, this list of conditions and the following disclaimer.
135ddb0317Sniklas  * 2. Redistributions in binary form must reproduce the above copyright
145ddb0317Sniklas  *    notice, this list of conditions and the following disclaimer in the
155ddb0317Sniklas  *    documentation and/or other materials provided with the distribution.
165ddb0317Sniklas  *
175ddb0317Sniklas  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
185ddb0317Sniklas  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
195ddb0317Sniklas  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
205ddb0317Sniklas  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
215ddb0317Sniklas  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
225ddb0317Sniklas  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235ddb0317Sniklas  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245ddb0317Sniklas  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255ddb0317Sniklas  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
265ddb0317Sniklas  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275ddb0317Sniklas  */
285ddb0317Sniklas 
295ddb0317Sniklas /*
305ddb0317Sniklas  * This code was written under funding by Ericsson Radio Systems.
315ddb0317Sniklas  */
325ddb0317Sniklas 
335ddb0317Sniklas #include <sys/queue.h>
34f6511159Sniklas #include <sys/socket.h>
355ddb0317Sniklas #include <stdlib.h>
365ddb0317Sniklas #include <string.h>
375ddb0317Sniklas 
385ddb0317Sniklas #include "conf.h"
395ddb0317Sniklas #include "connection.h"
40454877a4Sniklas #include "doi.h"
41937dccddSniklas #include "ipsec.h"
423a722197Shshoexer #include "pf_key_v2.h"
43937dccddSniklas 
44454877a4Sniklas /* XXX isakmp.h only required for compare_ids().  */
45937dccddSniklas #include "isakmp.h"
46937dccddSniklas 
475ddb0317Sniklas #include "log.h"
485ddb0317Sniklas #include "timer.h"
4914f1d06aSmpf #include "ui.h"
50937dccddSniklas #include "util.h"
515ddb0317Sniklas 
525ddb0317Sniklas /* How often should we check that connections we require to be up, are up?  */
535ddb0317Sniklas #define CHECK_INTERVAL 60
545ddb0317Sniklas 
554c8c122bSho static void     connection_passive_teardown(char *);
564c8c122bSho 
57fb9475d6Sderaadt struct connection {
585ddb0317Sniklas 	TAILQ_ENTRY(connection) link;
595ddb0317Sniklas 	char           *name;
605ddb0317Sniklas 	struct event   *ev;
615ddb0317Sniklas };
625ddb0317Sniklas 
63fb9475d6Sderaadt struct connection_passive {
64937dccddSniklas 	TAILQ_ENTRY(connection_passive) link;
65937dccddSniklas 	char           *name;
66937dccddSniklas 	u_int8_t       *local_id, *remote_id;
67937dccddSniklas 	size_t          local_sz, remote_sz;
68937dccddSniklas 
69937dccddSniklas #if 0
70937dccddSniklas 	/* XXX Potential additions to 'connection_passive'.  */
71937dccddSniklas 	char           *isakmp_peer;
72937dccddSniklas 	struct sa      *sa;	/* XXX "Soft" ref to active sa?  */
736ee513e5Sjca 	struct timespec sa_expiration;	/* XXX *sa may expire.  */
74937dccddSniklas #endif
75937dccddSniklas };
76937dccddSniklas 
775ddb0317Sniklas TAILQ_HEAD(connection_head, connection) connections;
78937dccddSniklas TAILQ_HEAD(passive_head, connection_passive) connections_passive;
795ddb0317Sniklas 
805ddb0317Sniklas /*
815ddb0317Sniklas  * This is where we setup all the connections we want there right from the
825ddb0317Sniklas  * start.
835ddb0317Sniklas  */
845ddb0317Sniklas void
connection_init(void)8530c1e3c7Sho connection_init(void)
865ddb0317Sniklas {
87937dccddSniklas 	struct conf_list *conns, *attrs;
881cda6f75Sderaadt 	struct conf_list_node *conn, *attr = NULL;
89937dccddSniklas 
90937dccddSniklas 	/*
91937dccddSniklas 	 * Passive connections normally include: all "active" connections that
92937dccddSniklas 	 * are not flagged "Active-Only", plus all connections listed in
93937dccddSniklas 	 * the 'Passive-Connections' list.
94937dccddSniklas 	 */
955ddb0317Sniklas 	TAILQ_INIT(&connections);
96937dccddSniklas 	TAILQ_INIT(&connections_passive);
97937dccddSniklas 
985ddb0317Sniklas 	conns = conf_get_list("Phase 2", "Connections");
99fb9475d6Sderaadt 	if (conns) {
1005ddb0317Sniklas 		for (conn = TAILQ_FIRST(&conns->fields); conn;
101fb9475d6Sderaadt 		    conn = TAILQ_NEXT(conn, link)) {
1025ddb0317Sniklas 			if (connection_setup(conn->field))
103df915834Shshoexer 				log_print("connection_init: could not setup "
104df915834Shshoexer 				    "\"%s\"", conn->field);
105937dccddSniklas 
106937dccddSniklas 			/* XXX Break/abort here if connection_setup failed?  */
107937dccddSniklas 
108937dccddSniklas 			/*
109df915834Shshoexer 			 * XXX This code (i.e. the attribute lookup) seems
110df915834Shshoexer 			 * like a likely candidate for factoring out into a
111df915834Shshoexer 			 * function of its own.
112937dccddSniklas 			 */
113937dccddSniklas 			attrs = conf_get_list(conn->field, "Flags");
114937dccddSniklas 			if (attrs)
115937dccddSniklas 				for (attr = TAILQ_FIRST(&attrs->fields); attr;
116937dccddSniklas 				    attr = TAILQ_NEXT(attr, link))
117df915834Shshoexer 					if (strcasecmp("active-only",
118df915834Shshoexer 					    attr->field) == 0)
119937dccddSniklas 						break;
120937dccddSniklas 			if (!attrs || (attrs && !attr))
121937dccddSniklas 				if (connection_record_passive(conn->field))
122df915834Shshoexer 					log_print("connection_init: could not "
123df915834Shshoexer 					    "record connection \"%s\"",
124df915834Shshoexer 					    conn->field);
125937dccddSniklas 			if (attrs)
126937dccddSniklas 				conf_free_list(attrs);
127937dccddSniklas 
1285ddb0317Sniklas 		}
1295ddb0317Sniklas 		conf_free_list(conns);
1305ddb0317Sniklas 	}
131937dccddSniklas 	conns = conf_get_list("Phase 2", "Passive-Connections");
132fb9475d6Sderaadt 	if (conns) {
133937dccddSniklas 		for (conn = TAILQ_FIRST(&conns->fields); conn;
134937dccddSniklas 		    conn = TAILQ_NEXT(conn, link))
135937dccddSniklas 			if (connection_record_passive(conn->field))
136df915834Shshoexer 				log_print("connection_init: could not record "
137df915834Shshoexer 				    "passive connection \"%s\"", conn->field);
138937dccddSniklas 		conf_free_list(conns);
139937dccddSniklas 	}
1405ddb0317Sniklas }
1415ddb0317Sniklas 
1425ddb0317Sniklas /* Check the connection in VCONN and schedule another check later.  */
1435ddb0317Sniklas static void
connection_checker(void * vconn)1445ddb0317Sniklas connection_checker(void *vconn)
1455ddb0317Sniklas {
1466ee513e5Sjca 	struct timespec  now;
1475ddb0317Sniklas 	struct connection *conn = vconn;
1488fe2399aSmpi 	char *name;
1495ddb0317Sniklas 
1506ee513e5Sjca 	clock_gettime(CLOCK_MONOTONIC, &now);
15150eea14cSho 	now.tv_sec += conf_get_num("General", "check-interval",
15250eea14cSho 	    CHECK_INTERVAL);
153fb9475d6Sderaadt 	conn->ev = timer_add_event("connection_checker",
154fb9475d6Sderaadt 	    connection_checker, conn, &now);
1555ddb0317Sniklas 	if (!conn->ev)
1568fe2399aSmpi 		log_print("%s: could not add timer event", __func__);
1578fe2399aSmpi 	if (ui_daemon_passive)
1588fe2399aSmpi 		return;
1598fe2399aSmpi 
1608fe2399aSmpi 	name = strdup(conn->name);
1618fe2399aSmpi 	if (!name) {
1628fe2399aSmpi 		log_print("%s: strdup (\"%s\") failed", __func__, conn->name);
1638fe2399aSmpi 		return;
1648fe2399aSmpi 	}
1658fe2399aSmpi 	pf_key_v2_connection_check(name);
1665ddb0317Sniklas }
1675ddb0317Sniklas 
1685ddb0317Sniklas /* Find the connection named NAME.  */
1695ddb0317Sniklas static struct connection *
connection_lookup(char * name)1705ddb0317Sniklas connection_lookup(char *name)
1715ddb0317Sniklas {
1725ddb0317Sniklas 	struct connection *conn;
1735ddb0317Sniklas 
174df915834Shshoexer 	for (conn = TAILQ_FIRST(&connections); conn;
175df915834Shshoexer 	    conn = TAILQ_NEXT(conn, link))
1765ddb0317Sniklas 		if (strcasecmp(conn->name, name) == 0)
1775ddb0317Sniklas 			return conn;
1785ddb0317Sniklas 	return 0;
1795ddb0317Sniklas }
1805ddb0317Sniklas 
18122d612abSniklas /* Does the connection named NAME exist?  */
18222d612abSniklas int
connection_exist(char * name)18322d612abSniklas connection_exist(char *name)
18422d612abSniklas {
1850eb823c5Sniklas 	return (connection_lookup(name) != 0);
18622d612abSniklas }
18722d612abSniklas 
188937dccddSniklas /* Find the passive connection named NAME.  */
189937dccddSniklas static struct connection_passive *
connection_passive_lookup_by_name(char * name)190937dccddSniklas connection_passive_lookup_by_name(char *name)
191937dccddSniklas {
192937dccddSniklas 	struct connection_passive *conn;
193937dccddSniklas 
194937dccddSniklas 	for (conn = TAILQ_FIRST(&connections_passive); conn;
195937dccddSniklas 	    conn = TAILQ_NEXT(conn, link))
196937dccddSniklas 		if (strcasecmp(conn->name, name) == 0)
197937dccddSniklas 			return conn;
198937dccddSniklas 	return 0;
199937dccddSniklas }
200937dccddSniklas 
201937dccddSniklas /*
202937dccddSniklas  * IDs of different types cannot be the same.
203937dccddSniklas  * XXX Rename to ipsec_compare_id, and move to ipsec.c ?
204937dccddSniklas  */
205937dccddSniklas static int
compare_ids(u_int8_t * id1,u_int8_t * id2,size_t idlen)206937dccddSniklas compare_ids(u_int8_t *id1, u_int8_t *id2, size_t idlen)
207937dccddSniklas {
208937dccddSniklas 	int	id1_type, id2_type;
209937dccddSniklas 
210937dccddSniklas 	id1_type = GET_ISAKMP_ID_TYPE(id1);
211937dccddSniklas 	id2_type = GET_ISAKMP_ID_TYPE(id2);
212937dccddSniklas 
213fb9475d6Sderaadt 	return id1_type == id2_type ? memcmp(id1 + ISAKMP_ID_DATA_OFF,
214fb9475d6Sderaadt 	    id2 + ISAKMP_ID_DATA_OFF, idlen - ISAKMP_ID_DATA_OFF) : -1;
215937dccddSniklas }
216937dccddSniklas 
217937dccddSniklas /* Find the connection named with matching IDs.  */
218937dccddSniklas char *
connection_passive_lookup_by_ids(u_int8_t * id1,u_int8_t * id2)219937dccddSniklas connection_passive_lookup_by_ids(u_int8_t *id1, u_int8_t *id2)
220937dccddSniklas {
221937dccddSniklas 	struct connection_passive *conn;
222937dccddSniklas 
223937dccddSniklas 	for (conn = TAILQ_FIRST(&connections_passive); conn;
224fb9475d6Sderaadt 	    conn = TAILQ_NEXT(conn, link)) {
2250eb823c5Sniklas 		if (!conn->remote_id)
226e21c3de4Sniklas 			continue;
227e21c3de4Sniklas 
228937dccddSniklas 		/*
229df915834Shshoexer 		 * If both IDs match what we have saved, return the name.
230df915834Shshoexer 		 * Don't bother in which order they are.
231937dccddSniklas 		 */
232fb9475d6Sderaadt 		if ((compare_ids(id1, conn->local_id, conn->local_sz) == 0 &&
233fb9475d6Sderaadt 		    compare_ids(id2, conn->remote_id, conn->remote_sz) == 0) ||
234fb9475d6Sderaadt 		    (compare_ids(id1, conn->remote_id, conn->remote_sz) == 0 &&
235fb9475d6Sderaadt 		    compare_ids(id2, conn->local_id, conn->local_sz) == 0)) {
23651ca15aeSniklas 			LOG_DBG((LOG_MISC, 60,
23750eea14cSho 			    "connection_passive_lookup_by_ids: "
23850eea14cSho 			    "returned \"%s\"", conn->name));
239937dccddSniklas 			return conn->name;
240937dccddSniklas 		}
241937dccddSniklas 	}
242e21c3de4Sniklas 
243fb9475d6Sderaadt 	/*
244fb9475d6Sderaadt 	 * In the road warrior case, we do not know the remote ID. In that
245e21c3de4Sniklas 	 * case we will just match against the local ID.
246e21c3de4Sniklas 	 */
247e21c3de4Sniklas 	for (conn = TAILQ_FIRST(&connections_passive); conn;
248fb9475d6Sderaadt 	    conn = TAILQ_NEXT(conn, link)) {
2490eb823c5Sniklas 		if (!conn->remote_id)
250e21c3de4Sniklas 			continue;
251e21c3de4Sniklas 
252fb9475d6Sderaadt 		if (compare_ids(id1, conn->local_id, conn->local_sz) == 0 ||
253fb9475d6Sderaadt 		    compare_ids(id2, conn->local_id, conn->local_sz) == 0) {
254e21c3de4Sniklas 			LOG_DBG((LOG_MISC, 60,
255e46ba839Shshoexer 			    "connection_passive_lookup_by_ids: returned \"%s\""
256e21c3de4Sniklas 			    " only matched local id", conn->name));
257e21c3de4Sniklas 			return conn->name;
258e21c3de4Sniklas 		}
259e21c3de4Sniklas 	}
26051ca15aeSniklas 	LOG_DBG((LOG_MISC, 60,
26151ca15aeSniklas 	    "connection_passive_lookup_by_ids: no match"));
262937dccddSniklas 	return 0;
263937dccddSniklas }
264937dccddSniklas 
2655ddb0317Sniklas /*
2665ddb0317Sniklas  * Setup NAME to be a connection that should be up "always", i.e. if it dies,
2675ddb0317Sniklas  * for whatever reason, it should be tried to be brought up, over and over
2685ddb0317Sniklas  * again.
2695ddb0317Sniklas  */
2705ddb0317Sniklas int
connection_setup(char * name)2715ddb0317Sniklas connection_setup(char *name)
2725ddb0317Sniklas {
2735ddb0317Sniklas 	struct connection *conn = 0;
2746ee513e5Sjca 	struct timespec  now;
2755ddb0317Sniklas 
2765ddb0317Sniklas 	/* Check for trials to add duplicate connections.  */
277fb9475d6Sderaadt 	if (connection_lookup(name)) {
278d2a2baa1Sho 		LOG_DBG((LOG_MISC, 10,
279d2a2baa1Sho 		    "connection_setup: cannot add \"%s\" twice", name));
2805ddb0317Sniklas 		return 0;
2815ddb0317Sniklas 	}
2825ddb0317Sniklas 	conn = calloc(1, sizeof *conn);
283fb9475d6Sderaadt 	if (!conn) {
2840cd3ca40Sho 		log_error("connection_setup: calloc (1, %lu) failed",
2850cd3ca40Sho 		    (unsigned long)sizeof *conn);
2865ddb0317Sniklas 		goto fail;
2875ddb0317Sniklas 	}
2885ddb0317Sniklas 	conn->name = strdup(name);
289fb9475d6Sderaadt 	if (!conn->name) {
2905ddb0317Sniklas 		log_error("connection_setup: strdup (\"%s\") failed", name);
2915ddb0317Sniklas 		goto fail;
2925ddb0317Sniklas 	}
2936ee513e5Sjca 	clock_gettime(CLOCK_MONOTONIC, &now);
294df915834Shshoexer 	conn->ev = timer_add_event("connection_checker", connection_checker,
295df915834Shshoexer 	    conn, &now);
296fb9475d6Sderaadt 	if (!conn->ev) {
2975ddb0317Sniklas 		log_print("connection_setup: could not add timer event");
2985ddb0317Sniklas 		goto fail;
2995ddb0317Sniklas 	}
3005ddb0317Sniklas 	TAILQ_INSERT_TAIL(&connections, conn, link);
3015ddb0317Sniklas 	return 0;
3025ddb0317Sniklas 
3035ddb0317Sniklas fail:
304fb9475d6Sderaadt 	if (conn) {
3055ddb0317Sniklas 		free(conn->name);
3065ddb0317Sniklas 		free(conn);
3075ddb0317Sniklas 	}
3085ddb0317Sniklas 	return -1;
3095ddb0317Sniklas }
3105ddb0317Sniklas 
311937dccddSniklas int
connection_record_passive(char * name)312937dccddSniklas connection_record_passive(char *name)
313937dccddSniklas {
314937dccddSniklas 	struct connection_passive *conn;
315937dccddSniklas 	char           *local_id, *remote_id;
316937dccddSniklas 
317fb9475d6Sderaadt 	if (connection_passive_lookup_by_name(name)) {
31851ca15aeSniklas 		LOG_DBG((LOG_MISC, 10,
319937dccddSniklas 		    "connection_record_passive: cannot add \"%s\" twice",
32051ca15aeSniklas 		    name));
321937dccddSniklas 		return 0;
322937dccddSniklas 	}
323937dccddSniklas 	local_id = conf_get_str(name, "Local-ID");
324fb9475d6Sderaadt 	if (!local_id) {
325937dccddSniklas 		log_print("connection_record_passive: "
326fb9475d6Sderaadt 		    "\"Local-ID\" is missing from section [%s]", name);
327937dccddSniklas 		return -1;
328937dccddSniklas 	}
329e21c3de4Sniklas 	/* If the remote id lookup fails we defer it to later */
330e21c3de4Sniklas 	remote_id = conf_get_str(name, "Remote-ID");
331e21c3de4Sniklas 
332937dccddSniklas 	conn = calloc(1, sizeof *conn);
333fb9475d6Sderaadt 	if (!conn) {
3347eb3b581Sderaadt 		log_error("connection_record_passive: calloc (1, %lu) failed",
3357eb3b581Sderaadt 		    (unsigned long)sizeof *conn);
336937dccddSniklas 		return -1;
337937dccddSniklas 	}
338937dccddSniklas 	conn->name = strdup(name);
339fb9475d6Sderaadt 	if (!conn->name) {
340d2a2baa1Sho 		log_error("connection_record_passive: strdup (\"%s\") failed",
341d2a2baa1Sho 		    name);
342937dccddSniklas 		goto fail;
343937dccddSniklas 	}
34461d575f0Sangelos 	/* XXX IPsec DOI-specific.  */
345937dccddSniklas 	conn->local_id = ipsec_build_id(local_id, &conn->local_sz);
346937dccddSniklas 	if (!conn->local_id)
347937dccddSniklas 		goto fail;
348937dccddSniklas 
349fb9475d6Sderaadt 	if (remote_id) {
350937dccddSniklas 		conn->remote_id = ipsec_build_id(remote_id, &conn->remote_sz);
351937dccddSniklas 		if (!conn->remote_id)
352937dccddSniklas 			goto fail;
353fb9475d6Sderaadt 	} else
3540eb823c5Sniklas 		conn->remote_id = 0;
355937dccddSniklas 
356937dccddSniklas 	TAILQ_INSERT_TAIL(&connections_passive, conn, link);
357937dccddSniklas 
35851ca15aeSniklas 	LOG_DBG((LOG_MISC, 60,
359fb9475d6Sderaadt 	    "connection_record_passive: passive connection \"%s\" added",
360fb9475d6Sderaadt 	    conn->name));
361937dccddSniklas 	return 0;
362937dccddSniklas 
363937dccddSniklas fail:
364937dccddSniklas 	free(conn->local_id);
365937dccddSniklas 	free(conn->name);
366937dccddSniklas 	free(conn);
367937dccddSniklas 	return -1;
368937dccddSniklas }
369937dccddSniklas 
3705ddb0317Sniklas /* Remove the connection named NAME.  */
3715ddb0317Sniklas void
connection_teardown(char * name)3725ddb0317Sniklas connection_teardown(char *name)
3735ddb0317Sniklas {
3745ddb0317Sniklas 	struct connection *conn;
3755ddb0317Sniklas 
3765ddb0317Sniklas 	conn = connection_lookup(name);
3775ddb0317Sniklas 	if (!conn)
3785ddb0317Sniklas 		return;
3795ddb0317Sniklas 
3805ddb0317Sniklas 	TAILQ_REMOVE(&connections, conn, link);
3815ddb0317Sniklas 	timer_remove_event(conn->ev);
3825ddb0317Sniklas 	free(conn->name);
3835ddb0317Sniklas 	free(conn);
3845ddb0317Sniklas }
385937dccddSniklas 
386937dccddSniklas /* Remove the passive connection named NAME.  */
3874c8c122bSho static void
connection_passive_teardown(char * name)388937dccddSniklas connection_passive_teardown(char *name)
389937dccddSniklas {
390937dccddSniklas 	struct connection_passive *conn;
391937dccddSniklas 
392937dccddSniklas 	conn = connection_passive_lookup_by_name(name);
393937dccddSniklas 	if (!conn)
394937dccddSniklas 		return;
395937dccddSniklas 
396937dccddSniklas 	TAILQ_REMOVE(&connections_passive, conn, link);
397937dccddSniklas 	free(conn->name);
398937dccddSniklas 	free(conn->local_id);
399937dccddSniklas 	free(conn->remote_id);
400937dccddSniklas 	free(conn);
401937dccddSniklas }
402937dccddSniklas 
403937dccddSniklas void
connection_report(void)404937dccddSniklas connection_report(void)
405937dccddSniklas {
406937dccddSniklas 	struct connection *conn;
4076ee513e5Sjca 	struct timespec  now;
408f6511159Sniklas 	struct connection_passive *pconn;
409454877a4Sniklas 	struct doi     *doi = doi_lookup(ISAKMP_DOI_ISAKMP);
410937dccddSniklas 
4116ee513e5Sjca 	clock_gettime(CLOCK_MONOTONIC, &now);
412d2a2baa1Sho 	for (conn = TAILQ_FIRST(&connections); conn;
413d2a2baa1Sho 	    conn = TAILQ_NEXT(conn, link))
41451ca15aeSniklas 		LOG_DBG((LOG_REPORT, 0,
4151c04898dSguenther 		    "connection_report: connection %s next check %lld seconds",
416937dccddSniklas 		    (conn->name ? conn->name : "<unnamed>"),
4171c04898dSguenther 		    (long long)(conn->ev->expiration.tv_sec - now.tv_sec)));
418937dccddSniklas 	for (pconn = TAILQ_FIRST(&connections_passive); pconn;
419937dccddSniklas 	    pconn = TAILQ_NEXT(pconn, link))
42051ca15aeSniklas 		LOG_DBG((LOG_REPORT, 0,
421937dccddSniklas 		    "connection_report: passive connection %s %s", pconn->name,
422454877a4Sniklas 		    doi->decode_ids("local_id: %s, remote_id: %s",
423454877a4Sniklas 		    pconn->local_id, pconn->local_sz,
424454877a4Sniklas 		    pconn->remote_id, pconn->remote_sz, 1)));
425937dccddSniklas }
426937dccddSniklas 
42705782133Sniklas /* Reinitialize all connections (SIGHUP handling).  */
428937dccddSniklas void
connection_reinit(void)429937dccddSniklas connection_reinit(void)
430937dccddSniklas {
43105782133Sniklas 	struct connection *conn, *next;
43205782133Sniklas 	struct connection_passive *pconn, *pnext;
433937dccddSniklas 
43451ca15aeSniklas 	LOG_DBG((LOG_MISC, 30,
43551ca15aeSniklas 	    "connection_reinit: reinitializing connection list"));
436937dccddSniklas 
437937dccddSniklas 	/* Remove all present connections.  */
438fb9475d6Sderaadt 	for (conn = TAILQ_FIRST(&connections); conn; conn = next) {
439d317b4b1Stholo 		next = TAILQ_NEXT(conn, link);
440937dccddSniklas 		connection_teardown(conn->name);
44105782133Sniklas 	}
442937dccddSniklas 
443fb9475d6Sderaadt 	for (pconn = TAILQ_FIRST(&connections_passive); pconn; pconn = pnext) {
444d317b4b1Stholo 		pnext = TAILQ_NEXT(pconn, link);
445937dccddSniklas 		connection_passive_teardown(pconn->name);
44605782133Sniklas 	}
447937dccddSniklas 
448937dccddSniklas 	/* Setup new connections, as the (new) config directs.  */
449937dccddSniklas 	connection_init();
450937dccddSniklas }
451