summaryrefslogtreecommitdiff
path: root/src/pluto/connections.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/connections.c')
-rw-r--r--src/pluto/connections.c6574
1 files changed, 3288 insertions, 3286 deletions
diff --git a/src/pluto/connections.c b/src/pluto/connections.c
index cd118cb34..4deb722f7 100644
--- a/src/pluto/connections.c
+++ b/src/pluto/connections.c
@@ -10,8 +10,6 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
- *
- * RCSID $Id: connections.c 4924 2009-03-10 21:13:18Z andreas $
*/
#include <string.h>
@@ -25,20 +23,21 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <resolv.h>
-#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
+#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
#include <sys/queue.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
#include "kameipsec.h"
+#include <credentials/keys/private_key.h>
+
#include "constants.h"
#include "defs.h"
#include "id.h"
#include "x509.h"
#include "ca.h"
#include "crl.h"
-#include "pgp.h"
+#include "pgpcert.h"
#include "certs.h"
#include "ac.h"
#include "smartcard.h"
@@ -48,13 +47,13 @@
#include "demux.h"
#include "state.h"
#include "timer.h"
-#include "ipsec_doi.h" /* needs demux.h and state.h */
+#include "ipsec_doi.h" /* needs demux.h and state.h */
#include "server.h"
#include "kernel.h"
#include "log.h"
#include "keys.h"
-#include "adns.h" /* needs <resolv.h> */
-#include "dnskey.h" /* needs keys.h and adns.h */
+#include "adns.h" /* needs <resolv.h> */
+#include "dnskey.h" /* needs keys.h and adns.h */
#include "whack.h"
#include "alg_info.h"
#include "ike_alg.h"
@@ -62,7 +61,7 @@
#include "nat_traversal.h"
#include "virtual.h"
-static void flush_pending_by_connection(struct connection *c); /* forward */
+static void flush_pending_by_connection(struct connection *c); /* forward */
static struct connection *connections = NULL;
@@ -77,14 +76,14 @@ static struct connection *connections = NULL;
*/
struct host_pair {
- struct {
- ip_address addr;
- u_int16_t port; /* host order */
- } me, him;
- bool initial_connection_sent;
- struct connection *connections; /* connections with this pair */
- struct pending *pending; /* awaiting Keying Channel */
- struct host_pair *next;
+ struct {
+ ip_address addr;
+ u_int16_t port; /* host order */
+ } me, him;
+ bool initial_connection_sent;
+ struct connection *connections; /* connections with this pair */
+ struct pending *pending; /* awaiting Keying Channel */
+ struct host_pair *next;
};
static struct host_pair *host_pairs = NULL;
@@ -96,45 +95,45 @@ bool
same_peer_ids(const struct connection *c, const struct connection *d
, const struct id *his_id)
{
- return same_id(&c->spd.this.id, &d->spd.this.id)
- && same_id(his_id == NULL? &c->spd.that.id : his_id, &d->spd.that.id);
+ return same_id(&c->spd.this.id, &d->spd.this.id)
+ && same_id(his_id == NULL? &c->spd.that.id : his_id, &d->spd.that.id);
}
static struct host_pair *
find_host_pair(const ip_address *myaddr, u_int16_t myport
, const ip_address *hisaddr, u_int16_t hisport)
{
- struct host_pair *p, *prev;
-
- /* default hisaddr to an appropriate any */
- if (hisaddr == NULL)
- hisaddr = aftoinfo(addrtypeof(myaddr))->any;
-
- if (nat_traversal_enabled)
- {
- /**
- * port is not relevant in host_pair. with nat_traversal we
- * always use pluto_port (500)
- */
- myport = pluto_port;
- hisport = pluto_port;
- }
-
- for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next)
- {
- if (sameaddr(&p->me.addr, myaddr) && p->me.port == myport
- && sameaddr(&p->him.addr, hisaddr) && p->him.port == hisport)
+ struct host_pair *p, *prev;
+
+ /* default hisaddr to an appropriate any */
+ if (hisaddr == NULL)
+ hisaddr = aftoinfo(addrtypeof(myaddr))->any;
+
+ if (nat_traversal_enabled)
{
- if (prev != NULL)
- {
- prev->next = p->next; /* remove p from list */
- p->next = host_pairs; /* and stick it on front */
- host_pairs = p;
- }
- break;
+ /**
+ * port is not relevant in host_pair. with nat_traversal we
+ * always use pluto_port (500)
+ */
+ myport = pluto_port;
+ hisport = pluto_port;
}
- }
- return p;
+
+ for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next)
+ {
+ if (sameaddr(&p->me.addr, myaddr) && p->me.port == myport
+ && sameaddr(&p->him.addr, hisaddr) && p->him.port == hisport)
+ {
+ if (prev != NULL)
+ {
+ prev->next = p->next; /* remove p from list */
+ p->next = host_pairs; /* and stick it on front */
+ host_pairs = p;
+ }
+ break;
+ }
+ }
+ return p;
}
/* find head of list of connections with this pair of hosts */
@@ -142,63 +141,63 @@ static struct connection *
find_host_pair_connections(const ip_address *myaddr, u_int16_t myport
, const ip_address *hisaddr, u_int16_t hisport)
{
- struct host_pair *hp = find_host_pair(myaddr, myport, hisaddr, hisport);
-
- if (nat_traversal_enabled && hp && hisaddr)
- {
- struct connection *c;
+ struct host_pair *hp = find_host_pair(myaddr, myport, hisaddr, hisport);
- for (c = hp->connections; c != NULL; c = c->hp_next)
+ if (nat_traversal_enabled && hp && hisaddr)
{
- if (c->spd.this.host_port == myport && c->spd.that.host_port == hisport)
- return c;
+ struct connection *c;
+
+ for (c = hp->connections; c != NULL; c = c->hp_next)
+ {
+ if (c->spd.this.host_port == myport && c->spd.that.host_port == hisport)
+ return c;
+ }
+ return NULL;
}
- return NULL;
- }
- return hp == NULL? NULL : hp->connections;
+ return hp == NULL? NULL : hp->connections;
}
static void
connect_to_host_pair(struct connection *c)
{
- if (oriented(*c))
- {
- struct host_pair *hp;
+ if (oriented(*c))
+ {
+ struct host_pair *hp;
- ip_address his_addr = (c->spd.that.allow_any)
- ? *aftoinfo(addrtypeof(&c->spd.that.host_addr))->any
- : c->spd.that.host_addr;
+ ip_address his_addr = (c->spd.that.allow_any)
+ ? *aftoinfo(addrtypeof(&c->spd.that.host_addr))->any
+ : c->spd.that.host_addr;
- hp = find_host_pair(&c->spd.this.host_addr, c->spd.this.host_port
- , &his_addr, c->spd.that.host_port);
+ hp = find_host_pair(&c->spd.this.host_addr, c->spd.this.host_port
+ , &his_addr, c->spd.that.host_port);
- if (hp == NULL)
+ if (hp == NULL)
+ {
+ /* no suitable host_pair -- build one */
+ hp = malloc_thing(struct host_pair);
+ hp->me.addr = c->spd.this.host_addr;
+ hp->him.addr = his_addr;
+ hp->me.port = nat_traversal_enabled ? pluto_port : c->spd.this.host_port;
+ hp->him.port = nat_traversal_enabled ? pluto_port : c->spd.that.host_port;
+ hp->initial_connection_sent = FALSE;
+ hp->connections = NULL;
+ hp->pending = NULL;
+ hp->next = host_pairs;
+ host_pairs = hp;
+ }
+ c->host_pair = hp;
+ c->hp_next = hp->connections;
+ hp->connections = c;
+ }
+ else
{
- /* no suitable host_pair -- build one */
- hp = alloc_thing(struct host_pair, "host_pair");
- hp->me.addr = c->spd.this.host_addr;
- hp->him.addr = his_addr;
- hp->me.port = nat_traversal_enabled ? pluto_port : c->spd.this.host_port;
- hp->him.port = nat_traversal_enabled ? pluto_port : c->spd.that.host_port;
- hp->initial_connection_sent = FALSE;
- hp->connections = NULL;
- hp->pending = NULL;
- hp->next = host_pairs;
- host_pairs = hp;
+ /* since this connection isn't oriented, we place it
+ * in the unoriented_connections list instead.
+ */
+ c->host_pair = NULL;
+ c->hp_next = unoriented_connections;
+ unoriented_connections = c;
}
- c->host_pair = hp;
- c->hp_next = hp->connections;
- hp->connections = c;
- }
- else
- {
- /* since this connection isn't oriented, we place it
- * in the unoriented_connections list instead.
- */
- c->host_pair = NULL;
- c->hp_next = unoriented_connections;
- unoriented_connections = c;
- }
}
/* find a connection by name.
@@ -209,317 +208,317 @@ connect_to_host_pair(struct connection *c)
struct connection *
con_by_name(const char *nm, bool strict)
{
- struct connection *p, *prev;
+ struct connection *p, *prev;
- for (prev = NULL, p = connections; ; prev = p, p = p->ac_next)
- {
- if (p == NULL)
+ for (prev = NULL, p = connections; ; prev = p, p = p->ac_next)
{
- if (strict)
- whack_log(RC_UNKNOWN_NAME
- , "no connection named \"%s\"", nm);
- break;
- }
- if (streq(p->name, nm)
- && (!strict || p->kind != CK_INSTANCE))
- {
- if (prev != NULL)
- {
- prev->ac_next = p->ac_next; /* remove p from list */
- p->ac_next = connections; /* and stick it on front */
- connections = p;
- }
- break;
+ if (p == NULL)
+ {
+ if (strict)
+ whack_log(RC_UNKNOWN_NAME
+ , "no connection named \"%s\"", nm);
+ break;
+ }
+ if (streq(p->name, nm)
+ && (!strict || p->kind != CK_INSTANCE))
+ {
+ if (prev != NULL)
+ {
+ prev->ac_next = p->ac_next; /* remove p from list */
+ p->ac_next = connections; /* and stick it on front */
+ connections = p;
+ }
+ break;
+ }
}
- }
- return p;
+ return p;
}
void
release_connection(struct connection *c, bool relations)
{
- if (c->kind == CK_INSTANCE)
- {
- /* This does everything we need.
- * Note that we will be called recursively by delete_connection,
- * but kind will be CK_GOING_AWAY.
- */
- delete_connection(c, relations);
- }
- else
- {
- flush_pending_by_connection(c);
- delete_states_by_connection(c, relations);
- unroute_connection(c);
- }
+ if (c->kind == CK_INSTANCE)
+ {
+ /* This does everything we need.
+ * Note that we will be called recursively by delete_connection,
+ * but kind will be CK_GOING_AWAY.
+ */
+ delete_connection(c, relations);
+ }
+ else
+ {
+ flush_pending_by_connection(c);
+ delete_states_by_connection(c, relations);
+ unroute_connection(c);
+ }
}
/* Delete a connection */
#define list_rm(etype, enext, e, ehead) { \
- etype **ep; \
- for (ep = &(ehead); *ep != (e); ep = &(*ep)->enext) \
- passert(*ep != NULL); /* we must not come up empty-handed */ \
- *ep = (e)->enext; \
- }
+ etype **ep; \
+ for (ep = &(ehead); *ep != (e); ep = &(*ep)->enext) \
+ passert(*ep != NULL); /* we must not come up empty-handed */ \
+ *ep = (e)->enext; \
+ }
void
delete_connection(struct connection *c, bool relations)
{
- struct connection *old_cur_connection
- = cur_connection == c? NULL : cur_connection;
+ struct connection *old_cur_connection
+ = cur_connection == c? NULL : cur_connection;
#ifdef DEBUG
- lset_t old_cur_debugging = cur_debugging;
+ lset_t old_cur_debugging = cur_debugging;
#endif
- set_cur_connection(c);
-
- /* Must be careful to avoid circularity:
- * we mark c as going away so it won't get deleted recursively.
- */
- passert(c->kind != CK_GOING_AWAY);
- if (c->kind == CK_INSTANCE)
- {
- plog("deleting connection \"%s\" instance with peer %s {isakmp=#%lu/ipsec=#%lu}"
- , c->name
- , ip_str(&c->spd.that.host_addr)
- , c->newest_isakmp_sa, c->newest_ipsec_sa);
- c->kind = CK_GOING_AWAY;
- }
- else
- {
- plog("deleting connection");
- }
- release_connection(c, relations); /* won't delete c */
-
- if (c->kind == CK_GROUP)
- delete_group(c);
-
- /* free up any logging resources */
- perpeer_logfree(c);
-
- /* find and delete c from connections list */
- list_rm(struct connection, ac_next, c, connections);
- cur_connection = old_cur_connection;
-
- /* find and delete c from the host pair list */
- if (c->host_pair == NULL)
- {
- if (c->ikev1)
- list_rm(struct connection, hp_next, c, unoriented_connections);
- }
- else
- {
- struct host_pair *hp = c->host_pair;
-
- list_rm(struct connection, hp_next, c, hp->connections);
- c->host_pair = NULL; /* redundant, but safe */
-
- /* if there are no more connections with this host_pair
- * and we haven't even made an initial contact, let's delete
- * this guy in case we were created by an attempted DOS attack.
+ set_cur_connection(c);
+
+ /* Must be careful to avoid circularity:
+ * we mark c as going away so it won't get deleted recursively.
*/
- if (hp->connections == NULL
- && !hp->initial_connection_sent)
+ passert(c->kind != CK_GOING_AWAY);
+ if (c->kind == CK_INSTANCE)
+ {
+ plog("deleting connection \"%s\" instance with peer %s {isakmp=#%lu/ipsec=#%lu}"
+ , c->name
+ , ip_str(&c->spd.that.host_addr)
+ , c->newest_isakmp_sa, c->newest_ipsec_sa);
+ c->kind = CK_GOING_AWAY;
+ }
+ else
+ {
+ plog("deleting connection");
+ }
+ release_connection(c, relations); /* won't delete c */
+
+ if (c->kind == CK_GROUP)
+ delete_group(c);
+
+ /* free up any logging resources */
+ perpeer_logfree(c);
+
+ /* find and delete c from connections list */
+ list_rm(struct connection, ac_next, c, connections);
+ cur_connection = old_cur_connection;
+
+ /* find and delete c from the host pair list */
+ if (c->host_pair == NULL)
{
- passert(hp->pending == NULL); /* ??? must deal with this! */
- list_rm(struct host_pair, next, hp, host_pairs);
- pfree(hp);
+ if (c->ikev1)
+ list_rm(struct connection, hp_next, c, unoriented_connections);
}
- }
+ else
+ {
+ struct host_pair *hp = c->host_pair;
- if (c->kind != CK_GOING_AWAY)
- pfreeany(c->spd.that.virt);
+ list_rm(struct connection, hp_next, c, hp->connections);
+ c->host_pair = NULL; /* redundant, but safe */
+ /* if there are no more connections with this host_pair
+ * and we haven't even made an initial contact, let's delete
+ * this guy in case we were created by an attempted DOS attack.
+ */
+ if (hp->connections == NULL
+ && !hp->initial_connection_sent)
+ {
+ passert(hp->pending == NULL); /* ??? must deal with this! */
+ list_rm(struct host_pair, next, hp, host_pairs);
+ free(hp);
+ }
+ }
+ if (c->kind != CK_GOING_AWAY)
+ {
+ free(c->spd.that.virt);
+ }
#ifdef DEBUG
- cur_debugging = old_cur_debugging;
+ cur_debugging = old_cur_debugging;
#endif
- pfreeany(c->name);
- free_id_content(&c->spd.this.id);
- pfreeany(c->spd.this.updown);
- freeanychunk(c->spd.this.ca);
- free_ietfAttrList(c->spd.this.groups);
- free_id_content(&c->spd.that.id);
- pfreeany(c->spd.that.updown);
- freeanychunk(c->spd.that.ca);
- free_ietfAttrList(c->spd.that.groups);
- free_generalNames(c->requested_ca, TRUE);
- gw_delref(&c->gw_info);
-
- lock_certs_and_keys("delete_connection");
- release_cert(c->spd.this.cert);
- scx_release(c->spd.this.sc);
- release_cert(c->spd.that.cert);
- scx_release(c->spd.that.sc);
- unlock_certs_and_keys("delete_connection");
-
- alg_info_delref((struct alg_info **)&c->alg_info_esp);
- alg_info_delref((struct alg_info **)&c->alg_info_ike);
-
- pfree(c);
+ free(c->name);
+ free_id_content(&c->spd.this.id);
+ free(c->spd.this.updown);
+ free(c->spd.this.ca.ptr);
+ free_ietfAttrList(c->spd.this.groups);
+ free_id_content(&c->spd.that.id);
+ free(c->spd.that.updown);
+ free(c->spd.that.ca.ptr);
+ free_ietfAttrList(c->spd.that.groups);
+ free_generalNames(c->requested_ca, TRUE);
+ gw_delref(&c->gw_info);
+
+ lock_certs_and_keys("delete_connection");
+ release_cert(c->spd.this.cert);
+ scx_release(c->spd.this.sc);
+ release_cert(c->spd.that.cert);
+ scx_release(c->spd.that.sc);
+ unlock_certs_and_keys("delete_connection");
+
+ alg_info_delref((struct alg_info **)&c->alg_info_esp);
+ alg_info_delref((struct alg_info **)&c->alg_info_ike);
+
+ free(c);
}
/* Delete connections with the specified name */
void
delete_connections_by_name(const char *name, bool strict)
{
- struct connection *c = con_by_name(name, strict);
+ struct connection *c = con_by_name(name, strict);
- for (; c != NULL; c = con_by_name(name, FALSE))
- delete_connection(c, FALSE);
+ for (; c != NULL; c = con_by_name(name, FALSE))
+ delete_connection(c, FALSE);
}
void
delete_every_connection(void)
{
- while (connections != NULL)
- delete_connection(connections, TRUE);
+ while (connections != NULL)
+ delete_connection(connections, TRUE);
}
void
release_dead_interfaces(void)
{
- struct host_pair *hp;
-
- for (hp = host_pairs; hp != NULL; hp = hp->next)
- {
- struct connection **pp
- , *p;
+ struct host_pair *hp;
- for (pp = &hp->connections; (p = *pp) != NULL; )
+ for (hp = host_pairs; hp != NULL; hp = hp->next)
{
- if (p->interface->change == IFN_DELETE)
- {
- /* this connection's interface is going away */
- enum connection_kind k = p->kind;
-
- release_connection(p, TRUE);
-
- if (k <= CK_PERMANENT)
- {
- /* The connection should have survived release:
- * move it to the unoriented_connections list.
- */
- passert(p == *pp);
-
- p->interface = NULL;
+ struct connection **pp
+ , *p;
- *pp = p->hp_next; /* advance *pp */
- p->host_pair = NULL;
- p->hp_next = unoriented_connections;
- unoriented_connections = p;
- }
- else
+ for (pp = &hp->connections; (p = *pp) != NULL; )
{
- /* The connection should have vanished,
- * but the previous connection remains.
- */
- passert(p != *pp);
+ if (p->interface->change == IFN_DELETE)
+ {
+ /* this connection's interface is going away */
+ enum connection_kind k = p->kind;
+
+ release_connection(p, TRUE);
+
+ if (k <= CK_PERMANENT)
+ {
+ /* The connection should have survived release:
+ * move it to the unoriented_connections list.
+ */
+ passert(p == *pp);
+
+ p->interface = NULL;
+
+ *pp = p->hp_next; /* advance *pp */
+ p->host_pair = NULL;
+ p->hp_next = unoriented_connections;
+ unoriented_connections = p;
+ }
+ else
+ {
+ /* The connection should have vanished,
+ * but the previous connection remains.
+ */
+ passert(p != *pp);
+ }
+ }
+ else
+ {
+ pp = &p->hp_next; /* advance pp */
+ }
}
- }
- else
- {
- pp = &p->hp_next; /* advance pp */
- }
}
- }
}
/* adjust orientations of connections to reflect newly added interfaces */
void
check_orientations(void)
{
- /* try to orient all the unoriented connections */
- {
- struct connection *c = unoriented_connections;
+ /* try to orient all the unoriented connections */
+ {
+ struct connection *c = unoriented_connections;
- unoriented_connections = NULL;
+ unoriented_connections = NULL;
- while (c != NULL)
- {
- struct connection *nxt = c->hp_next;
+ while (c != NULL)
+ {
+ struct connection *nxt = c->hp_next;
- (void)orient(c);
- connect_to_host_pair(c);
- c = nxt;
+ (void)orient(c);
+ connect_to_host_pair(c);
+ c = nxt;
+ }
}
- }
- /* Check that no oriented connection has become double-oriented.
- * In other words, the far side must not match one of our new interfaces.
- */
- {
- struct iface *i;
-
- for (i = interfaces; i != NULL; i = i->next)
+ /* Check that no oriented connection has become double-oriented.
+ * In other words, the far side must not match one of our new interfaces.
+ */
{
- if (i->change == IFN_ADD)
- {
- struct host_pair *hp;
+ struct iface *i;
- for (hp = host_pairs; hp != NULL; hp = hp->next)
+ for (i = interfaces; i != NULL; i = i->next)
{
- if (sameaddr(&hp->him.addr, &i->addr)
- && (!no_klips || hp->him.port == pluto_port))
- {
- /* bad news: the whole chain of connections
- * hanging off this host pair has both sides
- * matching an interface.
- * We'll get rid of them, using orient and
- * connect_to_host_pair. But we'll be lazy
- * and not ditch the host_pair itself (the
- * cost of leaving it is slight and cannot
- * be induced by a foe).
- */
- struct connection *c = hp->connections;
-
- hp->connections = NULL;
- while (c != NULL)
+ if (i->change == IFN_ADD)
{
- struct connection *nxt = c->hp_next;
-
- c->interface = NULL;
- (void)orient(c);
- connect_to_host_pair(c);
- c = nxt;
+ struct host_pair *hp;
+
+ for (hp = host_pairs; hp != NULL; hp = hp->next)
+ {
+ if (sameaddr(&hp->him.addr, &i->addr)
+ && (!no_klips || hp->him.port == pluto_port))
+ {
+ /* bad news: the whole chain of connections
+ * hanging off this host pair has both sides
+ * matching an interface.
+ * We'll get rid of them, using orient and
+ * connect_to_host_pair. But we'll be lazy
+ * and not ditch the host_pair itself (the
+ * cost of leaving it is slight and cannot
+ * be induced by a foe).
+ */
+ struct connection *c = hp->connections;
+
+ hp->connections = NULL;
+ while (c != NULL)
+ {
+ struct connection *nxt = c->hp_next;
+
+ c->interface = NULL;
+ (void)orient(c);
+ connect_to_host_pair(c);
+ c = nxt;
+ }
+ }
+ }
}
- }
}
- }
}
- }
}
static err_t
default_end(struct end *e, ip_address *dflt_nexthop)
{
- err_t ugh = NULL;
- const struct af_info *afi = aftoinfo(addrtypeof(&e->host_addr));
-
- if (afi == NULL)
- return "unknown address family in default_end";
-
- /* default ID to IP (but only if not NO_IP -- WildCard) */
- if (e->id.kind == ID_NONE && !isanyaddr(&e->host_addr))
- {
- e->id.kind = afi->id_addr;
- e->id.ip_addr = e->host_addr;
- e->has_id_wildcards = FALSE;
- }
-
- /* default nexthop to other side */
- if (isanyaddr(&e->host_nexthop))
- e->host_nexthop = *dflt_nexthop;
-
- /* default client to subnet containing only self
- * XXX This may mean that the client's address family doesn't match
- * tunnel_addr_family.
- */
- if (!e->has_client)
- ugh = addrtosubnet(&e->host_addr, &e->client);
-
- return ugh;
+ err_t ugh = NULL;
+ const struct af_info *afi = aftoinfo(addrtypeof(&e->host_addr));
+
+ if (afi == NULL)
+ return "unknown address family in default_end";
+
+ /* default ID to IP (but only if not NO_IP -- WildCard) */
+ if (e->id.kind == ID_ANY && !isanyaddr(&e->host_addr))
+ {
+ e->id.kind = afi->id_addr;
+ e->id.ip_addr = e->host_addr;
+ e->has_id_wildcards = FALSE;
+ }
+
+ /* default nexthop to other side */
+ if (isanyaddr(&e->host_nexthop))
+ e->host_nexthop = *dflt_nexthop;
+
+ /* default client to subnet containing only self
+ * XXX This may mean that the client's address family doesn't match
+ * tunnel_addr_family.
+ */
+ if (!e->has_client)
+ ugh = addrtosubnet(&e->host_addr, &e->client);
+
+ return ugh;
}
/* Format the topology of a connection end, leaving out defaults.
@@ -535,710 +534,702 @@ format_end(char *buf
, bool is_left
, lset_t policy)
{
- char client[SUBNETTOT_BUF];
- const char *client_sep = "";
- char protoport[sizeof(":255/65535")];
- const char *host = NULL;
- char host_space[ADDRTOT_BUF];
- char host_port[sizeof(":65535")];
- char host_id[BUF_LEN + 2];
- char hop[ADDRTOT_BUF];
- const char *hop_sep = "";
- const char *open_brackets = "";
- const char *close_brackets = "";
-
- if (isanyaddr(&this->host_addr))
- {
- switch (policy & (POLICY_GROUP | POLICY_OPPO))
+ char client[SUBNETTOT_BUF];
+ const char *client_sep = "";
+ char protoport[sizeof(":255/65535")];
+ const char *host = NULL;
+ char host_space[ADDRTOT_BUF];
+ char host_port[sizeof(":65535")];
+ char host_id[BUF_LEN + 2];
+ char hop[ADDRTOT_BUF];
+ const char *hop_sep = "";
+ const char *open_brackets = "";
+ const char *close_brackets = "";
+
+ if (isanyaddr(&this->host_addr))
{
- case POLICY_GROUP:
- host = "%group";
- break;
- case POLICY_OPPO:
- host = "%opportunistic";
- break;
- case POLICY_GROUP | POLICY_OPPO:
- host = "%opportunisticgroup";
- break;
- default:
- host = "%any";
- break;
+ switch (policy & (POLICY_GROUP | POLICY_OPPO))
+ {
+ case POLICY_GROUP:
+ host = "%group";
+ break;
+ case POLICY_OPPO:
+ host = "%opportunistic";
+ break;
+ case POLICY_GROUP | POLICY_OPPO:
+ host = "%opportunisticgroup";
+ break;
+ default:
+ host = "%any";
+ break;
+ }
}
- }
-
- client[0] = '\0';
-
- if (is_virtual_end(this) && isanyaddr(&this->host_addr))
- {
- host = "%virtual";
- }
-
- /* [client===] */
- if (this->has_client)
- {
- ip_address client_net, client_mask;
-
- networkof(&this->client, &client_net);
- maskof(&this->client, &client_mask);
- client_sep = "===";
-
- /* {client_subnet_wildcard} */
- if (this->has_client_wildcard)
- {
- open_brackets = "{";
- close_brackets = "}";
- }
-
- if (isanyaddr(&client_net) && isanyaddr(&client_mask)
- && (policy & (POLICY_GROUP | POLICY_OPPO)))
- client_sep = ""; /* boring case */
- else if (subnetisnone(&this->client))
- strcpy(client, "?");
+
+ client[0] = '\0';
+
+ if (is_virtual_end(this) && isanyaddr(&this->host_addr))
+ {
+ host = "%virtual";
+ }
+
+ /* [client===] */
+ if (this->has_client)
+ {
+ ip_address client_net, client_mask;
+
+ networkof(&this->client, &client_net);
+ maskof(&this->client, &client_mask);
+ client_sep = "===";
+
+ /* {client_subnet_wildcard} */
+ if (this->has_client_wildcard)
+ {
+ open_brackets = "{";
+ close_brackets = "}";
+ }
+
+ if (isanyaddr(&client_net) && isanyaddr(&client_mask)
+ && (policy & (POLICY_GROUP | POLICY_OPPO)))
+ client_sep = ""; /* boring case */
+ else if (subnetisnone(&this->client))
+ strcpy(client, "?");
+ else
+ subnettot(&this->client, 0, client, sizeof(client));
+ }
+ else if (this->modecfg && isanyaddr(&this->host_srcip))
+ {
+ /* we are mode config client */
+ client_sep = "===";
+ strcpy(client, "%modecfg");
+ }
+
+ /* host */
+ if (host == NULL)
+ {
+ addrtot(&this->host_addr, 0, host_space, sizeof(host_space));
+ host = host_space;
+ }
+
+ host_port[0] = '\0';
+ if (this->host_port != IKE_UDP_PORT)
+ snprintf(host_port, sizeof(host_port), ":%u"
+ , this->host_port);
+
+ /* payload portocol and port */
+ protoport[0] = '\0';
+ if (this->has_port_wildcard)
+ snprintf(protoport, sizeof(protoport), ":%u/%%any", this->protocol);
+ else if (this->port || this->protocol)
+ snprintf(protoport, sizeof(protoport), ":%u/%u", this->protocol
+ , this->port);
+
+ /* id, if different from host */
+ host_id[0] = '\0';
+ if (this->id.kind == ID_MYID)
+ {
+ strcpy(host_id, "[%myid]");
+ }
+ else if (!(this->id.kind == ID_ANY
+ || (id_is_ipaddr(&this->id) && sameaddr(&this->id.ip_addr, &this->host_addr))))
+ {
+ int len = idtoa(&this->id, host_id+1, sizeof(host_id)-2);
+
+ host_id[0] = '[';
+ strcpy(&host_id[len < 0? (ptrdiff_t)sizeof(host_id)-2 : 1 + len], "]");
+ }
+
+ /* [---hop] */
+ hop[0] = '\0';
+ hop_sep = "";
+ if (that != NULL && !sameaddr(&this->host_nexthop, &that->host_addr))
+ {
+ addrtot(&this->host_nexthop, 0, hop, sizeof(hop));
+ hop_sep = "---";
+ }
+
+ if (is_left)
+ snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
+ , open_brackets, client, close_brackets, client_sep
+ , this->allow_any? "%":""
+ , host, host_port, host_id, protoport
+ , hop_sep, hop);
else
- subnettot(&this->client, 0, client, sizeof(client));
- }
- else if (this->modecfg && isanyaddr(&this->host_srcip))
- {
- /* we are mode config client */
- client_sep = "===";
- strcpy(client, "%modecfg");
- }
-
- /* host */
- if (host == NULL)
- {
- addrtot(&this->host_addr, 0, host_space, sizeof(host_space));
- host = host_space;
- }
-
- host_port[0] = '\0';
- if (this->host_port != IKE_UDP_PORT)
- snprintf(host_port, sizeof(host_port), ":%u"
- , this->host_port);
-
- /* payload portocol and port */
- protoport[0] = '\0';
- if (this->has_port_wildcard)
- snprintf(protoport, sizeof(protoport), ":%u/%%any", this->protocol);
- else if (this->port || this->protocol)
- snprintf(protoport, sizeof(protoport), ":%u/%u", this->protocol
- , this->port);
-
- /* id, if different from host */
- host_id[0] = '\0';
- if (this->id.kind == ID_MYID)
- {
- strcpy(host_id, "[%myid]");
- }
- else if (!(this->id.kind == ID_NONE
- || (id_is_ipaddr(&this->id) && sameaddr(&this->id.ip_addr, &this->host_addr))))
- {
- int len = idtoa(&this->id, host_id+1, sizeof(host_id)-2);
-
- host_id[0] = '[';
- strcpy(&host_id[len < 0? (ptrdiff_t)sizeof(host_id)-2 : 1 + len], "]");
- }
-
- /* [---hop] */
- hop[0] = '\0';
- hop_sep = "";
- if (that != NULL && !sameaddr(&this->host_nexthop, &that->host_addr))
- {
- addrtot(&this->host_nexthop, 0, hop, sizeof(hop));
- hop_sep = "---";
- }
-
- if (is_left)
- snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
- , open_brackets, client, close_brackets, client_sep
- , this->allow_any? "%":""
- , host, host_port, host_id, protoport
- , hop_sep, hop);
- else
- snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
- , hop, hop_sep
- , this->allow_any? "%":""
- , host, host_port, host_id, protoport, client_sep
- , open_brackets, client, close_brackets);
- return strlen(buf);
+ snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
+ , hop, hop_sep
+ , this->allow_any? "%":""
+ , host, host_port, host_id, protoport, client_sep
+ , open_brackets, client, close_brackets);
+ return strlen(buf);
}
/* format topology of a connection.
* Two symmetric ends separated by ...
*/
-#define CONNECTION_BUF (2 * (END_BUF - 1) + 4)
+#define CONNECTION_BUF (2 * (END_BUF - 1) + 4)
static size_t
format_connection(char *buf, size_t buf_len
- , const struct connection *c
- , struct spd_route *sr)
+ , const struct connection *c
+ , struct spd_route *sr)
{
- size_t w = format_end(buf, buf_len, &sr->this, &sr->that, TRUE, LEMPTY);
+ size_t w = format_end(buf, buf_len, &sr->this, &sr->that, TRUE, LEMPTY);
- w += snprintf(buf + w, buf_len - w, "...");
- return w + format_end(buf + w, buf_len - w, &sr->that, &sr->this, FALSE, c->policy);
+ w += snprintf(buf + w, buf_len - w, "...");
+ return w + format_end(buf + w, buf_len - w, &sr->that, &sr->this, FALSE, c->policy);
}
static void
unshare_connection_strings(struct connection *c)
{
- c->name = clone_str(c->name, "connection name");
-
- unshare_id_content(&c->spd.this.id);
- c->spd.this.updown = clone_str(c->spd.this.updown, "updown");
- scx_share(c->spd.this.sc);
- share_cert(c->spd.this.cert);
- if (c->spd.this.ca.ptr != NULL)
- clonetochunk(c->spd.this.ca, c->spd.this.ca.ptr, c->spd.this.ca.len, "ca string");
-
- unshare_id_content(&c->spd.that.id);
- c->spd.that.updown = clone_str(c->spd.that.updown, "updown");
- scx_share(c->spd.that.sc);
- share_cert(c->spd.that.cert);
- if (c->spd.that.ca.ptr != NULL)
- clonetochunk(c->spd.that.ca, c->spd.that.ca.ptr, c->spd.that.ca.len, "ca string");
-
- /* increment references to algo's */
- alg_info_addref((struct alg_info *)c->alg_info_esp);
- alg_info_addref((struct alg_info *)c->alg_info_ike);
+ c->name = clone_str(c->name);
+
+ unshare_id_content(&c->spd.this.id);
+ c->spd.this.updown = clone_str(c->spd.this.updown);
+ scx_share(c->spd.this.sc);
+ share_cert(c->spd.this.cert);
+ c->spd.this.ca = chunk_clone(c->spd.this.ca);
+
+ unshare_id_content(&c->spd.that.id);
+ c->spd.that.updown = clone_str(c->spd.that.updown);
+ scx_share(c->spd.that.sc);
+ share_cert(c->spd.that.cert);
+ c->spd.that.ca = chunk_clone(c->spd.that.ca);
+
+ /* increment references to algo's */
+ alg_info_addref((struct alg_info *)c->alg_info_esp);
+ alg_info_addref((struct alg_info *)c->alg_info_ike);
}
-static void
-load_end_certificate(const char *filename, struct end *dst)
+static void load_end_certificate(char *filename, struct end *dst)
{
- time_t valid_until;
- cert_t cert;
- bool valid_cert = FALSE;
- bool cached_cert = FALSE;
+ time_t valid_until;
+ cert_t cert;
+ bool valid_cert = FALSE;
+ bool cached_cert = FALSE;
- /* initialize end certificate */
- dst->cert.type = CERT_NONE;
- dst->cert.u.x509 = NULL;
+ /* initialize end certificate */
+ dst->cert.type = CERT_NONE;
+ dst->cert.u.x509 = NULL;
- /* initialize smartcard info record */
- dst->sc = NULL;
+ /* initialize smartcard info record */
+ dst->sc = NULL;
- if (filename != NULL)
- {
- if (scx_on_smartcard(filename))
+ if (filename != NULL)
{
- /* load cert from smartcard */
- valid_cert = scx_load_cert(filename, &dst->sc, &cert, &cached_cert);
- }
- else
- {
- /* load cert from file */
- valid_cert = load_host_cert(filename, &cert);
+ if (scx_on_smartcard(filename))
+ {
+ /* load cert from smartcard */
+ valid_cert = scx_load_cert(filename, &dst->sc, &cert, &cached_cert);
+ }
+ else
+ {
+ /* load cert from file */
+ valid_cert = load_host_cert(filename, &cert);
+ }
}
- }
- if (valid_cert)
- {
- err_t ugh = NULL;
-
- switch (cert.type)
+ if (valid_cert)
{
- case CERT_PGP:
- select_pgpcert_id(cert.u.pgp, &dst->id);
-
- if (cached_cert)
- dst->cert = cert;
- else
- {
- valid_until = cert.u.pgp->until;
- add_pgp_public_key(cert.u.pgp, cert.u.pgp->until, DAL_LOCAL);
- dst->cert.type = cert.type;
- dst->cert.u.pgp = add_pgpcert(cert.u.pgp);
- }
- break;
- case CERT_X509_SIGNATURE:
- select_x509cert_id(cert.u.x509, &dst->id);
-
- if (cached_cert)
- dst->cert = cert;
- else
- {
- /* check validity of cert */
- valid_until = cert.u.x509->notAfter;
- ugh = check_validity(cert.u.x509, &valid_until);
- if (ugh != NULL)
+ err_t ugh = NULL;
+
+ switch (cert.type)
{
- plog(" %s", ugh);
- free_x509cert(cert.u.x509);
- break;
- }
+ case CERT_PGP:
+ select_pgpcert_id(cert.u.pgp, &dst->id);
- DBG(DBG_CONTROL,
- DBG_log("certificate is valid")
- )
- add_x509_public_key(cert.u.x509, valid_until, DAL_LOCAL);
- dst->cert.type = cert.type;
- dst->cert.u.x509 = add_x509cert(cert.u.x509);
- }
- /* if no CA is defined, use issuer as default */
- if (dst->ca.ptr == NULL)
- dst->ca = dst->cert.u.x509->issuer;
- break;
- default:
- break;
- }
+ if (cached_cert)
+ dst->cert = cert;
+ else
+ {
+ valid_until = cert.u.pgp->until;
+ add_pgp_public_key(cert.u.pgp, cert.u.pgp->until, DAL_LOCAL);
+ dst->cert.type = cert.type;
+ dst->cert.u.pgp = add_pgpcert(cert.u.pgp);
+ }
+ break;
+ case CERT_X509_SIGNATURE:
+ select_x509cert_id(cert.u.x509, &dst->id);
- /* cache the certificate that was last retrieved from the smartcard */
- if (dst->sc != NULL)
- {
- if (!same_cert(&dst->sc->last_cert, &dst->cert))
- {
- lock_certs_and_keys("load_end_certificates");
- release_cert(dst->sc->last_cert);
- dst->sc->last_cert = dst->cert;
- share_cert(dst->cert);
- unlock_certs_and_keys("load_end_certificates");
- }
- time(&dst->sc->last_load);
+ if (cached_cert)
+ dst->cert = cert;
+ else
+ {
+ /* check validity of cert */
+ valid_until = cert.u.x509->notAfter;
+ ugh = check_validity(cert.u.x509, &valid_until);
+ if (ugh != NULL)
+ {
+ plog(" %s", ugh);
+ free_x509cert(cert.u.x509);
+ break;
+ }
+
+ DBG(DBG_CONTROL,
+ DBG_log("certificate is valid")
+ )
+ add_x509_public_key(cert.u.x509, valid_until, DAL_LOCAL);
+ dst->cert.type = cert.type;
+ dst->cert.u.x509 = add_x509cert(cert.u.x509);
+ }
+ /* if no CA is defined, use issuer as default */
+ if (dst->ca.ptr == NULL)
+ dst->ca = dst->cert.u.x509->issuer;
+ break;
+ default:
+ break;
+ }
+
+ /* cache the certificate that was last retrieved from the smartcard */
+ if (dst->sc != NULL)
+ {
+ if (!same_cert(&dst->sc->last_cert, &dst->cert))
+ {
+ lock_certs_and_keys("load_end_certificates");
+ release_cert(dst->sc->last_cert);
+ dst->sc->last_cert = dst->cert;
+ share_cert(dst->cert);
+ unlock_certs_and_keys("load_end_certificates");
+ }
+ time(&dst->sc->last_load);
+ }
}
- }
}
static bool
extract_end(struct end *dst, const whack_end_t *src, const char *which)
{
- bool same_ca = FALSE;
-
- /* decode id, if any */
- if (src->id == NULL)
- {
- dst->id.kind = ID_NONE;
- }
- else
- {
- err_t ugh = atoid(src->id, &dst->id, TRUE);
+ bool same_ca = FALSE;
- if (ugh != NULL)
+ /* decode id, if any */
+ if (src->id == NULL)
{
- loglog(RC_BADID, "bad %s --id: %s (ignored)", which, ugh);
- dst->id = empty_id; /* ignore bad one */
+ dst->id.kind = ID_ANY;
}
- }
+ else
+ {
+ err_t ugh = atoid(src->id, &dst->id, TRUE);
- dst->ca = empty_chunk;
+ if (ugh != NULL)
+ {
+ loglog(RC_BADID, "bad %s --id: %s (ignored)", which, ugh);
+ dst->id = empty_id; /* ignore bad one */
+ }
+ }
+
+ dst->ca = chunk_empty;
- /* decode CA distinguished name, if any */
- if (src->ca != NULL)
- {
- if streq(src->ca, "%same")
- same_ca = TRUE;
- else if (!streq(src->ca, "%any"))
+ /* decode CA distinguished name, if any */
+ if (src->ca != NULL)
{
- err_t ugh;
-
- dst->ca.ptr = temporary_cyclic_buffer();
- ugh = atodn(src->ca, &dst->ca);
- if (ugh != NULL)
- {
- plog("bad CA string '%s': %s (ignored)", src->ca, ugh);
- dst->ca = empty_chunk;
- }
+ if streq(src->ca, "%same")
+ same_ca = TRUE;
+ else if (!streq(src->ca, "%any"))
+ {
+ err_t ugh;
+
+ dst->ca.ptr = temporary_cyclic_buffer();
+ ugh = atodn(src->ca, &dst->ca);
+ if (ugh != NULL)
+ {
+ plog("bad CA string '%s': %s (ignored)", src->ca, ugh);
+ dst->ca = chunk_empty;
+ }
+ }
}
- }
-
- /* load local end certificate and extract ID, if any */
- load_end_certificate(src->cert, dst);
-
- /* does id has wildcards? */
- dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0;
-
- /* decode group attributes, if any */
- decode_groups(src->groups, &dst->groups);
-
- /* the rest is simple copying of corresponding fields */
- dst->host_addr = src->host_addr;
- dst->host_nexthop = src->host_nexthop;
- dst->host_srcip = src->host_srcip;
- dst->has_natip = src->has_natip;
- dst->client = src->client;
- dst->protocol = src->protocol;
- dst->port = src->port;
- dst->has_port_wildcard = src->has_port_wildcard;
- dst->key_from_DNS_on_demand = src->key_from_DNS_on_demand;
- dst->has_client = src->has_client;
- dst->has_client_wildcard = src->has_client_wildcard;
- dst->modecfg = src->modecfg;
- dst->hostaccess = src->hostaccess;
- dst->allow_any = src->allow_any;
- dst->sendcert = src->sendcert;
- dst->updown = src->updown;
- dst->host_port = src->host_port;
-
- /* if host sourceip is defined but no client is present
- * behind the host then set client to sourceip/32
- */
- if (addrbytesptr(&dst->host_srcip, NULL)
- && !isanyaddr(&dst->host_srcip)
- && !dst->has_natip
- && !dst->has_client)
- {
- err_t ugh = addrtosubnet(&dst->host_srcip, &dst->client);
- if (ugh != NULL)
- plog("could not assign host sourceip to client subnet");
- else
- dst->has_client = TRUE;
- }
- return same_ca;
+ /* load local end certificate and extract ID, if any */
+ load_end_certificate(src->cert, dst);
+
+ /* does id has wildcards? */
+ dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0;
+
+ /* decode group attributes, if any */
+ decode_groups(src->groups, &dst->groups);
+
+ /* the rest is simple copying of corresponding fields */
+ dst->host_addr = src->host_addr;
+ dst->host_nexthop = src->host_nexthop;
+ dst->host_srcip = src->host_srcip;
+ dst->has_natip = src->has_natip;
+ dst->client = src->client;
+ dst->protocol = src->protocol;
+ dst->port = src->port;
+ dst->has_port_wildcard = src->has_port_wildcard;
+ dst->key_from_DNS_on_demand = src->key_from_DNS_on_demand;
+ dst->has_client = src->has_client;
+ dst->has_client_wildcard = src->has_client_wildcard;
+ dst->modecfg = src->modecfg;
+ dst->hostaccess = src->hostaccess;
+ dst->allow_any = src->allow_any;
+ dst->sendcert = src->sendcert;
+ dst->updown = src->updown;
+ dst->host_port = src->host_port;
+
+ /* if host sourceip is defined but no client is present
+ * behind the host then set client to sourceip/32
+ */
+ if (addrbytesptr(&dst->host_srcip, NULL)
+ && !isanyaddr(&dst->host_srcip)
+ && !dst->has_natip
+ && !dst->has_client)
+ {
+ err_t ugh = addrtosubnet(&dst->host_srcip, &dst->client);
+
+ if (ugh != NULL)
+ plog("could not assign host sourceip to client subnet");
+ else
+ dst->has_client = TRUE;
+ }
+ return same_ca;
}
static bool
check_connection_end(const whack_end_t *this, const whack_end_t *that
, const whack_message_t *wm)
{
- if (wm->addr_family != addrtypeof(&this->host_addr)
- || wm->addr_family != addrtypeof(&this->host_nexthop)
- || (this->has_client? wm->tunnel_addr_family : wm->addr_family)
- != subnettypeof(&this->client)
- || subnettypeof(&this->client) != subnettypeof(&that->client))
- {
- /* this should have been diagnosed by whack, so we need not be clear
- * !!! overloaded use of RC_CLASH
- */
- loglog(RC_CLASH, "address family inconsistency in connection");
- return FALSE;
- }
+ if (wm->addr_family != addrtypeof(&this->host_addr)
+ || wm->addr_family != addrtypeof(&this->host_nexthop)
+ || (this->has_client? wm->tunnel_addr_family : wm->addr_family)
+ != subnettypeof(&this->client)
+ || subnettypeof(&this->client) != subnettypeof(&that->client))
+ {
+ /* this should have been diagnosed by whack, so we need not be clear
+ * !!! overloaded use of RC_CLASH
+ */
+ loglog(RC_CLASH, "address family inconsistency in connection");
+ return FALSE;
+ }
- if (isanyaddr(&that->host_addr))
- {
- /* other side is wildcard: we must check if other conditions met */
- if (isanyaddr(&this->host_addr))
+ if (isanyaddr(&that->host_addr))
{
- loglog(RC_ORIENT, "connection must specify host IP address for our side");
- return FALSE;
+ /* other side is wildcard: we must check if other conditions met */
+ if (isanyaddr(&this->host_addr))
+ {
+ loglog(RC_ORIENT, "connection must specify host IP address for our side");
+ return FALSE;
+ }
}
- }
- if (this->virt && (!isanyaddr(&this->host_addr) || this->has_client))
- {
- loglog(RC_CLASH,
- "virtual IP must only be used with %%any and without client");
- return FALSE;
- }
+ if (this->virt && (!isanyaddr(&this->host_addr) || this->has_client))
+ {
+ loglog(RC_CLASH,
+ "virtual IP must only be used with %%any and without client");
+ return FALSE;
+ }
- return TRUE; /* happy */
+ return TRUE; /* happy */
}
struct connection *
find_connection_by_reqid(uint32_t reqid)
{
- struct connection *c;
+ struct connection *c;
- reqid &= ~3;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->spd.reqid == reqid)
- return c;
- }
+ reqid &= ~3;
+ for (c = connections; c != NULL; c = c->ac_next)
+ {
+ if (c->spd.reqid == reqid)
+ return c;
+ }
- return NULL;
+ return NULL;
}
static uint32_t
gen_reqid(void)
{
- uint32_t start;
- static uint32_t reqid = IPSEC_MANUAL_REQID_MAX & ~3;
-
- start = reqid;
- do {
- reqid += 4;
- if (reqid == 0)
- reqid = (IPSEC_MANUAL_REQID_MAX & ~3) + 4;
- if (!find_connection_by_reqid(reqid))
- return reqid;
- } while (reqid != start);
-
- exit_log("unable to allocate reqid");
- return 0; /* never reached ... */
+ uint32_t start;
+ static uint32_t reqid = IPSEC_MANUAL_REQID_MAX & ~3;
+
+ start = reqid;
+ do {
+ reqid += 4;
+ if (reqid == 0)
+ reqid = (IPSEC_MANUAL_REQID_MAX & ~3) + 4;
+ if (!find_connection_by_reqid(reqid))
+ return reqid;
+ } while (reqid != start);
+
+ exit_log("unable to allocate reqid");
+ return 0; /* never reached ... */
}
void
add_connection(const whack_message_t *wm)
{
- if (con_by_name(wm->name, FALSE) != NULL)
- {
- loglog(RC_DUPNAME, "attempt to redefine connection \"%s\"", wm->name);
- }
- else if (wm->right.protocol != wm->left.protocol)
- {
- /* this should haven been diagnosed by whack
- * !!! overloaded use of RC_CLASH
- */
- loglog(RC_CLASH, "the protocol must be the same for leftport and rightport");
- }
- else if (check_connection_end(&wm->right, &wm->left, wm)
- && check_connection_end(&wm->left, &wm->right, wm))
- {
- bool same_rightca, same_leftca;
- struct connection *c = alloc_thing(struct connection, "struct connection");
-
- c->name = wm->name;
- c->ikev1 = wm->ikev1;
- c->policy = wm->policy;
-
- if ((c->policy & POLICY_COMPRESS) && !can_do_IPcomp)
- loglog(RC_COMMENT
- , "ignoring --compress in \"%s\" because KLIPS is not configured to do IPCOMP"
- , c->name);
-
- if (wm->esp)
+ if (con_by_name(wm->name, FALSE) != NULL)
{
- const char *ugh;
-
- DBG(DBG_CONTROL,
- DBG_log("from whack: got --esp=%s", wm->esp ? wm->esp: "NULL")
- )
- c->alg_info_esp= alg_info_esp_create_from_str(wm->esp? wm->esp : "", &ugh);
-
- DBG(DBG_CRYPT|DBG_CONTROL,
- static char buf[256]="<NULL>";
-
- if (c->alg_info_esp)
- alg_info_snprint(buf, sizeof(buf)
- ,(struct alg_info *)c->alg_info_esp);
- DBG_log("esp string values: %s", buf);
- )
- if (c->alg_info_esp)
- {
- if (c->alg_info_esp->alg_info_cnt==0)
- loglog(RC_LOG_SERIOUS
- , "got 0 transforms for esp=\"%s\"", wm->esp);
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "esp string error: %s", ugh? ugh : "Unknown");
- }
+ loglog(RC_DUPNAME, "attempt to redefine connection \"%s\"", wm->name);
}
-
- if (wm->ike)
+ else if (wm->right.protocol != wm->left.protocol)
{
- const char *ugh;
-
- DBG(DBG_CONTROL,
- DBG_log("from whack: got --ike=%s", wm->ike ? wm->ike: "NULL")
- )
- c->alg_info_ike= alg_info_ike_create_from_str(wm->ike? wm->ike : "", &ugh);
-
- DBG(DBG_CRYPT|DBG_CONTROL,
- static char buf[256]="<NULL>";
-
- if (c->alg_info_ike)
- alg_info_snprint(buf, sizeof(buf)
- , (struct alg_info *)c->alg_info_ike);
- DBG_log("ike string values: %s", buf);
- )
- if (c->alg_info_ike)
- {
- if (c->alg_info_ike->alg_info_cnt==0)
- loglog(RC_LOG_SERIOUS
- , "got 0 transforms for ike=\"%s\"", wm->ike);
- }
- else
- {
- loglog(RC_LOG_SERIOUS
- , "ike string error: %s", ugh? ugh : "Unknown");
- }
+ /* this should haven been diagnosed by whack
+ * !!! overloaded use of RC_CLASH
+ */
+ loglog(RC_CLASH, "the protocol must be the same for leftport and rightport");
}
-
- c->sa_ike_life_seconds = wm->sa_ike_life_seconds;
- c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds;
- c->sa_rekey_margin = wm->sa_rekey_margin;
- c->sa_rekey_fuzz = wm->sa_rekey_fuzz;
- c->sa_keying_tries = wm->sa_keying_tries;
+ else if (check_connection_end(&wm->right, &wm->left, wm)
+ && check_connection_end(&wm->left, &wm->right, wm))
+ {
+ bool same_rightca, same_leftca;
+ struct connection *c = malloc_thing(struct connection);
- /* RFC 3706 DPD */
- c->dpd_delay = wm->dpd_delay;
- c->dpd_timeout = wm->dpd_timeout;
- c->dpd_action = wm->dpd_action;
+ zero(c);
+ c->name = wm->name;
+ c->ikev1 = wm->ikev1;
+ c->policy = wm->policy;
- c->addr_family = wm->addr_family;
- c->tunnel_addr_family = wm->tunnel_addr_family;
+ if ((c->policy & POLICY_COMPRESS) && !can_do_IPcomp)
+ loglog(RC_COMMENT
+ , "ignoring --compress in \"%s\" because KLIPS is not configured to do IPCOMP"
+ , c->name);
- c->requested_ca = NULL;
+ if (wm->esp)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("from whack: got --esp=%s", wm->esp ? wm->esp: "NULL")
+ )
+ c->alg_info_esp= alg_info_esp_create_from_str(wm->esp? wm->esp : "");
+
+ DBG(DBG_CRYPT|DBG_CONTROL,
+ static char buf[BUF_LEN]="<NULL>";
+
+ if (c->alg_info_esp)
+ alg_info_snprint(buf, sizeof(buf)
+ ,(struct alg_info *)c->alg_info_esp);
+ DBG_log("esp proposal: %s", buf);
+ )
+ if (c->alg_info_esp)
+ {
+ if (c->alg_info_esp->alg_info_cnt==0)
+ loglog(RC_LOG_SERIOUS
+ , "got 0 transforms for esp=\"%s\"", wm->esp);
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "esp string error");
+ }
+ }
+
+ if (wm->ike)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("from whack: got --ike=%s", wm->ike ? wm->ike: "NULL")
+ )
+ c->alg_info_ike= alg_info_ike_create_from_str(wm->ike? wm->ike : "");
+
+ DBG(DBG_CRYPT|DBG_CONTROL,
+ static char buf[BUF_LEN]="<NULL>";
+
+ if (c->alg_info_ike)
+ alg_info_snprint(buf, sizeof(buf)
+ , (struct alg_info *)c->alg_info_ike);
+ DBG_log("ike proposal: %s", buf);
+ )
+ if (c->alg_info_ike)
+ {
+ if (c->alg_info_ike->alg_info_cnt==0)
+ loglog(RC_LOG_SERIOUS
+ , "got 0 transforms for ike=\"%s\"", wm->ike);
+ }
+ else
+ {
+ loglog(RC_LOG_SERIOUS, "ike string error:");
+ }
+ }
+
+ c->sa_ike_life_seconds = wm->sa_ike_life_seconds;
+ c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds;
+ c->sa_rekey_margin = wm->sa_rekey_margin;
+ c->sa_rekey_fuzz = wm->sa_rekey_fuzz;
+ c->sa_keying_tries = wm->sa_keying_tries;
- same_leftca = extract_end(&c->spd.this, &wm->left, "left");
- same_rightca = extract_end(&c->spd.that, &wm->right, "right");
+ /* RFC 3706 DPD */
+ c->dpd_delay = wm->dpd_delay;
+ c->dpd_timeout = wm->dpd_timeout;
+ c->dpd_action = wm->dpd_action;
- if (same_rightca)
- c->spd.that.ca = c->spd.this.ca;
- else if (same_leftca)
- c->spd.this.ca = c->spd.that.ca;
+ c->addr_family = wm->addr_family;
+ c->tunnel_addr_family = wm->tunnel_addr_family;
- default_end(&c->spd.this, &c->spd.that.host_addr);
- default_end(&c->spd.that, &c->spd.this.host_addr);
+ c->requested_ca = NULL;
- /* force any wildcard host IP address, any wildcard subnet
- * or any wildcard ID to that end
- */
- if (isanyaddr(&c->spd.this.host_addr) || c->spd.this.has_client_wildcard
- || c->spd.this.has_port_wildcard || c->spd.this.has_id_wildcards
- || c->spd.this.allow_any)
- {
- struct end t = c->spd.this;
+ same_leftca = extract_end(&c->spd.this, &wm->left, "left");
+ same_rightca = extract_end(&c->spd.that, &wm->right, "right");
- c->spd.this = c->spd.that;
- c->spd.that = t;
- }
+ if (same_rightca)
+ c->spd.that.ca = c->spd.this.ca;
+ else if (same_leftca)
+ c->spd.this.ca = c->spd.that.ca;
- c->spd.next = NULL;
- c->spd.reqid = gen_reqid();
+ default_end(&c->spd.this, &c->spd.that.host_addr);
+ default_end(&c->spd.that, &c->spd.this.host_addr);
- /* set internal fields */
- c->instance_serial = 0;
- c->ac_next = connections;
- connections = c;
- c->interface = NULL;
- c->spd.routing = RT_UNROUTED;
- c->newest_isakmp_sa = SOS_NOBODY;
- c->newest_ipsec_sa = SOS_NOBODY;
- c->spd.eroute_owner = SOS_NOBODY;
-
- if (c->policy & POLICY_GROUP)
- {
- c->kind = CK_GROUP;
- add_group(c);
- }
- else if ((isanyaddr(&c->spd.that.host_addr) && !NEVER_NEGOTIATE(c->policy))
- || c->spd.that.has_client_wildcard || c->spd.that.has_port_wildcard
- || c->spd.that.has_id_wildcards || c->spd.that.allow_any)
- {
- /* Opportunistic or Road Warrior or wildcard client subnet
- * or wildcard ID */
- c->kind = CK_TEMPLATE;
- }
- else
- {
- c->kind = CK_PERMANENT;
- }
- set_policy_prio(c); /* must be after kind is set */
+ /* force any wildcard host IP address, any wildcard subnet
+ * or any wildcard ID to that end
+ */
+ if (isanyaddr(&c->spd.this.host_addr) || c->spd.this.has_client_wildcard
+ || c->spd.this.has_port_wildcard || c->spd.this.has_id_wildcards
+ || c->spd.this.allow_any)
+ {
+ struct end t = c->spd.this;
+
+ c->spd.this = c->spd.that;
+ c->spd.that = t;
+ }
+
+ c->spd.next = NULL;
+ c->spd.reqid = gen_reqid();
+
+ /* set internal fields */
+ c->instance_serial = 0;
+ c->ac_next = connections;
+ connections = c;
+ c->interface = NULL;
+ c->spd.routing = RT_UNROUTED;
+ c->newest_isakmp_sa = SOS_NOBODY;
+ c->newest_ipsec_sa = SOS_NOBODY;
+ c->spd.eroute_owner = SOS_NOBODY;
+
+ if (c->policy & POLICY_GROUP)
+ {
+ c->kind = CK_GROUP;
+ add_group(c);
+ }
+ else if ((isanyaddr(&c->spd.that.host_addr) && !NEVER_NEGOTIATE(c->policy))
+ || c->spd.that.has_client_wildcard || c->spd.that.has_port_wildcard
+ || c->spd.that.has_id_wildcards || c->spd.that.allow_any)
+ {
+ /* Opportunistic or Road Warrior or wildcard client subnet
+ * or wildcard ID */
+ c->kind = CK_TEMPLATE;
+ }
+ else
+ {
+ c->kind = CK_PERMANENT;
+ }
+ set_policy_prio(c); /* must be after kind is set */
#ifdef DEBUG
- c->extra_debugging = wm->debugging;
+ c->extra_debugging = wm->debugging;
#endif
- c->gw_info = NULL;
+ c->gw_info = NULL;
- passert(!(wm->left.virt && wm->right.virt));
- if (wm->left.virt || wm->right.virt)
- {
- passert(isanyaddr(&c->spd.that.host_addr));
- c->spd.that.virt = create_virtual(c,
- wm->left.virt ? wm->left.virt : wm->right.virt);
- if (c->spd.that.virt)
- c->spd.that.has_client = TRUE;
- }
+ passert(!(wm->left.virt && wm->right.virt));
+ if (wm->left.virt || wm->right.virt)
+ {
+ passert(isanyaddr(&c->spd.that.host_addr));
+ c->spd.that.virt = create_virtual(c,
+ wm->left.virt ? wm->left.virt : wm->right.virt);
+ if (c->spd.that.virt)
+ c->spd.that.has_client = TRUE;
+ }
- unshare_connection_strings(c);
- (void)orient(c);
+ unshare_connection_strings(c);
+ (void)orient(c);
- if (c->ikev1)
- connect_to_host_pair(c);
+ if (c->ikev1)
+ connect_to_host_pair(c);
- /* log all about this connection */
- plog("added connection description \"%s\"", c->name);
- DBG(DBG_CONTROL,
- char topo[CONNECTION_BUF];
-
- (void) format_connection(topo, sizeof(topo), c, &c->spd);
-
- DBG_log("%s", topo);
-
- /* Make sure that address families can be correctly inferred
- * from printed ends.
- */
- passert(c->addr_family == addrtypeof(&c->spd.this.host_addr)
- && c->addr_family == addrtypeof(&c->spd.this.host_nexthop)
- && (c->spd.this.has_client? c->tunnel_addr_family : c->addr_family)
- == subnettypeof(&c->spd.this.client)
-
- && c->addr_family == addrtypeof(&c->spd.that.host_addr)
- && c->addr_family == addrtypeof(&c->spd.that.host_nexthop)
- && (c->spd.that.has_client? c->tunnel_addr_family : c->addr_family)
- == subnettypeof(&c->spd.that.client));
-
- DBG_log("ike_life: %lus; ipsec_life: %lus; rekey_margin: %lus;"
- " rekey_fuzz: %lu%%; keyingtries: %lu; policy: %s"
- , (unsigned long) c->sa_ike_life_seconds
- , (unsigned long) c->sa_ipsec_life_seconds
- , (unsigned long) c->sa_rekey_margin
- , (unsigned long) c->sa_rekey_fuzz
- , (unsigned long) c->sa_keying_tries
- , prettypolicy(c->policy));
- );
- }
+ /* log all about this connection */
+ plog("added connection description \"%s\"", c->name);
+ DBG(DBG_CONTROL,
+ char topo[CONNECTION_BUF];
+
+ (void) format_connection(topo, sizeof(topo), c, &c->spd);
+
+ DBG_log("%s", topo);
+
+ /* Make sure that address families can be correctly inferred
+ * from printed ends.
+ */
+ passert(c->addr_family == addrtypeof(&c->spd.this.host_addr)
+ && c->addr_family == addrtypeof(&c->spd.this.host_nexthop)
+ && (c->spd.this.has_client? c->tunnel_addr_family : c->addr_family)
+ == subnettypeof(&c->spd.this.client)
+
+ && c->addr_family == addrtypeof(&c->spd.that.host_addr)
+ && c->addr_family == addrtypeof(&c->spd.that.host_nexthop)
+ && (c->spd.that.has_client? c->tunnel_addr_family : c->addr_family)
+ == subnettypeof(&c->spd.that.client));
+
+ DBG_log("ike_life: %lus; ipsec_life: %lus; rekey_margin: %lus;"
+ " rekey_fuzz: %lu%%; keyingtries: %lu; policy: %s"
+ , (unsigned long) c->sa_ike_life_seconds
+ , (unsigned long) c->sa_ipsec_life_seconds
+ , (unsigned long) c->sa_rekey_margin
+ , (unsigned long) c->sa_rekey_fuzz
+ , (unsigned long) c->sa_keying_tries
+ , prettypolicy(c->policy));
+ );
+ }
}
/* Derive a template connection from a group connection and target.
* Similar to instantiate(). Happens at whack --listen.
* Returns name of new connection. May be NULL.
- * Caller is responsible for pfreeing.
+ * Caller is responsible for freeing.
*/
char *
add_group_instance(struct connection *group, const ip_subnet *target)
{
- char namebuf[100]
- , targetbuf[SUBNETTOT_BUF];
- struct connection *t;
- char *name = NULL;
-
- passert(group->kind == CK_GROUP);
- passert(oriented(*group));
-
- /* manufacture a unique name for this template */
- subnettot(target, 0, targetbuf, sizeof(targetbuf));
- snprintf(namebuf, sizeof(namebuf), "%s#%s", group->name, targetbuf);
-
- if (con_by_name(namebuf, FALSE) != NULL)
- {
- loglog(RC_DUPNAME, "group name + target yields duplicate name \"%s\""
- , namebuf);
- }
- else
- {
- t = clone_thing(*group, "group instance");
- t->name = namebuf;
- unshare_connection_strings(t);
- name = clone_str(t->name, "group instance name");
- t->spd.that.client = *target;
- t->policy &= ~(POLICY_GROUP | POLICY_GROUTED);
- t->kind = isanyaddr(&t->spd.that.host_addr) && !NEVER_NEGOTIATE(t->policy)
- ? CK_TEMPLATE : CK_INSTANCE;
+ char namebuf[100]
+ , targetbuf[SUBNETTOT_BUF];
+ struct connection *t;
+ char *name = NULL;
- /* reset log file info */
- t->log_file_name = NULL;
- t->log_file = NULL;
- t->log_file_err = FALSE;
+ passert(group->kind == CK_GROUP);
+ passert(oriented(*group));
- t->spd.reqid = gen_reqid();
+ /* manufacture a unique name for this template */
+ subnettot(target, 0, targetbuf, sizeof(targetbuf));
+ snprintf(namebuf, sizeof(namebuf), "%s#%s", group->name, targetbuf);
- if (t->spd.that.virt)
+ if (con_by_name(namebuf, FALSE) != NULL)
{
- DBG_log("virtual_ip not supported in group instance");
- t->spd.that.virt = NULL;
+ loglog(RC_DUPNAME, "group name + target yields duplicate name \"%s\""
+ , namebuf);
}
+ else
+ {
+ t = clone_thing(*group);
+ t->name = namebuf;
+ unshare_connection_strings(t);
+ name = clone_str(t->name);
+ t->spd.that.client = *target;
+ t->policy &= ~(POLICY_GROUP | POLICY_GROUTED);
+ t->kind = isanyaddr(&t->spd.that.host_addr) && !NEVER_NEGOTIATE(t->policy)
+ ? CK_TEMPLATE : CK_INSTANCE;
+
+ /* reset log file info */
+ t->log_file_name = NULL;
+ t->log_file = NULL;
+ t->log_file_err = FALSE;
+
+ t->spd.reqid = gen_reqid();
+
+ if (t->spd.that.virt)
+ {
+ DBG_log("virtual_ip not supported in group instance");
+ t->spd.that.virt = NULL;
+ }
- /* add to connections list */
- t->ac_next = connections;
- connections = t;
+ /* add to connections list */
+ t->ac_next = connections;
+ connections = t;
- /* same host_pair as parent: stick after parent on list */
- group->hp_next = t;
+ /* same host_pair as parent: stick after parent on list */
+ group->hp_next = t;
- /* route if group is routed */
- if (group->policy & POLICY_GROUTED)
- {
- if (!trap_connection(t))
- whack_log(RC_ROUTE, "could not route");
+ /* route if group is routed */
+ if (group->policy & POLICY_GROUTED)
+ {
+ if (!trap_connection(t))
+ whack_log(RC_ROUTE, "could not route");
+ }
}
- }
- return name;
+ return name;
}
/* an old target has disappeared for a group: delete instance */
@@ -1246,17 +1237,17 @@ void
remove_group_instance(const struct connection *group USED_BY_DEBUG
, const char *name)
{
- passert(group->kind == CK_GROUP);
- passert(oriented(*group));
+ passert(group->kind == CK_GROUP);
+ passert(oriented(*group));
- delete_connections_by_name(name, FALSE);
+ delete_connections_by_name(name, FALSE);
}
/* Common part of instantiating a Road Warrior or Opportunistic connection.
* his_id can be used to carry over an ID discovered in Phase 1.
* It must not disagree with the one in c, but if that is unspecified,
* the new connection will use his_id.
- * If his_id is NULL, and c.that.id is uninstantiated (ID_NONE), the
+ * If his_id is NULL, and c.that.id is uninstantiated (ID_ANY), the
* new connection will continue to have an uninstantiated that.id.
* Note: instantiation does not affect port numbers.
*
@@ -1267,90 +1258,90 @@ instantiate(struct connection *c, const ip_address *him
, u_int16_t his_port
, const struct id *his_id)
{
- struct connection *d;
- int wildcards;
-
- passert(c->kind == CK_TEMPLATE);
- passert(c->spd.next == NULL);
-
- c->instance_serial++;
- d = clone_thing(*c, "temporary connection");
- d->spd.that.allow_any = FALSE;
-
- if (his_id != NULL)
- {
- passert(match_id(his_id, &d->spd.that.id, &wildcards));
- d->spd.that.id = *his_id;
- d->spd.that.has_id_wildcards = FALSE;
- }
- unshare_connection_strings(d);
- unshare_ietfAttrList(&d->spd.this.groups);
- unshare_ietfAttrList(&d->spd.that.groups);
- d->kind = CK_INSTANCE;
-
- passert(oriented(*d));
- d->spd.that.host_addr = *him;
- setportof(htons(c->spd.that.port), &d->spd.that.host_addr);
-
- if (his_port) d->spd.that.host_port = his_port;
-
- default_end(&d->spd.that, &d->spd.this.host_addr);
-
- /* We cannot guess what our next_hop should be, but if it was
- * explicitly specified as 0.0.0.0, we set it to be him.
- * (whack will not allow nexthop to be elided in RW case.)
- */
- default_end(&d->spd.this, &d->spd.that.host_addr);
- d->spd.next = NULL;
- d->spd.reqid = gen_reqid();
-
- /* set internal fields */
- d->ac_next = connections;
- connections = d;
- d->spd.routing = RT_UNROUTED;
- d->newest_isakmp_sa = SOS_NOBODY;
- d->newest_ipsec_sa = SOS_NOBODY;
- d->spd.eroute_owner = SOS_NOBODY;
-
- /* reset log file info */
- d->log_file_name = NULL;
- d->log_file = NULL;
- d->log_file_err = FALSE;
-
- connect_to_host_pair(d);
-
- return d;
- if (sameaddr(&d->spd.that.host_addr, &d->spd.this.host_nexthop))
- {
- d->spd.this.host_nexthop = *him;
- }
+ struct connection *d;
+ int wildcards;
+
+ passert(c->kind == CK_TEMPLATE);
+ passert(c->spd.next == NULL);
+
+ c->instance_serial++;
+ d = clone_thing(*c);
+ d->spd.that.allow_any = FALSE;
+
+ if (his_id != NULL)
+ {
+ passert(match_id(his_id, &d->spd.that.id, &wildcards));
+ d->spd.that.id = *his_id;
+ d->spd.that.has_id_wildcards = FALSE;
+ }
+ unshare_connection_strings(d);
+ unshare_ietfAttrList(&d->spd.this.groups);
+ unshare_ietfAttrList(&d->spd.that.groups);
+ d->kind = CK_INSTANCE;
+
+ passert(oriented(*d));
+ d->spd.that.host_addr = *him;
+ setportof(htons(c->spd.that.port), &d->spd.that.host_addr);
+
+ if (his_port) d->spd.that.host_port = his_port;
+
+ default_end(&d->spd.that, &d->spd.this.host_addr);
+
+ /* We cannot guess what our next_hop should be, but if it was
+ * explicitly specified as 0.0.0.0, we set it to be him.
+ * (whack will not allow nexthop to be elided in RW case.)
+ */
+ default_end(&d->spd.this, &d->spd.that.host_addr);
+ d->spd.next = NULL;
+ d->spd.reqid = gen_reqid();
+
+ /* set internal fields */
+ d->ac_next = connections;
+ connections = d;
+ d->spd.routing = RT_UNROUTED;
+ d->newest_isakmp_sa = SOS_NOBODY;
+ d->newest_ipsec_sa = SOS_NOBODY;
+ d->spd.eroute_owner = SOS_NOBODY;
+
+ /* reset log file info */
+ d->log_file_name = NULL;
+ d->log_file = NULL;
+ d->log_file_err = FALSE;
+
+ connect_to_host_pair(d);
+
+ return d;
+ if (sameaddr(&d->spd.that.host_addr, &d->spd.this.host_nexthop))
+ {
+ d->spd.this.host_nexthop = *him;
+ }
}
struct connection *
rw_instantiate(struct connection *c, const ip_address *him, u_int16_t his_port
, const ip_subnet *his_net, const struct id *his_id)
{
- struct connection *d = instantiate(c, him, his_port, his_id);
-
- if (d && his_net && is_virtual_connection(c))
- {
- d->spd.that.client = *his_net;
- d->spd.that.virt = NULL;
- if (subnetishost(his_net) && addrinsubnet(him, his_net))
- d->spd.that.has_client = FALSE;
- }
-
- if (d->policy & POLICY_OPPO)
- {
- /* This must be before we know the client addresses.
- * Fill in one that is impossible. This prevents anyone else from
- * trying to use this connection to get to a particular client
- */
- d->spd.that.client = *aftoinfo(subnettypeof(&d->spd.that.client))->none;
- }
- DBG(DBG_CONTROL
- , DBG_log("instantiated \"%s\" for %s" , d->name, ip_str(him)));
- return d;
+ struct connection *d = instantiate(c, him, his_port, his_id);
+
+ if (d && his_net && is_virtual_connection(c))
+ {
+ d->spd.that.client = *his_net;
+ d->spd.that.virt = NULL;
+ if (subnetishost(his_net) && addrinsubnet(him, his_net))
+ d->spd.that.has_client = FALSE;
+ }
+
+ if (d->policy & POLICY_OPPO)
+ {
+ /* This must be before we know the client addresses.
+ * Fill in one that is impossible. This prevents anyone else from
+ * trying to use this connection to get to a particular client
+ */
+ d->spd.that.client = *aftoinfo(subnettypeof(&d->spd.that.client))->none;
+ }
+ DBG(DBG_CONTROL
+ , DBG_log("instantiated \"%s\" for %s" , d->name, ip_str(him)));
+ return d;
}
struct connection *
@@ -1361,77 +1352,77 @@ oppo_instantiate(struct connection *c
, const ip_address *our_client USED_BY_DEBUG
, const ip_address *peer_client)
{
- struct connection *d = instantiate(c, him, 0, his_id);
+ struct connection *d = instantiate(c, him, 0, his_id);
- passert(d->spd.next == NULL);
+ passert(d->spd.next == NULL);
+
+ /* fill in our client side */
+ if (d->spd.this.has_client)
+ {
+ /* there was a client in the abstract connection
+ * so we demand that the required client is within that subnet.
+ */
+ passert(addrinsubnet(our_client, &d->spd.this.client));
+ happy(addrtosubnet(our_client, &d->spd.this.client));
+ /* opportunistic connections do not use port selectors */
+ setportof(0, &d->spd.this.client.addr);
+ }
+ else
+ {
+ /* there was no client in the abstract connection
+ * so we demand that the required client be the host
+ */
+ passert(sameaddr(our_client, &d->spd.this.host_addr));
+ }
- /* fill in our client side */
- if (d->spd.this.has_client)
- {
- /* there was a client in the abstract connection
- * so we demand that the required client is within that subnet.
+ /* fill in peer's client side.
+ * If the client is the peer, excise the client from the connection.
*/
- passert(addrinsubnet(our_client, &d->spd.this.client));
- happy(addrtosubnet(our_client, &d->spd.this.client));
+ passert((d->policy & POLICY_OPPO)
+ && addrinsubnet(peer_client, &d->spd.that.client));
+ happy(addrtosubnet(peer_client, &d->spd.that.client));
/* opportunistic connections do not use port selectors */
- setportof(0, &d->spd.this.client.addr);
- }
- else
- {
- /* there was no client in the abstract connection
- * so we demand that the required client be the host
+ setportof(0, &d->spd.that.client.addr);
+
+ if (sameaddr(peer_client, &d->spd.that.host_addr))
+ d->spd.that.has_client = FALSE;
+
+ passert(d->gw_info == NULL);
+ gw_addref(gw);
+ d->gw_info = gw;
+
+ /* Adjust routing if something is eclipsing c.
+ * It must be a %hold for us (hard to passert this).
+ * If there was another instance eclipsing, we'd be using it.
+ */
+ if (c->spd.routing == RT_ROUTED_ECLIPSED)
+ d->spd.routing = RT_ROUTED_PROSPECTIVE;
+
+ /* Remember if the template is routed:
+ * if so, this instance applies for initiation
+ * even if it is created for responding.
*/
- passert(sameaddr(our_client, &d->spd.this.host_addr));
- }
-
- /* fill in peer's client side.
- * If the client is the peer, excise the client from the connection.
- */
- passert((d->policy & POLICY_OPPO)
- && addrinsubnet(peer_client, &d->spd.that.client));
- happy(addrtosubnet(peer_client, &d->spd.that.client));
- /* opportunistic connections do not use port selectors */
- setportof(0, &d->spd.that.client.addr);
-
- if (sameaddr(peer_client, &d->spd.that.host_addr))
- d->spd.that.has_client = FALSE;
-
- passert(d->gw_info == NULL);
- gw_addref(gw);
- d->gw_info = gw;
-
- /* Adjust routing if something is eclipsing c.
- * It must be a %hold for us (hard to passert this).
- * If there was another instance eclipsing, we'd be using it.
- */
- if (c->spd.routing == RT_ROUTED_ECLIPSED)
- d->spd.routing = RT_ROUTED_PROSPECTIVE;
-
- /* Remember if the template is routed:
- * if so, this instance applies for initiation
- * even if it is created for responding.
- */
- if (routed(c->spd.routing))
- d->instance_initiation_ok = TRUE;
-
- DBG(DBG_CONTROL,
- char topo[CONNECTION_BUF];
-
- (void) format_connection(topo, sizeof(topo), d, &d->spd);
- DBG_log("instantiated \"%s\": %s", d->name, topo);
- );
- return d;
+ if (routed(c->spd.routing))
+ d->instance_initiation_ok = TRUE;
+
+ DBG(DBG_CONTROL,
+ char topo[CONNECTION_BUF];
+
+ (void) format_connection(topo, sizeof(topo), d, &d->spd);
+ DBG_log("instantiated \"%s\": %s", d->name, topo);
+ );
+ return d;
}
/* priority formatting */
void
fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
{
- if (pp == BOTTOM_PRIO)
- snprintf(buf, POLICY_PRIO_BUF, "0");
- else
- snprintf(buf, POLICY_PRIO_BUF, "%lu,%lu"
- , pp>>16, (pp & ~(~(policy_prio_t)0 << 16)) >> 8);
+ if (pp == BOTTOM_PRIO)
+ snprintf(buf, POLICY_PRIO_BUF, "0");
+ else
+ snprintf(buf, POLICY_PRIO_BUF, "%lu,%lu"
+ , pp>>16, (pp & ~(~(policy_prio_t)0 << 16)) >> 8);
}
/* Format any information needed to identify an instance of a connection.
@@ -1442,65 +1433,65 @@ fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
static size_t
fmt_client(const ip_subnet *client, const ip_address *gw, const char *prefix, char buf[ADDRTOT_BUF])
{
- if (subnetisaddr(client, gw))
- {
- buf[0] = '\0'; /* compact denotation for "self" */
- }
- else
- {
- char *ap;
-
- strcpy(buf, prefix);
- ap = buf + strlen(prefix);
- if (subnetisnone(client))
- strcpy(ap, "?"); /* unknown */
+ if (subnetisaddr(client, gw))
+ {
+ buf[0] = '\0'; /* compact denotation for "self" */
+ }
else
- subnettot(client, 0, ap, SUBNETTOT_BUF);
- }
- return strlen(buf);
+ {
+ char *ap;
+
+ strcpy(buf, prefix);
+ ap = buf + strlen(prefix);
+ if (subnetisnone(client))
+ strcpy(ap, "?"); /* unknown */
+ else
+ subnettot(client, 0, ap, SUBNETTOT_BUF);
+ }
+ return strlen(buf);
}
void
fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF])
{
- char *p = buf;
+ char *p = buf;
- *p = '\0';
+ *p = '\0';
- if (c->kind == CK_INSTANCE)
- {
- if (c->instance_serial != 0)
+ if (c->kind == CK_INSTANCE)
{
- snprintf(p, CONN_INST_BUF, "[%lu]", c->instance_serial);
- p += strlen(p);
- }
+ if (c->instance_serial != 0)
+ {
+ snprintf(p, CONN_INST_BUF, "[%lu]", c->instance_serial);
+ p += strlen(p);
+ }
- if (c->policy & POLICY_OPPO)
- {
- size_t w = fmt_client(&c->spd.this.client, &c->spd.this.host_addr, " ", p);
+ if (c->policy & POLICY_OPPO)
+ {
+ size_t w = fmt_client(&c->spd.this.client, &c->spd.this.host_addr, " ", p);
- p += w;
+ p += w;
- strcpy(p, w == 0? " ..." : "=== ...");
- p += strlen(p);
+ strcpy(p, w == 0? " ..." : "=== ...");
+ p += strlen(p);
- addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
- p += strlen(p);
+ addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
+ p += strlen(p);
- (void) fmt_client(&c->spd.that.client, &c->spd.that.host_addr, "===", p);
- }
- else
- {
- *p++ = ' ';
- addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
+ (void) fmt_client(&c->spd.that.client, &c->spd.that.host_addr, "===", p);
+ }
+ else
+ {
+ *p++ = ' ';
+ addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
#
- if (c->spd.that.host_port != pluto_port)
- {
- p += strlen(p);
- sprintf(p, ":%d", c->spd.that.host_port);
- }
+ if (c->spd.that.host_port != pluto_port)
+ {
+ p += strlen(p);
+ sprintf(p, ":%d", c->spd.that.host_port);
+ }
+ }
}
- }
}
/* Find an existing connection for a trapped outbound packet.
@@ -1520,124 +1511,124 @@ fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF])
*/
struct connection *
find_connection_for_clients(struct spd_route **srp,
- const ip_address *our_client,
- const ip_address *peer_client,
- int transport_proto)
+ const ip_address *our_client,
+ const ip_address *peer_client,
+ int transport_proto)
{
- struct connection *c = connections, *best = NULL;
- policy_prio_t best_prio = BOTTOM_PRIO;
- struct spd_route *sr;
- struct spd_route *best_sr = NULL;
- int our_port = ntohs(portof(our_client));
- int peer_port = ntohs(portof(peer_client));
-
- passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
+ struct connection *c = connections, *best = NULL;
+ policy_prio_t best_prio = BOTTOM_PRIO;
+ struct spd_route *sr;
+ struct spd_route *best_sr = NULL;
+ int our_port = ntohs(portof(our_client));
+ int peer_port = ntohs(portof(peer_client));
+
+ passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
#ifdef DEBUG
- if (DBGP(DBG_CONTROL))
- {
- char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
+ if (DBGP(DBG_CONTROL))
+ {
+ char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
- addrtot(our_client, 0, ocb, sizeof(ocb));
- addrtot(peer_client, 0, pcb, sizeof(pcb));
- DBG_log("find_connection: "
- "looking for policy for connection: %s:%d/%d -> %s:%d/%d"
- , ocb, transport_proto, our_port, pcb, transport_proto, peer_port);
- }
+ addrtot(our_client, 0, ocb, sizeof(ocb));
+ addrtot(peer_client, 0, pcb, sizeof(pcb));
+ DBG_log("find_connection: "
+ "looking for policy for connection: %s:%d/%d -> %s:%d/%d"
+ , ocb, transport_proto, our_port, pcb, transport_proto, peer_port);
+ }
#endif /* DEBUG */
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->kind == CK_GROUP)
- continue;
-
- for (sr = &c->spd; best!=c && sr; sr = sr->next)
+ for (c = connections; c != NULL; c = c->ac_next)
{
- if ((routed(sr->routing) || c->instance_initiation_ok)
- && addrinsubnet(our_client, &sr->this.client)
- && addrinsubnet(peer_client, &sr->that.client)
- && addrinsubnet(peer_client, &sr->that.client)
- && (!sr->this.protocol || transport_proto == sr->this.protocol)
- && (!sr->this.port || our_port == sr->this.port)
- && (!sr->that.port || peer_port == sr->that.port))
- {
- char cib[CONN_INST_BUF];
- char cib2[CONN_INST_BUF];
+ if (c->kind == CK_GROUP)
+ continue;
+
+ for (sr = &c->spd; best!=c && sr; sr = sr->next)
+ {
+ if ((routed(sr->routing) || c->instance_initiation_ok)
+ && addrinsubnet(our_client, &sr->this.client)
+ && addrinsubnet(peer_client, &sr->that.client)
+ && addrinsubnet(peer_client, &sr->that.client)
+ && (!sr->this.protocol || transport_proto == sr->this.protocol)
+ && (!sr->this.port || our_port == sr->this.port)
+ && (!sr->that.port || peer_port == sr->that.port))
+ {
+ char cib[CONN_INST_BUF];
+ char cib2[CONN_INST_BUF];
- policy_prio_t prio = 8 * (c->prio + (c->kind == CK_INSTANCE))
- + 2 * (sr->this.port == our_port)
- + 2 * (sr->that.port == peer_port)
- + (sr->this.protocol == transport_proto);
+ policy_prio_t prio = 8 * (c->prio + (c->kind == CK_INSTANCE))
+ + 2 * (sr->this.port == our_port)
+ + 2 * (sr->that.port == peer_port)
+ + (sr->this.protocol == transport_proto);
#ifdef DEBUG
- if (DBGP(DBG_CONTROL|DBG_CONTROLMORE))
- {
- char c_ocb[SUBNETTOT_BUF], c_pcb[SUBNETTOT_BUF];
-
- subnettot(&c->spd.this.client, 0, c_ocb, sizeof(c_ocb));
- subnettot(&c->spd.that.client, 0, c_pcb, sizeof(c_pcb));
- DBG_log("find_connection: conn \"%s\"%s has compatible peers: %s->%s [pri: %ld]"
- , c->name
- , (fmt_conn_instance(c, cib), cib)
- , c_ocb, c_pcb, prio);
- }
+ if (DBGP(DBG_CONTROL|DBG_CONTROLMORE))
+ {
+ char c_ocb[SUBNETTOT_BUF], c_pcb[SUBNETTOT_BUF];
+
+ subnettot(&c->spd.this.client, 0, c_ocb, sizeof(c_ocb));
+ subnettot(&c->spd.that.client, 0, c_pcb, sizeof(c_pcb));
+ DBG_log("find_connection: conn \"%s\"%s has compatible peers: %s->%s [pri: %ld]"
+ , c->name
+ , (fmt_conn_instance(c, cib), cib)
+ , c_ocb, c_pcb, prio);
+ }
#endif /* DEBUG */
- if (best == NULL)
- {
- best = c;
- best_sr = sr;
- best_prio = prio;
- }
-
- DBG(DBG_CONTROLMORE,
- DBG_log("find_connection: "
- "comparing best \"%s\"%s [pri:%ld]{%p} (child %s) to \"%s\"%s [pri:%ld]{%p} (child %s)"
- , best->name
- , (fmt_conn_instance(best, cib), cib)
- , best_prio
- , best
- , (best->policy_next ? best->policy_next->name : "none")
- , c->name
- , (fmt_conn_instance(c, cib2), cib2)
- , prio
- , c
- , (c->policy_next ? c->policy_next->name : "none")));
-
- if (prio > best_prio)
- {
- best = c;
- best_sr = sr;
- best_prio = prio;
+ if (best == NULL)
+ {
+ best = c;
+ best_sr = sr;
+ best_prio = prio;
+ }
+
+ DBG(DBG_CONTROLMORE,
+ DBG_log("find_connection: "
+ "comparing best \"%s\"%s [pri:%ld]{%p} (child %s) to \"%s\"%s [pri:%ld]{%p} (child %s)"
+ , best->name
+ , (fmt_conn_instance(best, cib), cib)
+ , best_prio
+ , best
+ , (best->policy_next ? best->policy_next->name : "none")
+ , c->name
+ , (fmt_conn_instance(c, cib2), cib2)
+ , prio
+ , c
+ , (c->policy_next ? c->policy_next->name : "none")));
+
+ if (prio > best_prio)
+ {
+ best = c;
+ best_sr = sr;
+ best_prio = prio;
+ }
+ }
}
- }
}
- }
- if (best!= NULL && NEVER_NEGOTIATE(best->policy))
- best = NULL;
+ if (best!= NULL && NEVER_NEGOTIATE(best->policy))
+ best = NULL;
- if (srp != NULL && best != NULL)
- *srp = best_sr;
+ if (srp != NULL && best != NULL)
+ *srp = best_sr;
#ifdef DEBUG
- if (DBGP(DBG_CONTROL))
- {
- if (best)
+ if (DBGP(DBG_CONTROL))
{
- char cib[CONN_INST_BUF];
- DBG_log("find_connection: concluding with \"%s\"%s [pri:%ld]{%p} kind=%s"
- , best->name
- , (fmt_conn_instance(best, cib), cib)
- , best_prio
- , best
- , enum_name(&connection_kind_names, best->kind));
- } else {
- DBG_log("find_connection: concluding with empty");
+ if (best)
+ {
+ char cib[CONN_INST_BUF];
+ DBG_log("find_connection: concluding with \"%s\"%s [pri:%ld]{%p} kind=%s"
+ , best->name
+ , (fmt_conn_instance(best, cib), cib)
+ , best_prio
+ , best
+ , enum_name(&connection_kind_names, best->kind));
+ } else {
+ DBG_log("find_connection: concluding with empty");
+ }
}
- }
#endif /* DEBUG */
- return best;
+ return best;
}
/* Find and instantiate a connection for an outgoing Opportunistic connection.
@@ -1664,203 +1655,203 @@ find_connection_for_clients(struct spd_route **srp,
*/
struct connection *
build_outgoing_opportunistic_connection(struct gw_info *gw
- ,const ip_address *our_client
- ,const ip_address *peer_client)
+ ,const ip_address *our_client
+ ,const ip_address *peer_client)
{
- struct iface *p;
- struct connection *best = NULL;
- struct spd_route *sr, *bestsr;
- char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
-
- addrtot(our_client, 0, ocb, sizeof(ocb));
- addrtot(peer_client, 0, pcb, sizeof(pcb));
-
- passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
-
- /* We don't know his ID yet, so gw id must be an ipaddr */
- passert(gw->key != NULL);
- passert(id_is_ipaddr(&gw->gw_id));
-
- /* for each of our addresses... */
- for (p = interfaces; p != NULL; p = p->next)
- {
- /* go through those connections with our address and NO_IP as hosts
- * We cannot know what port the peer would use, so we assume
- * that it is pluto_port (makes debugging easier).
- */
- struct connection *c = find_host_pair_connections(&p->addr
- , pluto_port, (ip_address *)NULL, pluto_port);
+ struct iface *p;
+ struct connection *best = NULL;
+ struct spd_route *sr, *bestsr;
+ char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
- for (; c != NULL; c = c->hp_next)
+ addrtot(our_client, 0, ocb, sizeof(ocb));
+ addrtot(peer_client, 0, pcb, sizeof(pcb));
+
+ passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
+
+ /* We don't know his ID yet, so gw id must be an ipaddr */
+ passert(gw->key != NULL);
+ passert(id_is_ipaddr(&gw->gw_id));
+
+ /* for each of our addresses... */
+ for (p = interfaces; p != NULL; p = p->next)
{
- DBG(DBG_OPPO,
- DBG_log("checking %s", c->name));
- if (c->kind == CK_GROUP)
- {
- continue;
- }
-
- for (sr = &c->spd; best!=c && sr; sr = sr->next)
- {
- if (routed(sr->routing)
- && addrinsubnet(our_client, &sr->this.client)
- && addrinsubnet(peer_client, &sr->that.client))
+ /* go through those connections with our address and NO_IP as hosts
+ * We cannot know what port the peer would use, so we assume
+ * that it is pluto_port (makes debugging easier).
+ */
+ struct connection *c = find_host_pair_connections(&p->addr
+ , pluto_port, (ip_address *)NULL, pluto_port);
+
+ for (; c != NULL; c = c->hp_next)
{
- if (best == NULL)
- {
- best = c;
- break;
- }
-
- DBG(DBG_OPPO,
- DBG_log("comparing best %s to %s"
- , best->name, c->name));
-
- for (bestsr = &best->spd; best!=c && bestsr; bestsr=bestsr->next)
- {
- if (!subnetinsubnet(&bestsr->this.client, &sr->this.client)
- || (samesubnet(&bestsr->this.client, &sr->this.client)
- && !subnetinsubnet(&bestsr->that.client
- , &sr->that.client)))
+ DBG(DBG_OPPO,
+ DBG_log("checking %s", c->name));
+ if (c->kind == CK_GROUP)
{
- best = c;
+ continue;
+ }
+
+ for (sr = &c->spd; best!=c && sr; sr = sr->next)
+ {
+ if (routed(sr->routing)
+ && addrinsubnet(our_client, &sr->this.client)
+ && addrinsubnet(peer_client, &sr->that.client))
+ {
+ if (best == NULL)
+ {
+ best = c;
+ break;
+ }
+
+ DBG(DBG_OPPO,
+ DBG_log("comparing best %s to %s"
+ , best->name, c->name));
+
+ for (bestsr = &best->spd; best!=c && bestsr; bestsr=bestsr->next)
+ {
+ if (!subnetinsubnet(&bestsr->this.client, &sr->this.client)
+ || (samesubnet(&bestsr->this.client, &sr->this.client)
+ && !subnetinsubnet(&bestsr->that.client
+ , &sr->that.client)))
+ {
+ best = c;
+ }
+ }
+ }
}
- }
}
- }
}
- }
- if (best == NULL
- || NEVER_NEGOTIATE(best->policy)
- || (best->policy & POLICY_OPPO) == LEMPTY
- || best->kind != CK_TEMPLATE)
- return NULL;
- else
- return oppo_instantiate(best, &gw->gw_id.ip_addr, NULL, gw
- , our_client, peer_client);
+ if (best == NULL
+ || NEVER_NEGOTIATE(best->policy)
+ || (best->policy & POLICY_OPPO) == LEMPTY
+ || best->kind != CK_TEMPLATE)
+ return NULL;
+ else
+ return oppo_instantiate(best, &gw->gw_id.ip_addr, NULL, gw
+ , our_client, peer_client);
}
bool
orient(struct connection *c)
{
- struct spd_route *sr;
-
- if (!oriented(*c))
- {
- struct iface *p;
+ struct spd_route *sr;
- for (sr = &c->spd; sr; sr = sr->next)
+ if (!oriented(*c))
{
- /* Note: this loop does not stop when it finds a match:
- * it continues checking to catch any ambiguity.
- */
- for (p = interfaces; p != NULL; p = p->next)
- {
- if (p->ike_float)
- continue;
-
- for (;;)
+ struct iface *p;
+
+ for (sr = &c->spd; sr; sr = sr->next)
{
- /* check if this interface matches this end */
- if (sameaddr(&sr->this.host_addr, &p->addr)
- && (!no_klips || sr->this.host_port == pluto_port))
- {
- if (oriented(*c))
+ /* Note: this loop does not stop when it finds a match:
+ * it continues checking to catch any ambiguity.
+ */
+ for (p = interfaces; p != NULL; p = p->next)
{
- if (c->interface == p)
- loglog(RC_LOG_SERIOUS
- , "both sides of \"%s\" are our interface %s!"
- , c->name, p->rname);
- else
- loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\" (%s, %s)"
- , c->name, c->interface->rname, p->rname);
- c->interface = NULL; /* withdraw orientation */
- return FALSE;
+ if (p->ike_float)
+ continue;
+
+ for (;;)
+ {
+ /* check if this interface matches this end */
+ if (sameaddr(&sr->this.host_addr, &p->addr)
+ && (!no_klips || sr->this.host_port == pluto_port))
+ {
+ if (oriented(*c))
+ {
+ if (c->interface == p)
+ loglog(RC_LOG_SERIOUS
+ , "both sides of \"%s\" are our interface %s!"
+ , c->name, p->rname);
+ else
+ loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\" (%s, %s)"
+ , c->name, c->interface->rname, p->rname);
+ c->interface = NULL; /* withdraw orientation */
+ return FALSE;
+ }
+ c->interface = p;
+ }
+
+ /* done with this interface if it doesn't match that end */
+ if (!(sameaddr(&sr->that.host_addr, &p->addr)
+ && (!no_klips || sr->that.host_port == pluto_port)))
+ break;
+
+ /* swap ends and try again.
+ * It is a little tricky to see that this loop will stop.
+ * Only continue if the far side matches.
+ * If both sides match, there is an error-out.
+ */
+ {
+ struct end t = sr->this;
+
+ sr->this = sr->that;
+ sr->that = t;
+ }
+ }
}
- c->interface = p;
- }
-
- /* done with this interface if it doesn't match that end */
- if (!(sameaddr(&sr->that.host_addr, &p->addr)
- && (!no_klips || sr->that.host_port == pluto_port)))
- break;
-
- /* swap ends and try again.
- * It is a little tricky to see that this loop will stop.
- * Only continue if the far side matches.
- * If both sides match, there is an error-out.
- */
- {
- struct end t = sr->this;
-
- sr->this = sr->that;
- sr->that = t;
- }
}
- }
}
- }
- return oriented(*c);
+ return oriented(*c);
}
void
initiate_connection(const char *name, int whackfd)
{
- struct connection *c = con_by_name(name, TRUE);
+ struct connection *c = con_by_name(name, TRUE);
- if (c != NULL && c->ikev1)
- {
- set_cur_connection(c);
- if (!oriented(*c))
- {
- loglog(RC_ORIENT, "we have no ipsecN interface for either end of this connection");
- }
- else if (NEVER_NEGOTIATE(c->policy))
- {
- loglog(RC_INITSHUNT
- , "cannot initiate an authby=never connection");
- }
- else if (c->kind != CK_PERMANENT && !c->spd.that.allow_any)
- {
- if (isanyaddr(&c->spd.that.host_addr))
- loglog(RC_NOPEERIP, "cannot initiate connection without knowing peer IP address");
- else
- loglog(RC_WILDCARD, "cannot initiate connection with ID wildcards");
- }
- else
+ if (c != NULL && c->ikev1)
{
- /* do we have to prompt for a PIN code? */
- if (c->spd.this.sc != NULL && !c->spd.this.sc->valid && whackfd != NULL_FD)
- {
- scx_get_pin(c->spd.this.sc, whackfd);
- }
- if (c->spd.this.sc != NULL && !c->spd.this.sc->valid)
- {
- loglog(RC_NOVALIDPIN, "cannot initiate connection without valid PIN");
- }
- else
- {
-
- if (c->spd.that.allow_any)
+ set_cur_connection(c);
+ if (!oriented(*c))
+ {
+ loglog(RC_ORIENT, "we have no ipsecN interface for either end of this connection");
+ }
+ else if (NEVER_NEGOTIATE(c->policy))
+ {
+ loglog(RC_INITSHUNT
+ , "cannot initiate an authby=never connection");
+ }
+ else if (c->kind != CK_PERMANENT && !c->spd.that.allow_any)
{
- c = instantiate(c, &c->spd.that.host_addr, c->spd.that.host_port
- , &c->spd.that.id);
+ if (isanyaddr(&c->spd.that.host_addr))
+ loglog(RC_NOPEERIP, "cannot initiate connection without knowing peer IP address");
+ else
+ loglog(RC_WILDCARD, "cannot initiate connection with ID wildcards");
}
+ else
+ {
+ /* do we have to prompt for a PIN code? */
+ if (c->spd.this.sc != NULL && !c->spd.this.sc->valid && whackfd != NULL_FD)
+ {
+ scx_get_pin(c->spd.this.sc, whackfd);
+ }
+ if (c->spd.this.sc != NULL && !c->spd.this.sc->valid)
+ {
+ loglog(RC_NOVALIDPIN, "cannot initiate connection without valid PIN");
+ }
+ else
+ {
- /* We will only request an IPsec SA if policy isn't empty
- * (ignoring Main Mode items).
- * This is a fudge, but not yet important.
- * If we are to proceed asynchronously, whackfd will be NULL_FD.
- */
- c->policy |= POLICY_UP;
- ipsecdoi_initiate(whackfd, c, c->policy, 1, SOS_NOBODY);
- whackfd = NULL_FD; /* protect from close */
- }
+ if (c->spd.that.allow_any)
+ {
+ c = instantiate(c, &c->spd.that.host_addr, c->spd.that.host_port
+ , &c->spd.that.id);
+ }
+
+ /* We will only request an IPsec SA if policy isn't empty
+ * (ignoring Main Mode items).
+ * This is a fudge, but not yet important.
+ * If we are to proceed asynchronously, whackfd will be NULL_FD.
+ */
+ c->policy |= POLICY_UP;
+ ipsecdoi_initiate(whackfd, c, c->policy, 1, SOS_NOBODY);
+ whackfd = NULL_FD; /* protect from close */
+ }
+ }
+ reset_cur_connection();
}
- reset_cur_connection();
- }
- close_any(whackfd);
+ close_any(whackfd);
}
/* (Possibly) Opportunistic Initiation:
@@ -1874,10 +1865,10 @@ initiate_connection(const char *name, int whackfd)
* Most of the code will be restarted if an ADNS request is made
* to discover the gateway. The only difference between the first
* and second entry is whether gateways_from_dns is NULL or not.
- * initiate_opportunistic: initial entrypoint
- * continue_oppo: where we pickup when ADNS result arrives
- * initiate_opportunistic_body: main body shared by above routines
- * cannot_oppo: a helper function to log a diagnostic
+ * initiate_opportunistic: initial entrypoint
+ * continue_oppo: where we pickup when ADNS result arrives
+ * initiate_opportunistic_body: main body shared by above routines
+ * cannot_oppo: a helper function to log a diagnostic
* This structure repeats a lot of code when the ADNS result arrives.
* This seems like a waste, but anything learned the first time through
* may no longer be true!
@@ -1887,174 +1878,174 @@ initiate_connection(const char *name, int whackfd)
*/
enum find_oppo_step {
- fos_start,
- fos_myid_ip_txt,
- fos_myid_hostname_txt,
- fos_myid_ip_key,
- fos_myid_hostname_key,
- fos_our_client,
- fos_our_txt,
+ fos_start,
+ fos_myid_ip_txt,
+ fos_myid_hostname_txt,
+ fos_myid_ip_key,
+ fos_myid_hostname_key,
+ fos_our_client,
+ fos_our_txt,
#ifdef USE_KEYRR
- fos_our_key,
+ fos_our_key,
#endif /* USE_KEYRR */
- fos_his_client,
- fos_done
+ fos_his_client,
+ fos_done
};
#ifdef DEBUG
static const char *const oppo_step_name[] = {
- "fos_start",
- "fos_myid_ip_txt",
- "fos_myid_hostname_txt",
- "fos_myid_ip_key",
- "fos_myid_hostname_key",
- "fos_our_client",
- "fos_our_txt",
+ "fos_start",
+ "fos_myid_ip_txt",
+ "fos_myid_hostname_txt",
+ "fos_myid_ip_key",
+ "fos_myid_hostname_key",
+ "fos_our_client",
+ "fos_our_txt",
#ifdef USE_KEYRR
- "fos_our_key",
+ "fos_our_key",
#endif /* USE_KEYRR */
- "fos_his_client",
- "fos_done"
+ "fos_his_client",
+ "fos_done"
};
#endif /* DEBUG */
struct find_oppo_bundle {
- enum find_oppo_step step;
- err_t want;
- bool failure_ok; /* if true, continue_oppo should not die on DNS failure */
- ip_address our_client; /* not pointer! */
- ip_address peer_client;
- int transport_proto;
- bool held;
- policy_prio_t policy_prio;
- ipsec_spi_t failure_shunt; /* in host order! 0 for delete. */
- int whackfd;
+ enum find_oppo_step step;
+ err_t want;
+ bool failure_ok; /* if true, continue_oppo should not die on DNS failure */
+ ip_address our_client; /* not pointer! */
+ ip_address peer_client;
+ int transport_proto;
+ bool held;
+ policy_prio_t policy_prio;
+ ipsec_spi_t failure_shunt; /* in host order! 0 for delete. */
+ int whackfd;
};
struct find_oppo_continuation {
- struct adns_continuation ac; /* common prefix */
- struct find_oppo_bundle b;
+ struct adns_continuation ac; /* common prefix */
+ struct find_oppo_bundle b;
};
static void
cannot_oppo(struct connection *c
- , struct find_oppo_bundle *b
- , err_t ugh)
+ , struct find_oppo_bundle *b
+ , err_t ugh)
{
- char pcb[ADDRTOT_BUF];
- char ocb[ADDRTOT_BUF];
+ char pcb[ADDRTOT_BUF];
+ char ocb[ADDRTOT_BUF];
- addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
- addrtot(&b->our_client, 0, ocb, sizeof(ocb));
+ addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
+ addrtot(&b->our_client, 0, ocb, sizeof(ocb));
- DBG(DBG_DNS | DBG_OPPO, DBG_log("Can't Opportunistically initiate for %s to %s: %s"
- , ocb, pcb, ugh));
+ DBG(DBG_DNS | DBG_OPPO, DBG_log("Can't Opportunistically initiate for %s to %s: %s"
+ , ocb, pcb, ugh));
- whack_log(RC_OPPOFAILURE
- , "Can't Opportunistically initiate for %s to %s: %s"
- , ocb, pcb, ugh);
+ whack_log(RC_OPPOFAILURE
+ , "Can't Opportunistically initiate for %s to %s: %s"
+ , ocb, pcb, ugh);
- if (c != NULL && c->policy_next != NULL)
- {
- /* there is some policy that comes afterwards */
- struct spd_route *shunt_spd;
- struct connection *nc = c->policy_next;
- struct state *st;
+ if (c != NULL && c->policy_next != NULL)
+ {
+ /* there is some policy that comes afterwards */
+ struct spd_route *shunt_spd;
+ struct connection *nc = c->policy_next;
+ struct state *st;
- passert(c->kind == CK_TEMPLATE);
- passert(c->policy_next->kind == CK_PERMANENT);
+ passert(c->kind == CK_TEMPLATE);
+ passert(c->policy_next->kind == CK_PERMANENT);
- DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt"
- , ocb, pcb, c->policy_next->name));
+ DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt"
+ , ocb, pcb, c->policy_next->name));
- /*
- * okay, here we need add to the "next" policy, which is ought
- * to be an instance.
- * We will add another entry to the spd_route list for the specific
- * situation that we have.
- */
+ /*
+ * okay, here we need add to the "next" policy, which is ought
+ * to be an instance.
+ * We will add another entry to the spd_route list for the specific
+ * situation that we have.
+ */
- shunt_spd = clone_thing(nc->spd, "shunt eroute policy");
+ shunt_spd = clone_thing(nc->spd);
- shunt_spd->next = nc->spd.next;
- nc->spd.next = shunt_spd;
+ shunt_spd->next = nc->spd.next;
+ nc->spd.next = shunt_spd;
- happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client));
+ happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client));
- if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr))
- shunt_spd->that.has_client = FALSE;
+ if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr))
+ shunt_spd->that.has_client = FALSE;
- /*
- * override the tunnel destination with the one from the secondaried
- * policy
- */
- shunt_spd->that.host_addr = nc->spd.that.host_addr;
+ /*
+ * override the tunnel destination with the one from the secondaried
+ * policy
+ */
+ shunt_spd->that.host_addr = nc->spd.that.host_addr;
- /* now, lookup the state, and poke it up.
- */
+ /* now, lookup the state, and poke it up.
+ */
- st = state_with_serialno(nc->newest_ipsec_sa);
+ st = state_with_serialno(nc->newest_ipsec_sa);
- /* XXX what to do if the IPSEC SA has died? */
- passert(st != NULL);
+ /* XXX what to do if the IPSEC SA has died? */
+ passert(st != NULL);
- /* link the new connection instance to the state's list of
- * connections
- */
+ /* link the new connection instance to the state's list of
+ * connections
+ */
- DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s"
- , nc->newest_ipsec_sa
- , ocb, pcb));
+ DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s"
+ , nc->newest_ipsec_sa
+ , ocb, pcb));
#ifdef DEBUG
- if (DBGP(DBG_OPPO | DBG_CONTROLMORE))
- {
- char state_buf[LOG_WIDTH];
- char state_buf2[LOG_WIDTH];
- time_t n = now();
-
- fmt_state(FALSE, st, n
- , state_buf, sizeof(state_buf)
- , state_buf2, sizeof(state_buf2));
- DBG_log("cannot_oppo, failure SA1: %s", state_buf);
- DBG_log("cannot_oppo, failure SA2: %s", state_buf2);
- }
+ if (DBGP(DBG_OPPO | DBG_CONTROLMORE))
+ {
+ char state_buf[LOG_WIDTH];
+ char state_buf2[LOG_WIDTH];
+ time_t n = now();
+
+ fmt_state(FALSE, st, n
+ , state_buf, sizeof(state_buf)
+ , state_buf2, sizeof(state_buf2));
+ DBG_log("cannot_oppo, failure SA1: %s", state_buf);
+ DBG_log("cannot_oppo, failure SA2: %s", state_buf2);
+ }
#endif /* DEBUG */
- if (!route_and_eroute(c, shunt_spd, st))
- {
- whack_log(RC_OPPOFAILURE
- , "failed to instantiate shunt policy %s for %s to %s"
- , c->name
- , ocb, pcb);
+ if (!route_and_eroute(c, shunt_spd, st))
+ {
+ whack_log(RC_OPPOFAILURE
+ , "failed to instantiate shunt policy %s for %s to %s"
+ , c->name
+ , ocb, pcb);
+ }
+ return;
}
- return;
- }
#ifdef KLIPS
- if (b->held)
- {
- /* Replace HOLD with b->failure_shunt.
- * If no b->failure_shunt specified, use SPI_PASS -- THIS MAY CHANGE.
- */
- if (b->failure_shunt == 0)
+ if (b->held)
{
- DBG(DBG_OPPO, DBG_log("no explicit failure shunt for %s to %s; installing %%pass"
- , ocb, pcb));
- }
+ /* Replace HOLD with b->failure_shunt.
+ * If no b->failure_shunt specified, use SPI_PASS -- THIS MAY CHANGE.
+ */
+ if (b->failure_shunt == 0)
+ {
+ DBG(DBG_OPPO, DBG_log("no explicit failure shunt for %s to %s; installing %%pass"
+ , ocb, pcb));
+ }
- (void) replace_bare_shunt(&b->our_client, &b->peer_client
- , b->policy_prio
- , b->failure_shunt
- , b->failure_shunt != 0
- , b->transport_proto
- , ugh);
- }
+ (void) replace_bare_shunt(&b->our_client, &b->peer_client
+ , b->policy_prio
+ , b->failure_shunt
+ , b->failure_shunt != 0
+ , b->transport_proto
+ , ugh);
+ }
#endif
}
static void initiate_opportunistic_body(struct find_oppo_bundle *b
- , struct adns_continuation *ac, err_t ac_ugh); /* forward */
+ , struct adns_continuation *ac, err_t ac_ugh); /* forward */
void
initiate_opportunistic(const ip_address *our_client
@@ -2063,93 +2054,93 @@ initiate_opportunistic(const ip_address *our_client
, bool held
, int whackfd)
{
- struct find_oppo_bundle b;
-
- b.want = (whackfd == NULL_FD ? "whack" : "acquire");
- b.failure_ok = FALSE;
- b.our_client = *our_client;
- b.peer_client = *peer_client;
- b.transport_proto = transport_proto;
- b.held = held;
- b.policy_prio = BOTTOM_PRIO;
- b.failure_shunt = 0;
- b.whackfd = whackfd;
- b.step = fos_start;
- initiate_opportunistic_body(&b, NULL, NULL);
+ struct find_oppo_bundle b;
+
+ b.want = (whackfd == NULL_FD ? "whack" : "acquire");
+ b.failure_ok = FALSE;
+ b.our_client = *our_client;
+ b.peer_client = *peer_client;
+ b.transport_proto = transport_proto;
+ b.held = held;
+ b.policy_prio = BOTTOM_PRIO;
+ b.failure_shunt = 0;
+ b.whackfd = whackfd;
+ b.step = fos_start;
+ initiate_opportunistic_body(&b, NULL, NULL);
}
static void
continue_oppo(struct adns_continuation *acr, err_t ugh)
{
- struct find_oppo_continuation *cr = (void *)acr; /* inherit, damn you! */
- struct connection *c;
- bool was_held = cr->b.held;
- int whackfd = cr->b.whackfd;
+ struct find_oppo_continuation *cr = (void *)acr; /* inherit, damn you! */
+ struct connection *c;
+ bool was_held = cr->b.held;
+ int whackfd = cr->b.whackfd;
- /* note: cr->id has no resources; cr->sgw_id is id_none:
- * neither need freeing.
- */
- whack_log_fd = whackfd;
+ /* note: cr->id has no resources; cr->sgw_id is ID_ANY:
+ * neither need freeing.
+ */
+ whack_log_fd = whackfd;
#ifdef KLIPS
- /* Discover and record whether %hold has gone away.
- * This could have happened while we were awaiting DNS.
- * We must check BEFORE any call to cannot_oppo.
- */
- if (was_held)
- cr->b.held = has_bare_hold(&cr->b.our_client, &cr->b.peer_client
- , cr->b.transport_proto);
+ /* Discover and record whether %hold has gone away.
+ * This could have happened while we were awaiting DNS.
+ * We must check BEFORE any call to cannot_oppo.
+ */
+ if (was_held)
+ cr->b.held = has_bare_hold(&cr->b.our_client, &cr->b.peer_client
+ , cr->b.transport_proto);
#endif
#ifdef DEBUG
- /* if we're going to ignore the error, at least note it in debugging log */
- if (cr->b.failure_ok && ugh != NULL)
- {
- DBG(DBG_CONTROL | DBG_DNS,
- {
+ /* if we're going to ignore the error, at least note it in debugging log */
+ if (cr->b.failure_ok && ugh != NULL)
+ {
+ DBG(DBG_CONTROL | DBG_DNS,
+ {
+ char ocb[ADDRTOT_BUF];
+ char pcb[ADDRTOT_BUF];
+
+ addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb));
+ addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb));
+ DBG_log("continuing from failed DNS lookup for %s, %s to %s: %s"
+ , cr->b.want, ocb, pcb, ugh);
+ });
+ }
+#endif
+
+ if (!cr->b.failure_ok && ugh != NULL)
+ {
+ c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client
+ , cr->b.transport_proto);
+ cannot_oppo(c, &cr->b
+ , builddiag("%s: %s", cr->b.want, ugh));
+ }
+ else if (was_held && !cr->b.held)
+ {
+ /* was_held indicates we were started due to a %trap firing
+ * (as opposed to a "whack --oppohere --oppothere").
+ * Since the %hold has gone, we can assume that somebody else
+ * has beaten us to the punch. We can go home. But lets log it.
+ */
char ocb[ADDRTOT_BUF];
char pcb[ADDRTOT_BUF];
addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb));
addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb));
- DBG_log("continuing from failed DNS lookup for %s, %s to %s: %s"
- , cr->b.want, ocb, pcb, ugh);
- });
- }
-#endif
- if (!cr->b.failure_ok && ugh != NULL)
- {
- c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client
- , cr->b.transport_proto);
- cannot_oppo(c, &cr->b
- , builddiag("%s: %s", cr->b.want, ugh));
- }
- else if (was_held && !cr->b.held)
- {
- /* was_held indicates we were started due to a %trap firing
- * (as opposed to a "whack --oppohere --oppothere").
- * Since the %hold has gone, we can assume that somebody else
- * has beaten us to the punch. We can go home. But lets log it.
- */
- char ocb[ADDRTOT_BUF];
- char pcb[ADDRTOT_BUF];
+ loglog(RC_COMMENT
+ , "%%hold otherwise handled during DNS lookup for Opportunistic Initiation for %s to %s"
+ , ocb, pcb);
+ }
+ else
+ {
+ initiate_opportunistic_body(&cr->b, &cr->ac, ugh);
+ whackfd = NULL_FD; /* was handed off */
+ }
- addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb));
- addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb));
-
- loglog(RC_COMMENT
- , "%%hold otherwise handled during DNS lookup for Opportunistic Initiation for %s to %s"
- , ocb, pcb);
- }
- else
- {
- initiate_opportunistic_body(&cr->b, &cr->ac, ugh);
- whackfd = NULL_FD; /* was handed off */
- }
-
- whack_log_fd = NULL_FD;
- close_any(whackfd);
+ whack_log_fd = NULL_FD;
+ close_any(whackfd);
}
#ifdef USE_KEYRR
@@ -2158,110 +2149,112 @@ check_key_recs(enum myid_state try_state
, const struct connection *c
, struct adns_continuation *ac)
{
- /* Check if KEY lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- enum myid_state old_myid_state = myid_state;
- const struct RSA_private_key *our_RSA_pri;
- err_t ugh = NULL;
-
- myid_state = try_state;
-
- if (old_myid_state != myid_state
- && old_myid_state == MYID_SPECIFIED)
- {
- ugh = "%myid was specified while we were guessing";
- }
- else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!same_id(&ac->id, &c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
+ /* Check if KEY lookup yielded good results.
+ * Looking up based on our ID. Used if
+ * client is ourself, or if TXT had no public key.
+ * Note: if c is different this time, there is
+ * a chance that we did the wrong query.
+ * If so, treat as a kind of failure.
*/
- pubkey_list_t *kr;
+ enum myid_state old_myid_state = myid_state;
+ private_key_t *private;
+ err_t ugh = NULL;
- ugh = "no KEY RR found for us";
- for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next)
+ myid_state = try_state;
+
+ if (old_myid_state != myid_state && old_myid_state == MYID_SPECIFIED)
{
- ugh = "all our KEY RRs have the wrong public key";
- if (kr->key->alg == PUBKEY_ALG_RSA
- && same_RSA_public_key(&our_RSA_pri->pub, &kr->key->u.rsa))
- {
- ugh = NULL; /* good! */
- break;
- }
+ ugh = "%myid was specified while we were guessing";
+ }
+ else if ((private = get_private_key(c)) == NULL)
+ {
+ ugh = "we don't know our own RSA key";
}
- }
- if (ugh != NULL)
- myid_state = old_myid_state;
- return ugh;
+ else if (!same_id(&ac->id, &c->spd.this.id))
+ {
+ ugh = "our ID changed underfoot";
+ }
+ else
+ {
+ /* Similar to code in RSA_check_signature
+ * for checking the other side.
+ */
+ pubkey_list_t *kr;
+
+ ugh = "no KEY RR found for us";
+ for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next)
+ {
+ ugh = "all our KEY RRs have the wrong public key";
+ if (kr->key->alg == PUBKEY_ALG_RSA
+ && private->belongs_to(private, &kr->key->public_key))
+ {
+ ugh = NULL; /* good! */
+ break;
+ }
+ }
+ }
+ if (ugh != NULL)
+ myid_state = old_myid_state;
+ return ugh;
}
#endif /* USE_KEYRR */
-static err_t
-check_txt_recs(enum myid_state try_state
-, const struct connection *c
-, struct adns_continuation *ac)
+static err_t check_txt_recs(enum myid_state try_state,
+ const struct connection *c,
+ struct adns_continuation *ac)
{
- /* Check if TXT lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- enum myid_state old_myid_state = myid_state;
- const struct RSA_private_key *our_RSA_pri;
- err_t ugh = NULL;
-
- myid_state = try_state;
-
- if (old_myid_state != myid_state
- && old_myid_state == MYID_SPECIFIED)
- {
- ugh = "%myid was specified while we were guessing";
- }
- else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!same_id(&ac->id, &c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
+ /* Check if TXT lookup yielded good results.
+ * Looking up based on our ID. Used if
+ * client is ourself, or if TXT had no public key.
+ * Note: if c is different this time, there is
+ * a chance that we did the wrong query.
+ * If so, treat as a kind of failure.
*/
- struct gw_info *gwp;
+ enum myid_state old_myid_state = myid_state;
+ private_key_t *private;
+ err_t ugh = NULL;
+
+ myid_state = try_state;
- ugh = "no TXT RR found for us";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ if (old_myid_state != myid_state
+ && old_myid_state == MYID_SPECIFIED)
{
- ugh = "all our TXT RRs have the wrong public key";
- if (gwp->key->alg == PUBKEY_ALG_RSA
- && same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa))
- {
- ugh = NULL; /* good! */
- break;
- }
+ ugh = "%myid was specified while we were guessing";
+ }
+ else if ((private = get_private_key(c)) == NULL)
+ {
+ ugh = "we don't know our own RSA key";
}
- }
- if (ugh != NULL)
- myid_state = old_myid_state;
- return ugh;
+ else if (!same_id(&ac->id, &c->spd.this.id))
+ {
+ ugh = "our ID changed underfoot";
+ }
+ else
+ {
+ /* Similar to code in RSA_check_signature
+ * for checking the other side.
+ */
+ struct gw_info *gwp;
+
+ ugh = "no TXT RR found for us";
+ for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
+ public_key_t *pub_key = gwp->key->public_key;
+
+ ugh = "all our TXT RRs have the wrong public key";
+ if (pub_key->get_type(pub_key) == KEY_RSA &&
+ private->belongs_to(private, pub_key))
+ {
+ ugh = NULL; /* good! */
+ break;
+ }
+ }
+ }
+ if (ugh != NULL)
+ {
+ myid_state = old_myid_state;
+ }
+ return ugh;
}
@@ -2271,776 +2264,775 @@ initiate_opportunistic_body(struct find_oppo_bundle *b
, struct adns_continuation *ac
, err_t ac_ugh)
{
- struct connection *c;
- struct spd_route *sr;
+ struct connection *c;
+ struct spd_route *sr;
- /* What connection shall we use?
- * First try for one that explicitly handles the clients.
- */
- DBG(DBG_CONTROL,
- {
- char ours[ADDRTOT_BUF];
- char his[ADDRTOT_BUF];
- int ourport;
- int hisport;
-
- addrtot(&b->our_client, 0, ours, sizeof(ours));
- addrtot(&b->peer_client, 0, his, sizeof(his));
- ourport = ntohs(portof(&b->our_client));
- hisport = ntohs(portof(&b->peer_client));
- DBG_log("initiate on demand from %s:%d to %s:%d proto=%d state: %s because: %s"
- , ours, ourport, his, hisport, b->transport_proto
- , oppo_step_name[b->step], b->want);
- });
- if (isanyaddr(&b->our_client) || isanyaddr(&b->peer_client))
- {
- cannot_oppo(NULL, b, "impossible IP address");
- }
- else if ((c = find_connection_for_clients(&sr
- , &b->our_client
- , &b->peer_client
- , b->transport_proto)) == NULL)
- {
- /* No connection explicitly handles the clients and there
- * are no Opportunistic connections -- whine and give up.
- * The failure policy cannot be gotten from a connection; we pick %pass.
- */
- cannot_oppo(NULL, b, "no routed Opportunistic template covers this pair");
- }
- else if (c->kind != CK_TEMPLATE)
- {
- /* We've found a connection that can serve.
- * Do we have to initiate it?
- * Not if there is currently an IPSEC SA.
- * But if there is an IPSEC SA, then KLIPS would not
- * have generated the acquire. So we assume that there isn't one.
- * This may be redundant if a non-opportunistic
- * negotiation is already being attempted.
+ /* What connection shall we use?
+ * First try for one that explicitly handles the clients.
*/
-
- /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */
-
- if(c->kind == CK_INSTANCE)
+ DBG(DBG_CONTROL,
+ {
+ char ours[ADDRTOT_BUF];
+ char his[ADDRTOT_BUF];
+ int ourport;
+ int hisport;
+
+ addrtot(&b->our_client, 0, ours, sizeof(ours));
+ addrtot(&b->peer_client, 0, his, sizeof(his));
+ ourport = ntohs(portof(&b->our_client));
+ hisport = ntohs(portof(&b->peer_client));
+ DBG_log("initiate on demand from %s:%d to %s:%d proto=%d state: %s because: %s"
+ , ours, ourport, his, hisport, b->transport_proto
+ , oppo_step_name[b->step], b->want);
+ });
+ if (isanyaddr(&b->our_client) || isanyaddr(&b->peer_client))
{
- char cib[CONN_INST_BUF];
- /* there is already an instance being negotiated, no nothing */
- DBG(DBG_CONTROL, DBG_log("found existing instance \"%s\"%s, rekeying it"
- , c->name
- , (fmt_conn_instance(c, cib), cib)));
- /* XXX-mcr - return; */
+ cannot_oppo(NULL, b, "impossible IP address");
}
-
- /* otherwise, there is some kind of static conn that can handle
- * this connection, so we initiate it */
-
-#ifdef KLIPS
- if (b->held)
+ else if ((c = find_connection_for_clients(&sr
+ , &b->our_client
+ , &b->peer_client
+ , b->transport_proto)) == NULL)
{
- /* what should we do on failure? */
- (void) assign_hold(c, sr, b->transport_proto, &b->our_client, &b->peer_client);
+ /* No connection explicitly handles the clients and there
+ * are no Opportunistic connections -- whine and give up.
+ * The failure policy cannot be gotten from a connection; we pick %pass.
+ */
+ cannot_oppo(NULL, b, "no routed Opportunistic template covers this pair");
}
-#endif
- ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY);
- b->whackfd = NULL_FD; /* protect from close */
- }
- else
- {
- /* We are handling an opportunistic situation.
- * This involves several DNS lookup steps that require suspension.
- * Note: many facts might change while we're suspended.
- * Here be dragons.
- *
- * The first chunk of code handles the result of the previous
- * DNS query (if any). It also selects the kind of the next step.
- * The second chunk initiates the next DNS query (if any).
- */
- enum find_oppo_step next_step = fos_myid_ip_txt;
- err_t ugh = ac_ugh;
- char mycredentialstr[BUF_LEN];
- char cib[CONN_INST_BUF];
-
- DBG(DBG_CONTROL, DBG_log("creating new instance from \"%s\"%s"
- , c->name
- , (fmt_conn_instance(c, cib), cib)));
-
-
- idtoa(&sr->this.id, mycredentialstr, sizeof(mycredentialstr));
-
- passert(c->policy & POLICY_OPPO); /* can't initiate Road Warrior connections */
-
- /* handle any DNS answer; select next step */
-
- switch (b->step)
+ else if (c->kind != CK_TEMPLATE)
{
- case fos_start:
- /* just starting out: select first query step */
- next_step = fos_myid_ip_txt;
- break;
-
- case fos_myid_ip_txt: /* TXT for our default IP address as %myid */
- ugh = check_txt_recs(MYID_IP, c, ac);
- if (ugh != NULL)
- {
- /* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our IP (%s:TXT) as identity: %s"
- , myid_str[MYID_IP]
- , ugh));
- if (!logged_myid_ip_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "can not use our IP (%s:TXT) as identity: %s"
- , myid_str[MYID_IP]
- , ugh);
- logged_myid_ip_txt_warning = TRUE;
- }
-
- next_step = fos_myid_hostname_txt;
- ugh = NULL; /* failure can be recovered from */
- }
- else
- {
- /* we can use our IP as OE identity for initiation */
- if (!logged_myid_ip_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "using our IP (%s:TXT) as identity!"
- , myid_str[MYID_IP]);
- logged_myid_ip_txt_warning = TRUE;
- }
+ /* We've found a connection that can serve.
+ * Do we have to initiate it?
+ * Not if there is currently an IPSEC SA.
+ * But if there is an IPSEC SA, then KLIPS would not
+ * have generated the acquire. So we assume that there isn't one.
+ * This may be redundant if a non-opportunistic
+ * negotiation is already being attempted.
+ */
- next_step = fos_our_client;
- }
- break;
-
- case fos_myid_hostname_txt: /* TXT for our hostname as %myid */
- ugh = check_txt_recs(MYID_HOSTNAME, c, ac);
- if (ugh != NULL)
- {
- /* cannot use our hostname as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:TXT) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh));
- if (!logged_myid_fqdn_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "can not use our hostname (%s:TXT) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh);
- logged_myid_fqdn_txt_warning = TRUE;
- }
-#ifdef USE_KEYRR
- next_step = fos_myid_ip_key;
- ugh = NULL; /* failure can be recovered from */
-#endif
- }
- else
- {
- /* we can use our hostname as OE identity for initiation */
- if (!logged_myid_fqdn_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "using our hostname (%s:TXT) as identity!"
- , myid_str[MYID_HOSTNAME]);
- logged_myid_fqdn_txt_warning = TRUE;
- }
- next_step = fos_our_client;
- }
- break;
+ /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */
-#ifdef USE_KEYRR
- case fos_myid_ip_key: /* KEY for our default IP address as %myid */
- ugh = check_key_recs(MYID_IP, c, ac);
- if (ugh != NULL)
- {
- /* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our IP (%s:KEY) as identity: %s"
- , myid_str[MYID_IP]
- , ugh));
- if (!logged_myid_ip_key_warning)
+ if(c->kind == CK_INSTANCE)
{
- loglog(RC_LOG_SERIOUS
- , "can not use our IP (%s:KEY) as identity: %s"
- , myid_str[MYID_IP]
- , ugh);
- logged_myid_ip_key_warning = TRUE;
+ char cib[CONN_INST_BUF];
+ /* there is already an instance being negotiated, no nothing */
+ DBG(DBG_CONTROL, DBG_log("found existing instance \"%s\"%s, rekeying it"
+ , c->name
+ , (fmt_conn_instance(c, cib), cib)));
+ /* XXX-mcr - return; */
}
- next_step = fos_myid_hostname_key;
- ugh = NULL; /* failure can be recovered from */
- }
- else
- {
- /* we can use our IP as OE identity for initiation */
- if (!logged_myid_ip_key_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "using our IP (%s:KEY) as identity!"
- , myid_str[MYID_IP]);
- logged_myid_ip_key_warning = TRUE;
- }
- next_step = fos_our_client;
- }
- break;
-
- case fos_myid_hostname_key: /* KEY for our hostname as %myid */
- ugh = check_key_recs(MYID_HOSTNAME, c, ac);
- if (ugh != NULL)
- {
- /* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:KEY) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh));
- if (!logged_myid_fqdn_key_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "can not use our hostname (%s:KEY) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh);
- logged_myid_fqdn_key_warning = TRUE;
- }
+ /* otherwise, there is some kind of static conn that can handle
+ * this connection, so we initiate it */
- next_step = fos_myid_hostname_key;
- ugh = NULL; /* failure can be recovered from */
- }
- else
- {
- /* we can use our IP as OE identity for initiation */
- if (!logged_myid_fqdn_key_warning)
+#ifdef KLIPS
+ if (b->held)
{
- loglog(RC_LOG_SERIOUS
- , "using our hostname (%s:KEY) as identity!"
- , myid_str[MYID_HOSTNAME]);
- logged_myid_fqdn_key_warning = TRUE;
+ /* what should we do on failure? */
+ (void) assign_hold(c, sr, b->transport_proto, &b->our_client, &b->peer_client);
}
- next_step = fos_our_client;
- }
- break;
#endif
-
- case fos_our_client: /* TXT for our client */
- {
- /* Our client is not us: we must check the TXT records.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
+ ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY);
+ b->whackfd = NULL_FD; /* protect from close */
+ }
+ else
+ {
+ /* We are handling an opportunistic situation.
+ * This involves several DNS lookup steps that require suspension.
+ * Note: many facts might change while we're suspended.
+ * Here be dragons.
+ *
+ * The first chunk of code handles the result of the previous
+ * DNS query (if any). It also selects the kind of the next step.
+ * The second chunk initiates the next DNS query (if any).
*/
- const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c);
+ enum find_oppo_step next_step = fos_myid_ip_txt;
+ err_t ugh = ac_ugh;
+ char mycredentialstr[BUF_LEN];
+ char cib[CONN_INST_BUF];
- next_step = fos_his_client; /* normal situation */
+ DBG(DBG_CONTROL, DBG_log("creating new instance from \"%s\"%s"
+ , c->name
+ , (fmt_conn_instance(c, cib), cib)));
+
- passert(sr != NULL);
+ idtoa(&sr->this.id, mycredentialstr, sizeof(mycredentialstr));
- if (our_RSA_pri == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (sameaddr(&sr->this.host_addr, &b->our_client))
- {
- /* this wasn't true when we started -- bail */
- ugh = "our IP address changed underfoot";
- }
- else if (!same_id(&ac->sgw_id, &sr->this.id))
- {
- /* this wasn't true when we started -- bail */
- ugh = "our ID changed underfoot";
- }
- else
+ passert(c->policy & POLICY_OPPO); /* can't initiate Road Warrior connections */
+
+ /* handle any DNS answer; select next step */
+
+ switch (b->step)
{
- /* Similar to code in quick_inI1_outR1_tail
- * for checking the other side.
- */
- struct gw_info *gwp;
-
- ugh = "no TXT RR for our client delegates us";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- passert(same_id(&gwp->gw_id, &sr->this.id));
-
- ugh = "TXT RR for our client has wrong key";
- /* If there is a key from the TXT record,
- * we count it as a win if we match the key.
- * If there was no key, we have a tentative win:
- * we need to check our KEY record to be sure.
- */
- if (!gwp->gw_key_present)
+ case fos_start:
+ /* just starting out: select first query step */
+ next_step = fos_myid_ip_txt;
+ break;
+
+ case fos_myid_ip_txt: /* TXT for our default IP address as %myid */
+ ugh = check_txt_recs(MYID_IP, c, ac);
+ if (ugh != NULL)
{
- /* Success, but the TXT had no key
- * so we must check our our own KEY records.
- */
- next_step = fos_our_txt;
- ugh = NULL; /* good! */
- break;
+ /* cannot use our IP as OE identitiy for initiation */
+ DBG(DBG_OPPO, DBG_log("can not use our IP (%s:TXT) as identity: %s"
+ , myid_str[MYID_IP]
+ , ugh));
+ if (!logged_myid_ip_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "can not use our IP (%s:TXT) as identity: %s"
+ , myid_str[MYID_IP]
+ , ugh);
+ logged_myid_ip_txt_warning = TRUE;
+ }
+
+ next_step = fos_myid_hostname_txt;
+ ugh = NULL; /* failure can be recovered from */
}
- if (same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa))
+ else
{
- ugh = NULL; /* good! */
- break;
+ /* we can use our IP as OE identity for initiation */
+ if (!logged_myid_ip_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "using our IP (%s:TXT) as identity!"
+ , myid_str[MYID_IP]);
+ logged_myid_ip_txt_warning = TRUE;
+ }
+
+ next_step = fos_our_client;
}
- }
- }
- }
- break;
-
- case fos_our_txt: /* TXT for us */
- {
- /* Check if TXT lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c);
-
- next_step = fos_his_client; /* unless we decide to look for KEY RR */
+ break;
- if (our_RSA_pri == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!same_id(&ac->id, &c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
- */
- struct gw_info *gwp;
-
- ugh = "no TXT RR for us";
- for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
- {
- passert(same_id(&gwp->gw_id, &sr->this.id));
-
- ugh = "TXT RR for us has wrong key";
- if (gwp->gw_key_present
- && same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa))
+ case fos_myid_hostname_txt: /* TXT for our hostname as %myid */
+ ugh = check_txt_recs(MYID_HOSTNAME, c, ac);
+ if (ugh != NULL)
{
- DBG(DBG_CONTROL,
- DBG_log("initiate on demand found TXT with right public key at: %s"
- , mycredentialstr));
- ugh = NULL;
- break;
- }
- }
+ /* cannot use our hostname as OE identitiy for initiation */
+ DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:TXT) as identity: %s"
+ , myid_str[MYID_HOSTNAME]
+ , ugh));
+ if (!logged_myid_fqdn_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "can not use our hostname (%s:TXT) as identity: %s"
+ , myid_str[MYID_HOSTNAME]
+ , ugh);
+ logged_myid_fqdn_txt_warning = TRUE;
+ }
#ifdef USE_KEYRR
- if (ugh != NULL)
- {
- /* if no TXT with right key, try KEY */
- DBG(DBG_CONTROL,
- DBG_log("will try for KEY RR since initiate on demand found %s: %s"
- , ugh, mycredentialstr));
- next_step = fos_our_key;
- ugh = NULL;
- }
+ next_step = fos_myid_ip_key;
+ ugh = NULL; /* failure can be recovered from */
#endif
- }
- }
- break;
+ }
+ else
+ {
+ /* we can use our hostname as OE identity for initiation */
+ if (!logged_myid_fqdn_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "using our hostname (%s:TXT) as identity!"
+ , myid_str[MYID_HOSTNAME]);
+ logged_myid_fqdn_txt_warning = TRUE;
+ }
+ next_step = fos_our_client;
+ }
+ break;
#ifdef USE_KEYRR
- case fos_our_key: /* KEY for us */
- {
- /* Check if KEY lookup yielded good results.
- * Looking up based on our ID. Used if
- * client is ourself, or if TXT had no public key.
- * Note: if c is different this time, there is
- * a chance that we did the wrong query.
- * If so, treat as a kind of failure.
- */
- const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c);
+ case fos_myid_ip_key: /* KEY for our default IP address as %myid */
+ ugh = check_key_recs(MYID_IP, c, ac);
+ if (ugh != NULL)
+ {
+ /* cannot use our IP as OE identitiy for initiation */
+ DBG(DBG_OPPO, DBG_log("can not use our IP (%s:KEY) as identity: %s"
+ , myid_str[MYID_IP]
+ , ugh));
+ if (!logged_myid_ip_key_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "can not use our IP (%s:KEY) as identity: %s"
+ , myid_str[MYID_IP]
+ , ugh);
+ logged_myid_ip_key_warning = TRUE;
+ }
+
+ next_step = fos_myid_hostname_key;
+ ugh = NULL; /* failure can be recovered from */
+ }
+ else
+ {
+ /* we can use our IP as OE identity for initiation */
+ if (!logged_myid_ip_key_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "using our IP (%s:KEY) as identity!"
+ , myid_str[MYID_IP]);
+ logged_myid_ip_key_warning = TRUE;
+ }
+ next_step = fos_our_client;
+ }
+ break;
- next_step = fos_his_client; /* always */
+ case fos_myid_hostname_key: /* KEY for our hostname as %myid */
+ ugh = check_key_recs(MYID_HOSTNAME, c, ac);
+ if (ugh != NULL)
+ {
+ /* cannot use our IP as OE identitiy for initiation */
+ DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:KEY) as identity: %s"
+ , myid_str[MYID_HOSTNAME]
+ , ugh));
+ if (!logged_myid_fqdn_key_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "can not use our hostname (%s:KEY) as identity: %s"
+ , myid_str[MYID_HOSTNAME]
+ , ugh);
+ logged_myid_fqdn_key_warning = TRUE;
+ }
+
+ next_step = fos_myid_hostname_key;
+ ugh = NULL; /* failure can be recovered from */
+ }
+ else
+ {
+ /* we can use our IP as OE identity for initiation */
+ if (!logged_myid_fqdn_key_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "using our hostname (%s:KEY) as identity!"
+ , myid_str[MYID_HOSTNAME]);
+ logged_myid_fqdn_key_warning = TRUE;
+ }
+ next_step = fos_our_client;
+ }
+ break;
+#endif
- if (our_RSA_pri == NULL)
- {
- ugh = "we don't know our own RSA key";
- }
- else if (!same_id(&ac->id, &c->spd.this.id))
- {
- ugh = "our ID changed underfoot";
- }
- else
- {
- /* Similar to code in RSA_check_signature
- * for checking the other side.
- */
- pubkey_list_t *kr;
-
- ugh = "no KEY RR found for us (and no good TXT RR)";
- for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next)
- {
- ugh = "all our KEY RRs have the wrong public key (and no good TXT RR)";
- if (kr->key->alg == PUBKEY_ALG_RSA
- && same_RSA_public_key(&our_RSA_pri->pub, &kr->key->u.rsa))
+ case fos_our_client: /* TXT for our client */
{
- /* do this only once a day */
- if (!logged_txt_warning)
- {
- loglog(RC_LOG_SERIOUS
- , "found KEY RR but not TXT RR for %s. See http://www.freeswan.org/err/txt-change.html."
- , mycredentialstr);
- logged_txt_warning = TRUE;
- }
- ugh = NULL; /* good! */
- break;
+ /* Our client is not us: we must check the TXT records.
+ * Note: if c is different this time, there is
+ * a chance that we did the wrong query.
+ * If so, treat as a kind of failure.
+ */
+ private_key_t *private = get_private_key(c);
+
+ next_step = fos_his_client; /* normal situation */
+
+ passert(sr != NULL);
+
+ if (private == NULL)
+ {
+ ugh = "we don't know our own RSA key";
+ }
+ else if (sameaddr(&sr->this.host_addr, &b->our_client))
+ {
+ /* this wasn't true when we started -- bail */
+ ugh = "our IP address changed underfoot";
+ }
+ else if (!same_id(&ac->sgw_id, &sr->this.id))
+ {
+ /* this wasn't true when we started -- bail */
+ ugh = "our ID changed underfoot";
+ }
+ else
+ {
+ /* Similar to code in quick_inI1_outR1_tail
+ * for checking the other side.
+ */
+ struct gw_info *gwp;
+
+ ugh = "no TXT RR for our client delegates us";
+ for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
+ passert(same_id(&gwp->gw_id, &sr->this.id));
+
+ ugh = "TXT RR for our client has wrong key";
+ /* If there is a key from the TXT record,
+ * we count it as a win if we match the key.
+ * If there was no key, we have a tentative win:
+ * we need to check our KEY record to be sure.
+ */
+ if (!gwp->gw_key_present)
+ {
+ /* Success, but the TXT had no key
+ * so we must check our our own KEY records.
+ */
+ next_step = fos_our_txt;
+ ugh = NULL; /* good! */
+ break;
+ }
+ if (private->belongs_to(private, gwp->key->public_key))
+ {
+ ugh = NULL; /* good! */
+ break;
+ }
+ }
+ }
}
- }
- }
- }
- break;
-#endif /* USE_KEYRR */
+ break;
- case fos_his_client: /* TXT for his client */
- {
- /* We've finished last DNS queries: TXT for his client.
- * Using the information, try to instantiate a connection
- * and start negotiating.
- * We now know the peer. The chosing of "c" ignored this,
- * so we will disregard its current value.
- * !!! We need to randomize the entry in gw that we choose.
- */
- next_step = fos_done; /* no more queries */
+ case fos_our_txt: /* TXT for us */
+ {
+ /* Check if TXT lookup yielded good results.
+ * Looking up based on our ID. Used if
+ * client is ourself, or if TXT had no public key.
+ * Note: if c is different this time, there is
+ * a chance that we did the wrong query.
+ * If so, treat as a kind of failure.
+ */
+ private_key_t *private = get_private_key(c);
+
+ next_step = fos_his_client; /* unless we decide to look for KEY RR */
+
+ if (private == NULL)
+ {
+ ugh = "we don't know our own RSA key";
+ }
+ else if (!same_id(&ac->id, &c->spd.this.id))
+ {
+ ugh = "our ID changed underfoot";
+ }
+ else
+ {
+ /* Similar to code in RSA_check_signature
+ * for checking the other side.
+ */
+ struct gw_info *gwp;
+
+ ugh = "no TXT RR for us";
+ for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
+ {
+ passert(same_id(&gwp->gw_id, &sr->this.id));
+
+ ugh = "TXT RR for us has wrong key";
+ if (gwp->gw_key_present &&
+ private->belongs_to(private, gwp->key->public_key))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("initiate on demand found TXT with right public key at: %s"
+ , mycredentialstr));
+ ugh = NULL;
+ break;
+ }
+ }
+#ifdef USE_KEYRR
+ if (ugh != NULL)
+ {
+ /* if no TXT with right key, try KEY */
+ DBG(DBG_CONTROL,
+ DBG_log("will try for KEY RR since initiate on demand found %s: %s"
+ , ugh, mycredentialstr));
+ next_step = fos_our_key;
+ ugh = NULL;
+ }
+#endif
+ }
+ }
+ break;
- c = build_outgoing_opportunistic_connection(ac->gateways_from_dns
- , &b->our_client
- , &b->peer_client);
+#ifdef USE_KEYRR
+ case fos_our_key: /* KEY for us */
+ {
+ /* Check if KEY lookup yielded good results.
+ * Looking up based on our ID. Used if
+ * client is ourself, or if TXT had no public key.
+ * Note: if c is different this time, there is
+ * a chance that we did the wrong query.
+ * If so, treat as a kind of failure.
+ */
+ private_key_t *private = get_private_key(c);
+
+ next_step = fos_his_client; /* always */
+
+ if (private == NULL)
+ {
+ ugh = "we don't know our own RSA key";
+ }
+ else if (!same_id(&ac->id, &c->spd.this.id))
+ {
+ ugh = "our ID changed underfoot";
+ }
+ else
+ {
+ /* Similar to code in RSA_check_signature
+ * for checking the other side.
+ */
+ pubkey_list_t *kr;
+
+ ugh = "no KEY RR found for us (and no good TXT RR)";
+ for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next)
+ {
+ ugh = "all our KEY RRs have the wrong public key (and no good TXT RR)";
+ if (kr->key->alg == PUBKEY_ALG_RSA
+ && private->belongs_to(private, kr->key->public_key))
+ {
+ /* do this only once a day */
+ if (!logged_txt_warning)
+ {
+ loglog(RC_LOG_SERIOUS
+ , "found KEY RR but not TXT RR for %s. See http://www.freeswan.org/err/txt-change.html."
+ , mycredentialstr);
+ logged_txt_warning = TRUE;
+ }
+ ugh = NULL; /* good! */
+ break;
+ }
+ }
+ }
+ }
+ break;
+#endif /* USE_KEYRR */
- if (c == NULL)
- {
- /* We cannot seem to instantiate a suitable connection:
- * complain clearly.
- */
- char ocb[ADDRTOT_BUF]
- , pcb[ADDRTOT_BUF]
- , pb[ADDRTOT_BUF];
-
- addrtot(&b->our_client, 0, ocb, sizeof(ocb));
- addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
- passert(id_is_ipaddr(&ac->gateways_from_dns->gw_id));
- addrtot(&ac->gateways_from_dns->gw_id.ip_addr, 0, pb, sizeof(pb));
- loglog(RC_OPPOFAILURE
- , "no suitable connection for opportunism"
- " between %s and %s with %s as peer"
- , ocb, pcb, pb);
+ case fos_his_client: /* TXT for his client */
+ {
+ /* We've finished last DNS queries: TXT for his client.
+ * Using the information, try to instantiate a connection
+ * and start negotiating.
+ * We now know the peer. The chosing of "c" ignored this,
+ * so we will disregard its current value.
+ * !!! We need to randomize the entry in gw that we choose.
+ */
+ next_step = fos_done; /* no more queries */
+
+ c = build_outgoing_opportunistic_connection(ac->gateways_from_dns
+ , &b->our_client
+ , &b->peer_client);
+
+ if (c == NULL)
+ {
+ /* We cannot seem to instantiate a suitable connection:
+ * complain clearly.
+ */
+ char ocb[ADDRTOT_BUF]
+ , pcb[ADDRTOT_BUF]
+ , pb[ADDRTOT_BUF];
+
+ addrtot(&b->our_client, 0, ocb, sizeof(ocb));
+ addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
+ passert(id_is_ipaddr(&ac->gateways_from_dns->gw_id));
+ addrtot(&ac->gateways_from_dns->gw_id.ip_addr, 0, pb, sizeof(pb));
+ loglog(RC_OPPOFAILURE
+ , "no suitable connection for opportunism"
+ " between %s and %s with %s as peer"
+ , ocb, pcb, pb);
#ifdef KLIPS
- if (b->held)
- {
- /* Replace HOLD with PASS.
- * The type of replacement *ought* to be
- * specified by policy.
- */
- (void) replace_bare_shunt(&b->our_client, &b->peer_client
- , BOTTOM_PRIO
- , SPI_PASS /* fail into PASS */
- , TRUE, b->transport_proto
- , "no suitable connection");
- }
+ if (b->held)
+ {
+ /* Replace HOLD with PASS.
+ * The type of replacement *ought* to be
+ * specified by policy.
+ */
+ (void) replace_bare_shunt(&b->our_client, &b->peer_client
+ , BOTTOM_PRIO
+ , SPI_PASS /* fail into PASS */
+ , TRUE, b->transport_proto
+ , "no suitable connection");
+ }
#endif
- }
- else
- {
- /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */
- passert(c->kind == CK_INSTANCE);
- passert(c->gw_info != NULL);
- passert(HAS_IPSEC_POLICY(c->policy));
- passert(LHAS(LELEM(RT_UNROUTED) | LELEM(RT_ROUTED_PROSPECTIVE), c->spd.routing));
+ }
+ else
+ {
+ /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */
+ passert(c->kind == CK_INSTANCE);
+ passert(c->gw_info != NULL);
+ passert(HAS_IPSEC_POLICY(c->policy));
+ passert(LHAS(LELEM(RT_UNROUTED) | LELEM(RT_ROUTED_PROSPECTIVE), c->spd.routing));
#ifdef KLIPS
- if (b->held)
- {
- /* what should we do on failure? */
- (void) assign_hold(c, &c->spd
- , b->transport_proto
- , &b->our_client, &b->peer_client);
- }
+ if (b->held)
+ {
+ /* what should we do on failure? */
+ (void) assign_hold(c, &c->spd
+ , b->transport_proto
+ , &b->our_client, &b->peer_client);
+ }
#endif
- c->gw_info->key->last_tried_time = now();
- ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY);
- b->whackfd = NULL_FD; /* protect from close */
- }
- }
- break;
+ c->gw_info->key->last_tried_time = now();
+ ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY);
+ b->whackfd = NULL_FD; /* protect from close */
+ }
+ }
+ break;
- default:
- bad_case(b->step);
- }
+ default:
+ bad_case(b->step);
+ }
- /* the second chunk: initiate the next DNS query (if any) */
- DBG(DBG_CONTROL,
- {
- char ours[ADDRTOT_BUF];
- char his[ADDRTOT_BUF];
+ /* the second chunk: initiate the next DNS query (if any) */
+ DBG(DBG_CONTROL,
+ {
+ char ours[ADDRTOT_BUF];
+ char his[ADDRTOT_BUF];
- addrtot(&b->our_client, 0, ours, sizeof(ours));
- addrtot(&b->peer_client, 0, his, sizeof(his));
- DBG_log("initiate on demand from %s to %s new state: %s with ugh: %s"
- , ours, his, oppo_step_name[b->step], ugh ? ugh : "ok");
- });
+ addrtot(&b->our_client, 0, ours, sizeof(ours));
+ addrtot(&b->peer_client, 0, his, sizeof(his));
+ DBG_log("initiate on demand from %s to %s new state: %s with ugh: %s"
+ , ours, his, oppo_step_name[b->step], ugh ? ugh : "ok");
+ });
- if (ugh != NULL)
- {
- b->policy_prio = c->prio;
- b->failure_shunt = shunt_policy_spi(c, FALSE);
- cannot_oppo(c, b, ugh);
- }
- else if (next_step == fos_done)
- {
- /* nothing to do */
- }
- else
- {
- /* set up the next query */
- struct find_oppo_continuation *cr = alloc_thing(struct find_oppo_continuation
- , "opportunistic continuation");
- struct id id;
-
- b->policy_prio = c->prio;
- b->failure_shunt = shunt_policy_spi(c, FALSE);
- cr->b = *b; /* copy; start hand off of whackfd */
- cr->b.failure_ok = FALSE;
- cr->b.step = next_step;
-
- for (sr = &c->spd
- ; sr!=NULL && !sameaddr(&sr->this.host_addr, &b->our_client)
- ; sr = sr->next)
- ;
-
- if (sr == NULL)
- sr = &c->spd;
-
- /* If a %hold shunt has replaced the eroute for this template,
- * record this fact.
- */
- if (b->held
- && sr->routing == RT_ROUTED_PROSPECTIVE && eclipsable(sr))
- {
- sr->routing = RT_ROUTED_ECLIPSED;
- eclipse_count++;
- }
-
- /* Switch to issue next query.
- * A case may turn out to be unnecessary. If so, it falls
- * through to the next case.
- * Figuring out what %myid can stand for must be done before
- * our client credentials are looked up: we must know what
- * the client credentials may use to identify us.
- * On the other hand, our own credentials should be looked
- * up after our clients in case our credentials are not
- * needed at all.
- * XXX this is a wasted effort if we don't have credentials
- * BUT they are not needed.
- */
- switch (next_step)
- {
- case fos_myid_ip_txt:
- if (c->spd.this.id.kind == ID_MYID
- && myid_state != MYID_SPECIFIED)
+ if (ugh != NULL)
{
- cr->b.failure_ok = TRUE;
- cr->b.want = b->want = "TXT record for IP address as %myid";
- ugh = start_adns_query(&myids[MYID_IP]
- , &myids[MYID_IP]
- , T_TXT
- , continue_oppo
- , &cr->ac);
- break;
+ b->policy_prio = c->prio;
+ b->failure_shunt = shunt_policy_spi(c, FALSE);
+ cannot_oppo(c, b, ugh);
}
- cr->b.step = fos_myid_hostname_txt;
- /* fall through */
-
- case fos_myid_hostname_txt:
- if (c->spd.this.id.kind == ID_MYID
- && myid_state != MYID_SPECIFIED)
+ else if (next_step == fos_done)
+ {
+ /* nothing to do */
+ }
+ else
{
+ /* set up the next query */
+ struct find_oppo_continuation *cr = malloc_thing(struct find_oppo_continuation);
+ struct id id;
+
+ b->policy_prio = c->prio;
+ b->failure_shunt = shunt_policy_spi(c, FALSE);
+ cr->b = *b; /* copy; start hand off of whackfd */
+ cr->b.failure_ok = FALSE;
+ cr->b.step = next_step;
+
+ for (sr = &c->spd
+ ; sr!=NULL && !sameaddr(&sr->this.host_addr, &b->our_client)
+ ; sr = sr->next)
+ ;
+
+ if (sr == NULL)
+ sr = &c->spd;
+
+ /* If a %hold shunt has replaced the eroute for this template,
+ * record this fact.
+ */
+ if (b->held
+ && sr->routing == RT_ROUTED_PROSPECTIVE && eclipsable(sr))
+ {
+ sr->routing = RT_ROUTED_ECLIPSED;
+ eclipse_count++;
+ }
+
+ /* Switch to issue next query.
+ * A case may turn out to be unnecessary. If so, it falls
+ * through to the next case.
+ * Figuring out what %myid can stand for must be done before
+ * our client credentials are looked up: we must know what
+ * the client credentials may use to identify us.
+ * On the other hand, our own credentials should be looked
+ * up after our clients in case our credentials are not
+ * needed at all.
+ * XXX this is a wasted effort if we don't have credentials
+ * BUT they are not needed.
+ */
+ switch (next_step)
+ {
+ case fos_myid_ip_txt:
+ if (c->spd.this.id.kind == ID_MYID
+ && myid_state != MYID_SPECIFIED)
+ {
+ cr->b.failure_ok = TRUE;
+ cr->b.want = b->want = "TXT record for IP address as %myid";
+ ugh = start_adns_query(&myids[MYID_IP]
+ , &myids[MYID_IP]
+ , T_TXT
+ , continue_oppo
+ , &cr->ac);
+ break;
+ }
+ cr->b.step = fos_myid_hostname_txt;
+ /* fall through */
+
+ case fos_myid_hostname_txt:
+ if (c->spd.this.id.kind == ID_MYID
+ && myid_state != MYID_SPECIFIED)
+ {
#ifdef USE_KEYRR
- cr->b.failure_ok = TRUE;
+ cr->b.failure_ok = TRUE;
#else
- cr->b.failure_ok = FALSE;
+ cr->b.failure_ok = FALSE;
#endif
- cr->b.want = b->want = "TXT record for hostname as %myid";
- ugh = start_adns_query(&myids[MYID_HOSTNAME]
- , &myids[MYID_HOSTNAME]
- , T_TXT
- , continue_oppo
- , &cr->ac);
- break;
- }
+ cr->b.want = b->want = "TXT record for hostname as %myid";
+ ugh = start_adns_query(&myids[MYID_HOSTNAME]
+ , &myids[MYID_HOSTNAME]
+ , T_TXT
+ , continue_oppo
+ , &cr->ac);
+ break;
+ }
#ifdef USE_KEYRR
- cr->b.step = fos_myid_ip_key;
- /* fall through */
-
- case fos_myid_ip_key:
- if (c->spd.this.id.kind == ID_MYID
- && myid_state != MYID_SPECIFIED)
- {
- cr->b.failure_ok = TRUE;
- cr->b.want = b->want = "KEY record for IP address as %myid (no good TXT)";
- ugh = start_adns_query(&myids[MYID_IP]
- , (const struct id *) NULL /* security gateway meaningless */
- , T_KEY
- , continue_oppo
- , &cr->ac);
- break;
- }
- cr->b.step = fos_myid_hostname_key;
- /* fall through */
-
- case fos_myid_hostname_key:
- if (c->spd.this.id.kind == ID_MYID
- && myid_state != MYID_SPECIFIED)
- {
- cr->b.failure_ok = FALSE; /* last attempt! */
- cr->b.want = b->want = "KEY record for hostname as %myid (no good TXT)";
- ugh = start_adns_query(&myids[MYID_HOSTNAME]
- , (const struct id *) NULL /* security gateway meaningless */
- , T_KEY
- , continue_oppo
- , &cr->ac);
- break;
- }
+ cr->b.step = fos_myid_ip_key;
+ /* fall through */
+
+ case fos_myid_ip_key:
+ if (c->spd.this.id.kind == ID_MYID
+ && myid_state != MYID_SPECIFIED)
+ {
+ cr->b.failure_ok = TRUE;
+ cr->b.want = b->want = "KEY record for IP address as %myid (no good TXT)";
+ ugh = start_adns_query(&myids[MYID_IP]
+ , (const struct id *) NULL /* security gateway meaningless */
+ , T_KEY
+ , continue_oppo
+ , &cr->ac);
+ break;
+ }
+ cr->b.step = fos_myid_hostname_key;
+ /* fall through */
+
+ case fos_myid_hostname_key:
+ if (c->spd.this.id.kind == ID_MYID
+ && myid_state != MYID_SPECIFIED)
+ {
+ cr->b.failure_ok = FALSE; /* last attempt! */
+ cr->b.want = b->want = "KEY record for hostname as %myid (no good TXT)";
+ ugh = start_adns_query(&myids[MYID_HOSTNAME]
+ , (const struct id *) NULL /* security gateway meaningless */
+ , T_KEY
+ , continue_oppo
+ , &cr->ac);
+ break;
+ }
#endif
- cr->b.step = fos_our_client;
- /* fall through */
-
- case fos_our_client: /* TXT for our client */
- if (!sameaddr(&c->spd.this.host_addr, &b->our_client))
- {
- /* Check that at least one TXT(reverse(b->our_client)) is workable.
- * Note: {unshare|free}_id_content not needed for id: ephemeral.
- */
- cr->b.want = b->want = "our client's TXT record";
- iptoid(&b->our_client, &id);
- ugh = start_adns_query(&id
- , &c->spd.this.id /* we are the security gateway */
- , T_TXT
- , continue_oppo
- , &cr->ac);
- break;
- }
- cr->b.step = fos_our_txt;
- /* fall through */
-
- case fos_our_txt: /* TXT for us */
- cr->b.failure_ok = b->failure_ok = TRUE;
- cr->b.want = b->want = "our TXT record";
- ugh = start_adns_query(&sr->this.id
- , &sr->this.id /* we are the security gateway XXX - maybe ignore? mcr */
- , T_TXT
- , continue_oppo
- , &cr->ac);
- break;
+ cr->b.step = fos_our_client;
+ /* fall through */
+
+ case fos_our_client: /* TXT for our client */
+ if (!sameaddr(&c->spd.this.host_addr, &b->our_client))
+ {
+ /* Check that at least one TXT(reverse(b->our_client)) is workable.
+ * Note: {unshare|free}_id_content not needed for id: ephemeral.
+ */
+ cr->b.want = b->want = "our client's TXT record";
+ iptoid(&b->our_client, &id);
+ ugh = start_adns_query(&id
+ , &c->spd.this.id /* we are the security gateway */
+ , T_TXT
+ , continue_oppo
+ , &cr->ac);
+ break;
+ }
+ cr->b.step = fos_our_txt;
+ /* fall through */
+
+ case fos_our_txt: /* TXT for us */
+ cr->b.failure_ok = b->failure_ok = TRUE;
+ cr->b.want = b->want = "our TXT record";
+ ugh = start_adns_query(&sr->this.id
+ , &sr->this.id /* we are the security gateway XXX - maybe ignore? mcr */
+ , T_TXT
+ , continue_oppo
+ , &cr->ac);
+ break;
#ifdef USE_KEYRR
- case fos_our_key: /* KEY for us */
- cr->b.want = b->want = "our KEY record";
- cr->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(&sr->this.id
- , (const struct id *) NULL /* security gateway meaningless */
- , T_KEY
- , continue_oppo
- , &cr->ac);
- break;
+ case fos_our_key: /* KEY for us */
+ cr->b.want = b->want = "our KEY record";
+ cr->b.failure_ok = b->failure_ok = FALSE;
+ ugh = start_adns_query(&sr->this.id
+ , (const struct id *) NULL /* security gateway meaningless */
+ , T_KEY
+ , continue_oppo
+ , &cr->ac);
+ break;
#endif /* USE_KEYRR */
- case fos_his_client: /* TXT for his client */
- /* note: {unshare|free}_id_content not needed for id: ephemeral */
- cr->b.want = b->want = "target's TXT record";
- cr->b.failure_ok = b->failure_ok = FALSE;
- iptoid(&b->peer_client, &id);
- ugh = start_adns_query(&id
- , (const struct id *) NULL /* security gateway unconstrained */
- , T_TXT
- , continue_oppo
- , &cr->ac);
- break;
-
- default:
- bad_case(next_step);
- }
+ case fos_his_client: /* TXT for his client */
+ /* note: {unshare|free}_id_content not needed for id: ephemeral */
+ cr->b.want = b->want = "target's TXT record";
+ cr->b.failure_ok = b->failure_ok = FALSE;
+ iptoid(&b->peer_client, &id);
+ ugh = start_adns_query(&id
+ , (const struct id *) NULL /* security gateway unconstrained */
+ , T_TXT
+ , continue_oppo
+ , &cr->ac);
+ break;
+
+ default:
+ bad_case(next_step);
+ }
- if (ugh == NULL)
- b->whackfd = NULL_FD; /* complete hand-off */
- else
- cannot_oppo(c, b, ugh);
+ if (ugh == NULL)
+ b->whackfd = NULL_FD; /* complete hand-off */
+ else
+ cannot_oppo(c, b, ugh);
+ }
}
- }
- close_any(b->whackfd);
+ close_any(b->whackfd);
}
void
terminate_connection(const char *nm)
{
- /* Loop because more than one may match (master and instances)
- * But at least one is required (enforced by con_by_name).
- */
- struct connection *c = con_by_name(nm, TRUE);
-
- if (c == NULL || !c->ikev1)
- return;
+ /* Loop because more than one may match (master and instances)
+ * But at least one is required (enforced by con_by_name).
+ */
+ struct connection *c = con_by_name(nm, TRUE);
- do
- {
- struct connection *n = c->ac_next; /* grab this before c might disappear */
+ if (c == NULL || !c->ikev1)
+ return;
- if (streq(c->name, nm)
- && c->kind >= CK_PERMANENT
- && !NEVER_NEGOTIATE(c->policy))
+ do
{
- set_cur_connection(c);
- plog("terminating SAs using this connection");
- c->policy &= ~POLICY_UP;
- flush_pending_by_connection(c);
- delete_states_by_connection(c, FALSE);
- if (c->kind == CK_INSTANCE)
- delete_connection(c, FALSE);
- reset_cur_connection();
- }
- c = n;
- } while (c != NULL);
+ struct connection *n = c->ac_next; /* grab this before c might disappear */
+
+ if (streq(c->name, nm)
+ && c->kind >= CK_PERMANENT
+ && !NEVER_NEGOTIATE(c->policy))
+ {
+ set_cur_connection(c);
+ plog("terminating SAs using this connection");
+ c->policy &= ~POLICY_UP;
+ flush_pending_by_connection(c);
+ delete_states_by_connection(c, FALSE);
+ if (c->kind == CK_INSTANCE)
+ delete_connection(c, FALSE);
+ reset_cur_connection();
+ }
+ c = n;
+ } while (c != NULL);
}
/* an ISAKMP SA has been established.
* Note the serial number, and release any connections with
* the same peer ID but different peer IP address.
*/
-bool uniqueIDs = FALSE; /* --uniqueids? */
+bool uniqueIDs = FALSE; /* --uniqueids? */
void
ISAKMP_SA_established(struct connection *c, so_serial_t serial)
{
- c->newest_isakmp_sa = serial;
-
- /* the connection is now oriented so that we are able to determine
- * whether we are a mode config server with a virtual IP to send.
- */
- if (!isanyaddr(&c->spd.that.host_srcip) && !c->spd.that.has_natip)
- c->spd.that.modecfg = TRUE;
-
- if (uniqueIDs)
- {
- /* for all connections: if the same Phase 1 IDs are used
- * for a different IP address, unorient that connection.
- */
- struct connection *d;
+ c->newest_isakmp_sa = serial;
- for (d = connections; d != NULL; )
+ /* the connection is now oriented so that we are able to determine
+ * whether we are a mode config server with a virtual IP to send.
+ */
+ if (!isanyaddr(&c->spd.that.host_srcip) && !c->spd.that.has_natip)
+ c->spd.that.modecfg = TRUE;
+
+ if (uniqueIDs)
{
- struct connection *next = d->ac_next; /* might move underneath us */
-
- if (d->kind >= CK_PERMANENT
- && same_id(&c->spd.this.id, &d->spd.this.id)
- && same_id(&c->spd.that.id, &d->spd.that.id)
- && !sameaddr(&c->spd.that.host_addr, &d->spd.that.host_addr))
- {
- release_connection(d, FALSE);
- }
- d = next;
+ /* for all connections: if the same Phase 1 IDs are used
+ * for a different IP address, unorient that connection.
+ */
+ struct connection *d;
+
+ for (d = connections; d != NULL; )
+ {
+ struct connection *next = d->ac_next; /* might move underneath us */
+
+ if (d->kind >= CK_PERMANENT
+ && same_id(&c->spd.this.id, &d->spd.this.id)
+ && same_id(&c->spd.that.id, &d->spd.that.id)
+ && !sameaddr(&c->spd.that.host_addr, &d->spd.that.host_addr))
+ {
+ release_connection(d, FALSE);
+ }
+ d = next;
+ }
}
- }
}
/* Find the connection to connection c's peer's client with the
@@ -3056,108 +3048,108 @@ ISAKMP_SA_established(struct connection *c, so_serial_t serial)
*/
struct connection *
route_owner(struct connection *c
- , struct spd_route **srp
- , struct connection **erop
- , struct spd_route **esrp)
+ , struct spd_route **srp
+ , struct connection **erop
+ , struct spd_route **esrp)
{
- struct connection *d
- , *best_ro = c
- , *best_ero = c;
- struct spd_route *srd, *src;
- struct spd_route *best_sr, *best_esr;
- enum routing_t best_routing, best_erouting;
-
- passert(oriented(*c));
- best_sr = NULL;
- best_esr = NULL;
- best_routing = c->spd.routing;
- best_erouting = best_routing;
-
- for (d = connections; d != NULL; d = d->ac_next)
- {
- for (srd = &d->spd; srd; srd = srd->next)
+ struct connection *d
+ , *best_ro = c
+ , *best_ero = c;
+ struct spd_route *srd, *src;
+ struct spd_route *best_sr, *best_esr;
+ enum routing_t best_routing, best_erouting;
+
+ passert(oriented(*c));
+ best_sr = NULL;
+ best_esr = NULL;
+ best_routing = c->spd.routing;
+ best_erouting = best_routing;
+
+ for (d = connections; d != NULL; d = d->ac_next)
{
- if (srd->routing == RT_UNROUTED)
- continue;
-
- for (src = &c->spd; src; src=src->next)
- {
- if (!samesubnet(&src->that.client, &srd->that.client))
- continue;
- if (src->that.protocol != srd->that.protocol)
- continue;
- if (src->that.port != srd->that.port)
- continue;
- passert(oriented(*d));
- if (srd->routing > best_routing)
+ for (srd = &d->spd; srd; srd = srd->next)
{
- best_ro = d;
- best_sr = srd;
- best_routing = srd->routing;
- }
+ if (srd->routing == RT_UNROUTED)
+ continue;
- if (!samesubnet(&src->this.client, &srd->this.client))
- continue;
- if (src->this.protocol != srd->this.protocol)
- continue;
- if (src->this.port != srd->this.port)
- continue;
- if (srd->routing > best_erouting)
- {
- best_ero = d;
- best_esr = srd;
- best_erouting = srd->routing;
+ for (src = &c->spd; src; src=src->next)
+ {
+ if (!samesubnet(&src->that.client, &srd->that.client))
+ continue;
+ if (src->that.protocol != srd->that.protocol)
+ continue;
+ if (src->that.port != srd->that.port)
+ continue;
+ passert(oriented(*d));
+ if (srd->routing > best_routing)
+ {
+ best_ro = d;
+ best_sr = srd;
+ best_routing = srd->routing;
+ }
+
+ if (!samesubnet(&src->this.client, &srd->this.client))
+ continue;
+ if (src->this.protocol != srd->this.protocol)
+ continue;
+ if (src->this.port != srd->this.port)
+ continue;
+ if (srd->routing > best_erouting)
+ {
+ best_ero = d;
+ best_esr = srd;
+ best_erouting = srd->routing;
+ }
+ }
}
- }
}
- }
- DBG(DBG_CONTROL,
+ DBG(DBG_CONTROL,
+ {
+ char cib[CONN_INST_BUF];
+ err_t m = builddiag("route owner of \"%s\"%s %s:"
+ , c->name
+ , (fmt_conn_instance(c, cib), cib)
+ , enum_name(&routing_story, c->spd.routing));
+
+ if (!routed(best_ro->spd.routing))
+ m = builddiag("%s NULL", m);
+ else if (best_ro == c)
+ m = builddiag("%s self", m);
+ else
+ m = builddiag("%s \"%s\"%s %s", m
+ , best_ro->name
+ , (fmt_conn_instance(best_ro, cib), cib)
+ , enum_name(&routing_story, best_ro->spd.routing));
+
+ if (erop != NULL)
+ {
+ m = builddiag("%s; eroute owner:", m);
+ if (!erouted(best_ero->spd.routing))
+ m = builddiag("%s NULL", m);
+ else if (best_ero == c)
+ m = builddiag("%s self", m);
+ else
+ m = builddiag("%s \"%s\"%s %s", m
+ , best_ero->name
+ , (fmt_conn_instance(best_ero, cib), cib)
+ , enum_name(&routing_story, best_ero->spd.routing));
+ }
+
+ DBG_log("%s", m);
+ });
+
+ if (erop != NULL)
+ *erop = erouted(best_erouting)? best_ero : NULL;
+
+ if (srp != NULL )
{
- char cib[CONN_INST_BUF];
- err_t m = builddiag("route owner of \"%s\"%s %s:"
- , c->name
- , (fmt_conn_instance(c, cib), cib)
- , enum_name(&routing_story, c->spd.routing));
-
- if (!routed(best_ro->spd.routing))
- m = builddiag("%s NULL", m);
- else if (best_ro == c)
- m = builddiag("%s self", m);
- else
- m = builddiag("%s \"%s\"%s %s", m
- , best_ro->name
- , (fmt_conn_instance(best_ro, cib), cib)
- , enum_name(&routing_story, best_ro->spd.routing));
-
- if (erop != NULL)
- {
- m = builddiag("%s; eroute owner:", m);
- if (!erouted(best_ero->spd.routing))
- m = builddiag("%s NULL", m);
- else if (best_ero == c)
- m = builddiag("%s self", m);
- else
- m = builddiag("%s \"%s\"%s %s", m
- , best_ero->name
- , (fmt_conn_instance(best_ero, cib), cib)
- , enum_name(&routing_story, best_ero->spd.routing));
- }
-
- DBG_log("%s", m);
- });
-
- if (erop != NULL)
- *erop = erouted(best_erouting)? best_ero : NULL;
-
- if (srp != NULL )
- {
- *srp = best_sr;
- if (esrp != NULL )
- *esrp = best_esr;
- }
-
- return routed(best_routing)? best_ro : NULL;
+ *srp = best_sr;
+ if (esrp != NULL )
+ *esrp = best_esr;
+ }
+
+ return routed(best_routing)? best_ro : NULL;
}
/* Find a connection that owns the shunt eroute between subnets.
@@ -3167,20 +3159,20 @@ route_owner(struct connection *c
struct connection *
shunt_owner(const ip_subnet *ours, const ip_subnet *his)
{
- struct connection *c;
- struct spd_route *sr;
+ struct connection *c;
+ struct spd_route *sr;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- for (sr = &c->spd; sr; sr = sr->next)
+ for (c = connections; c != NULL; c = c->ac_next)
{
- if (shunt_erouted(sr->routing)
- && samesubnet(ours, &sr->this.client)
- && samesubnet(his, &sr->that.client))
- return c;
+ for (sr = &c->spd; sr; sr = sr->next)
+ {
+ if (shunt_erouted(sr->routing)
+ && samesubnet(ours, &sr->this.client)
+ && samesubnet(his, &sr->that.client))
+ return c;
+ }
}
- }
- return NULL;
+ return NULL;
}
/* Find some connection with this pair of hosts.
@@ -3191,25 +3183,25 @@ struct connection *
find_host_connection(const ip_address *me, u_int16_t my_port
, const ip_address *him, u_int16_t his_port, lset_t policy)
{
- struct connection *c = find_host_pair_connections(me, my_port, him, his_port);
-
- if (policy != LEMPTY)
- {
- lset_t auth_requested = policy & POLICY_ID_AUTH_MASK;
+ struct connection *c = find_host_pair_connections(me, my_port, him, his_port);
- /* if we have requirements for the policy,
- * choose the first matching connection.
- */
- while (c != NULL)
+ if (policy != LEMPTY)
{
- if (c->policy & auth_requested)
- {
- break;
- }
- c = c->hp_next;
+ lset_t auth_requested = policy & POLICY_ID_AUTH_MASK;
+
+ /* if we have requirements for the policy,
+ * choose the first matching connection.
+ */
+ while (c != NULL)
+ {
+ if (c->policy & auth_requested)
+ {
+ break;
+ }
+ c = c->hp_next;
+ }
}
- }
- return c;
+ return c;
}
/* given an up-until-now satisfactory connection, find the best connection
@@ -3266,187 +3258,197 @@ find_host_connection(const ip_address *me, u_int16_t my_port
*
* In the Initiator case, the particular connection might have been
* specified by whatever provoked Pluto to initiate. For example:
- * whack --initiate connection-name
+ * whack --initiate connection-name
* The advantages of switching connections when we're the Initiator seem
* less important than the disadvantages, so after FreeS/WAN 1.9, we
* don't do this.
*/
-#define PRIO_NO_MATCH_FOUND 2048
+#define PRIO_NO_MATCH_FOUND 2048
struct connection *
refine_host_connection(const struct state *st, const struct id *peer_id
, chunk_t peer_ca)
{
- struct connection *c = st->st_connection;
- struct connection *d;
- struct connection *best_found = NULL;
- u_int16_t auth = st->st_oakley.auth;
- lset_t auth_policy = POLICY_PSK;
- const chunk_t *psk = NULL;
- bool wcpip; /* wildcard Peer IP? */
- int best_prio = PRIO_NO_MATCH_FOUND;
- int wildcards, our_pathlen, peer_pathlen;
-
- if (same_id(&c->spd.that.id, peer_id)
- && trusted_ca(peer_ca, c->spd.that.ca, &peer_pathlen)
- && peer_pathlen == 0
- && match_requested_ca(c->requested_ca, c->spd.this.ca, &our_pathlen)
- && our_pathlen == 0)
- {
- DBG(DBG_CONTROL,
- DBG_log("current connection is a full match"
- " -- no need to look further");
- )
- return c;
- }
-
- switch (auth)
- {
- case OAKLEY_PRESHARED_KEY:
- auth_policy = POLICY_PSK;
- psk = get_preshared_secret(c);
- /* It should be virtually impossible to fail to find PSK:
- * we just used it to decode the current message!
- */
- if (psk == NULL)
- return NULL; /* cannot determine PSK! */
- break;
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- auth_policy = POLICY_XAUTH_PSK;
- psk = get_preshared_secret(c);
- if (psk == NULL)
- return NULL; /* cannot determine PSK! */
- break;
- case OAKLEY_RSA_SIG:
- auth_policy = POLICY_RSASIG;
- break;
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- auth_policy = POLICY_XAUTH_RSASIG;
- break;
- default:
- bad_case(auth);
- }
-
- /* The current connection won't do: search for one that will.
- * First search for one with the same pair of hosts.
- * If that fails, search for a suitable Road Warrior or Opportunistic
- * connection (i.e. wildcard peer IP).
- * We need to match:
- * - peer_id (slightly complicated by instantiation)
- * - if PSK auth, the key must not change (we used it to decode message)
- * - policy-as-used must be acceptable to new connection
- */
- d = c->host_pair->connections;
- for (wcpip = FALSE; ; wcpip = TRUE)
- {
- for (; d != NULL; d = d->hp_next)
+ struct connection *c = st->st_connection;
+ struct connection *d;
+ struct connection *best_found = NULL;
+ u_int16_t auth = st->st_oakley.auth;
+ lset_t auth_policy = POLICY_PSK;
+ const chunk_t *psk = NULL;
+ bool wcpip; /* wildcard Peer IP? */
+ int best_prio = PRIO_NO_MATCH_FOUND;
+ int wildcards, our_pathlen, peer_pathlen;
+
+ if (same_id(&c->spd.that.id, peer_id)
+ && trusted_ca(peer_ca, c->spd.that.ca, &peer_pathlen)
+ && peer_pathlen == 0
+ && match_requested_ca(c->requested_ca, c->spd.this.ca, &our_pathlen)
+ && our_pathlen == 0)
{
- const char *match_name[] = {"no", "ok"};
-
- bool matching_id = match_id(peer_id
- , &d->spd.that.id, &wildcards);
- bool matching_auth = (d->policy & auth_policy) != LEMPTY;
-
- bool matching_trust = trusted_ca(peer_ca
- , d->spd.that.ca, &peer_pathlen);
- bool matching_request = match_requested_ca(c->requested_ca
- , d->spd.this.ca, &our_pathlen);
- bool match = matching_id && matching_auth && matching_trust;
-
- int prio = (MAX_WILDCARDS + 1) * !matching_request + wildcards;
-
- prio = (MAX_CA_PATH_LEN + 1) * prio + peer_pathlen;
- prio = (MAX_CA_PATH_LEN + 1) * prio + our_pathlen;
-
- DBG(DBG_CONTROLMORE,
- DBG_log("%s: %s match (id: %s, auth: %s, trust: %s, request: %s, prio: %4d)"
- , d->name
- , match ? "full":" no"
- , match_name[matching_id]
- , match_name[matching_auth]
- , match_name[matching_trust]
- , match_name[matching_request]
- , match ? prio:PRIO_NO_MATCH_FOUND)
- )
-
- /* do we have a match? */
- if (!match)
- continue;
-
- /* ignore group connections */
- if (d->policy & POLICY_GROUP)
- continue;
-
- if (c->spd.that.host_port != d->spd.that.host_port
- && d->kind == CK_INSTANCE)
- {
- continue;
- }
-
- switch (auth)
- {
- case OAKLEY_PRESHARED_KEY:
- case XAUTHInitPreShared:
- case XAUTHRespPreShared:
- /* secret must match the one we already used */
- {
- const chunk_t *dpsk = get_preshared_secret(d);
-
- if (dpsk == NULL)
- continue; /* no secret */
+ DBG(DBG_CONTROL,
+ DBG_log("current connection is a full match"
+ " -- no need to look further");
+ )
+ return c;
+ }
- if (psk != dpsk)
- if (psk->len != dpsk->len
- || memcmp(psk->ptr, dpsk->ptr, psk->len) != 0)
- continue; /* different secret */
+ switch (auth)
+ {
+ case OAKLEY_PRESHARED_KEY:
+ auth_policy = POLICY_PSK;
+ psk = get_preshared_secret(c);
+ /* It should be virtually impossible to fail to find PSK:
+ * we just used it to decode the current message!
+ */
+ if (psk == NULL)
+ {
+ return NULL; /* cannot determine PSK! */
}
break;
-
- case OAKLEY_RSA_SIG:
- case XAUTHInitRSA:
- case XAUTHRespRSA:
- /*
- * We must at least be able to find our private key
- .*/
- if (d->spd.this.sc == NULL /* no smartcard */
- && get_RSA_private_key(d) == NULL) /* no private key */
- continue;
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ auth_policy = POLICY_XAUTH_PSK;
+ psk = get_preshared_secret(c);
+ if (psk == NULL)
+ {
+ return NULL; /* cannot determine PSK! */
+ }
break;
-
- default:
+ case OAKLEY_RSA_SIG:
+ case OAKLEY_ECDSA_256:
+ case OAKLEY_ECDSA_384:
+ case OAKLEY_ECDSA_521:
+ auth_policy = POLICY_PUBKEY;
+ break;
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ auth_policy = POLICY_XAUTH_RSASIG;
+ break;
+ default:
bad_case(auth);
- }
-
- /* d has passed all the tests.
- * We'll go with it if the Peer ID was an exact match.
- */
- if (prio == 0)
- {
- return d;
- }
-
- /* We'll remember it as best_found in case an exact
- * match doesn't come along.
- */
- if (prio < best_prio)
- {
- best_found = d;
- best_prio = prio;
- }
}
- if (wcpip)
- return best_found; /* been around twice already */
- /* Starting second time around.
- * We're willing to settle for a connection that needs Peer IP
- * instantiated: Road Warrior or Opportunistic.
- * Look on list of connections for host pair with wildcard Peer IP
+ /* The current connection won't do: search for one that will.
+ * First search for one with the same pair of hosts.
+ * If that fails, search for a suitable Road Warrior or Opportunistic
+ * connection (i.e. wildcard peer IP).
+ * We need to match:
+ * - peer_id (slightly complicated by instantiation)
+ * - if PSK auth, the key must not change (we used it to decode message)
+ * - policy-as-used must be acceptable to new connection
*/
- d = find_host_pair_connections(&c->spd.this.host_addr, c->spd.this.host_port
- , (ip_address *)NULL, c->spd.that.host_port);
- }
+ d = c->host_pair->connections;
+ for (wcpip = FALSE; ; wcpip = TRUE)
+ {
+ for (; d != NULL; d = d->hp_next)
+ {
+ const char *match_name[] = {"no", "ok"};
+
+ bool matching_id = match_id(peer_id
+ , &d->spd.that.id, &wildcards);
+ bool matching_auth = (d->policy & auth_policy) != LEMPTY;
+
+ bool matching_trust = trusted_ca(peer_ca
+ , d->spd.that.ca, &peer_pathlen);
+ bool matching_request = match_requested_ca(c->requested_ca
+ , d->spd.this.ca, &our_pathlen);
+ bool match = matching_id && matching_auth && matching_trust;
+
+ int prio = (MAX_WILDCARDS + 1) * !matching_request + wildcards;
+
+ prio = (MAX_CA_PATH_LEN + 1) * prio + peer_pathlen;
+ prio = (MAX_CA_PATH_LEN + 1) * prio + our_pathlen;
+
+ DBG(DBG_CONTROLMORE,
+ DBG_log("%s: %s match (id: %s, auth: %s, trust: %s, request: %s, prio: %4d)"
+ , d->name
+ , match ? "full":" no"
+ , match_name[matching_id]
+ , match_name[matching_auth]
+ , match_name[matching_trust]
+ , match_name[matching_request]
+ , match ? prio:PRIO_NO_MATCH_FOUND)
+ )
+
+ /* do we have a match? */
+ if (!match)
+ continue;
+
+ /* ignore group connections */
+ if (d->policy & POLICY_GROUP)
+ continue;
+
+ if (c->spd.that.host_port != d->spd.that.host_port
+ && d->kind == CK_INSTANCE)
+ {
+ continue;
+ }
+
+ switch (auth)
+ {
+ case OAKLEY_PRESHARED_KEY:
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ /* secret must match the one we already used */
+ {
+ const chunk_t *dpsk = get_preshared_secret(d);
+
+ if (dpsk == NULL)
+ continue; /* no secret */
+
+ if (psk != dpsk)
+ if (psk->len != dpsk->len
+ || memcmp(psk->ptr, dpsk->ptr, psk->len) != 0)
+ continue; /* different secret */
+ }
+ break;
+
+ case OAKLEY_RSA_SIG:
+ case OAKLEY_ECDSA_256:
+ case OAKLEY_ECDSA_384:
+ case OAKLEY_ECDSA_521:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ /*
+ * We must at least be able to find our private key
+ .*/
+ if (d->spd.this.sc == NULL /* no smartcard */
+ && get_private_key(d) == NULL) /* no private key */
+ continue;
+ break;
+
+ default:
+ bad_case(auth);
+ }
+
+ /* d has passed all the tests.
+ * We'll go with it if the Peer ID was an exact match.
+ */
+ if (prio == 0)
+ {
+ return d;
+ }
+
+ /* We'll remember it as best_found in case an exact
+ * match doesn't come along.
+ */
+ if (prio < best_prio)
+ {
+ best_found = d;
+ best_prio = prio;
+ }
+ }
+ if (wcpip)
+ return best_found; /* been around twice already */
+
+ /* Starting second time around.
+ * We're willing to settle for a connection that needs Peer IP
+ * instantiated: Road Warrior or Opportunistic.
+ * Look on list of connections for host pair with wildcard Peer IP
+ */
+ d = find_host_pair_connections(&c->spd.this.host_addr, c->spd.this.host_port
+ , (ip_address *)NULL, c->spd.that.host_port);
+ }
}
/**
@@ -3456,35 +3458,35 @@ refine_host_connection(const struct state *st, const struct id *peer_id
static bool
is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id)
{
- struct connection *d;
+ struct connection *d;
- for (d = connections; d != NULL; d = d->ac_next)
- {
- switch (d->kind)
+ for (d = connections; d != NULL; d = d->ac_next)
{
- case CK_PERMANENT:
- case CK_INSTANCE:
- if ((subnetinsubnet(peer_net,&d->spd.that.client) ||
- subnetinsubnet(&d->spd.that.client,peer_net))
- && !same_id(&d->spd.that.id, peer_id))
- {
- char buf[BUF_LEN];
- char client[SUBNETTOT_BUF];
-
- subnettot(peer_net, 0, client, sizeof(client));
- idtoa(&d->spd.that.id, buf, sizeof(buf));
- plog("Virtual IP %s is already used by '%s'", client, buf);
- idtoa(peer_id, buf, sizeof(buf));
- plog("Your ID is '%s'", buf);
- return TRUE; /* already used by another one */
- }
- break;
- case CK_GOING_AWAY:
- default:
- break;
+ switch (d->kind)
+ {
+ case CK_PERMANENT:
+ case CK_INSTANCE:
+ if ((subnetinsubnet(peer_net,&d->spd.that.client) ||
+ subnetinsubnet(&d->spd.that.client,peer_net))
+ && !same_id(&d->spd.that.id, peer_id))
+ {
+ char buf[BUF_LEN];
+ char client[SUBNETTOT_BUF];
+
+ subnettot(peer_net, 0, client, sizeof(client));
+ idtoa(&d->spd.that.id, buf, sizeof(buf));
+ plog("Virtual IP %s is already used by '%s'", client, buf);
+ idtoa(peer_id, buf, sizeof(buf));
+ plog("Your ID is '%s'", buf);
+ return TRUE; /* already used by another one */
+ }
+ break;
+ case CK_GOING_AWAY:
+ default:
+ break;
+ }
}
- }
- return FALSE; /* you can safely use it */
+ return FALSE; /* you can safely use it */
}
/* find_client_connection: given a connection suitable for ISAKMP
@@ -3512,9 +3514,9 @@ is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id)
* instantiation. They are the IDs that have been authenticated.
*/
-#define PATH_WEIGHT 1
-#define WILD_WEIGHT (MAX_CA_PATH_LEN+1)
-#define PRIO_WEIGHT (MAX_WILDCARDS+1)*WILD_WEIGHT
+#define PATH_WEIGHT 1
+#define WILD_WEIGHT (MAX_CA_PATH_LEN+1)
+#define PRIO_WEIGHT (MAX_WILDCARDS+1)*WILD_WEIGHT
/* fc_try: a helper function for find_client_connection */
static struct connection *
@@ -3530,121 +3532,121 @@ fc_try(const struct connection *c
, chunk_t peer_ca
, const ietfAttrList_t *peer_list)
{
- struct connection *d;
- struct connection *best = NULL;
- policy_prio_t best_prio = BOTTOM_PRIO;
- int wildcards, pathlen;
-
- const bool peer_net_is_host = subnetisaddr(peer_net, &c->spd.that.host_addr);
-
- for (d = hp->connections; d != NULL; d = d->hp_next)
- {
- struct spd_route *sr;
+ struct connection *d;
+ struct connection *best = NULL;
+ policy_prio_t best_prio = BOTTOM_PRIO;
+ int wildcards, pathlen;
- if (d->policy & POLICY_GROUP)
- continue;
-
- if (!(same_id(&c->spd.this.id, &d->spd.this.id)
- && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
- && trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
- && group_membership(peer_list, d->name, d->spd.that.groups)))
- continue;
-
- /* compare protocol and ports */
- if (d->spd.this.protocol != our_protocol
- || d->spd.this.port != our_port
- || d->spd.that.protocol != peer_protocol
- || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
- continue;
-
- /* non-Opportunistic case:
- * our_client must match.
- *
- * So must peer_client, but the testing is complicated
- * by the fact that the peer might be a wildcard
- * and if so, the default value of that.client
- * won't match the default peer_net. The appropriate test:
- *
- * If d has a peer client, it must match peer_net.
- * If d has no peer client, peer_net must just have peer itself.
- */
+ const bool peer_net_is_host = subnetisaddr(peer_net, &c->spd.that.host_addr);
- for (sr = &d->spd; best != d && sr != NULL; sr = sr->next)
+ for (d = hp->connections; d != NULL; d = d->hp_next)
{
- policy_prio_t prio;
-#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
- char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF];
+ struct spd_route *sr;
- subnettot(our_net, 0, s1, sizeof(s1));
- subnettot(peer_net, 0, d1, sizeof(d1));
- subnettot(&sr->this.client, 0, s3, sizeof(s3));
- subnettot(&sr->that.client, 0, d3, sizeof(d3));
- DBG_log(" fc_try trying "
- "%s:%s:%d/%d -> %s:%d/%d vs %s:%s:%d/%d -> %s:%d/%d"
- , c->name, s1, c->spd.this.protocol, c->spd.this.port
- , d1, c->spd.that.protocol, c->spd.that.port
- , d->name, s3, sr->this.protocol, sr->this.port
- , d3, sr->that.protocol, sr->that.port);
- }
-#endif /* DEBUG */
+ if (d->policy & POLICY_GROUP)
+ continue;
- if (!samesubnet(&sr->this.client, our_net))
- continue;
+ if (!(same_id(&c->spd.this.id, &d->spd.this.id)
+ && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
+ && trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
+ && group_membership(peer_list, d->name, d->spd.that.groups)))
+ continue;
- if (sr->that.has_client)
- {
- if (sr->that.has_client_wildcard)
- {
- if (!subnetinsubnet(peer_net, &sr->that.client))
+ /* compare protocol and ports */
+ if (d->spd.this.protocol != our_protocol
+ || d->spd.this.port != our_port
+ || d->spd.that.protocol != peer_protocol
+ || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
continue;
- }
- else
+
+ /* non-Opportunistic case:
+ * our_client must match.
+ *
+ * So must peer_client, but the testing is complicated
+ * by the fact that the peer might be a wildcard
+ * and if so, the default value of that.client
+ * won't match the default peer_net. The appropriate test:
+ *
+ * If d has a peer client, it must match peer_net.
+ * If d has no peer client, peer_net must just have peer itself.
+ */
+
+ for (sr = &d->spd; best != d && sr != NULL; sr = sr->next)
{
- if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d))
- continue;
- if (is_virtual_connection(d)
- && (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr)
- || is_virtual_net_used(peer_net, peer_id?peer_id:&c->spd.that.id)))
- continue;
+ policy_prio_t prio;
+#ifdef DEBUG
+ if (DBGP(DBG_CONTROLMORE))
+ {
+ char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
+ char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF];
+
+ subnettot(our_net, 0, s1, sizeof(s1));
+ subnettot(peer_net, 0, d1, sizeof(d1));
+ subnettot(&sr->this.client, 0, s3, sizeof(s3));
+ subnettot(&sr->that.client, 0, d3, sizeof(d3));
+ DBG_log(" fc_try trying "
+ "%s:%s:%d/%d -> %s:%d/%d vs %s:%s:%d/%d -> %s:%d/%d"
+ , c->name, s1, c->spd.this.protocol, c->spd.this.port
+ , d1, c->spd.that.protocol, c->spd.that.port
+ , d->name, s3, sr->this.protocol, sr->this.port
+ , d3, sr->that.protocol, sr->that.port);
+ }
+#endif /* DEBUG */
+
+ if (!samesubnet(&sr->this.client, our_net))
+ continue;
+
+ if (sr->that.has_client)
+ {
+ if (sr->that.has_client_wildcard)
+ {
+ if (!subnetinsubnet(peer_net, &sr->that.client))
+ continue;
+ }
+ else
+ {
+ if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d))
+ continue;
+ if (is_virtual_connection(d)
+ && (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr)
+ || is_virtual_net_used(peer_net, peer_id?peer_id:&c->spd.that.id)))
+ continue;
+ }
+ }
+ else
+ {
+ if (!peer_net_is_host)
+ continue;
+ }
+
+ /* We've run the gauntlet -- success:
+ * We've got an exact match of subnets.
+ * The connection is feasible, but we continue looking for the best.
+ * The highest priority wins, implementing eroute-like rule.
+ * - a routed connection is preferrred
+ * - given that, the smallest number of ID wildcards are preferred
+ * - given that, the shortest CA pathlength is preferred
+ */
+ prio = PRIO_WEIGHT * routed(sr->routing)
+ + WILD_WEIGHT * (MAX_WILDCARDS - wildcards)
+ + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen)
+ + 1;
+ if (prio > best_prio)
+ {
+ best = d;
+ best_prio = prio;
+ }
}
- }
- else
- {
- if (!peer_net_is_host)
- continue;
- }
-
- /* We've run the gauntlet -- success:
- * We've got an exact match of subnets.
- * The connection is feasible, but we continue looking for the best.
- * The highest priority wins, implementing eroute-like rule.
- * - a routed connection is preferrred
- * - given that, the smallest number of ID wildcards are preferred
- * - given that, the shortest CA pathlength is preferred
- */
- prio = PRIO_WEIGHT * routed(sr->routing)
- + WILD_WEIGHT * (MAX_WILDCARDS - wildcards)
- + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen)
- + 1;
- if (prio > best_prio)
- {
- best = d;
- best_prio = prio;
- }
}
- }
- if (best != NULL && NEVER_NEGOTIATE(best->policy))
- best = NULL;
+ if (best != NULL && NEVER_NEGOTIATE(best->policy))
+ best = NULL;
- DBG(DBG_CONTROLMORE,
- DBG_log(" fc_try concluding with %s [%ld]"
- , (best ? best->name : "none"), best_prio)
- )
- return best;
+ DBG(DBG_CONTROLMORE,
+ DBG_log(" fc_try concluding with %s [%ld]"
+ , (best ? best->name : "none"), best_prio)
+ )
+ return best;
}
static struct connection *
@@ -3659,92 +3661,92 @@ fc_try_oppo(const struct connection *c
, chunk_t peer_ca
, const ietfAttrList_t *peer_list)
{
- struct connection *d;
- struct connection *best = NULL;
- policy_prio_t best_prio = BOTTOM_PRIO;
- int wildcards, pathlen;
+ struct connection *d;
+ struct connection *best = NULL;
+ policy_prio_t best_prio = BOTTOM_PRIO;
+ int wildcards, pathlen;
- for (d = hp->connections; d != NULL; d = d->hp_next)
- {
- struct spd_route *sr;
- policy_prio_t prio;
-
- if (d->policy & POLICY_GROUP)
- continue;
-
- if (!(same_id(&c->spd.this.id, &d->spd.this.id)
- && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
- && trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
- && group_membership(peer_list, d->name, d->spd.that.groups)))
- continue;
-
- /* compare protocol and ports */
- if (d->spd.this.protocol != our_protocol
- || d->spd.this.port != our_port
- || d->spd.that.protocol != peer_protocol
- || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
- continue;
-
- /* Opportunistic case:
- * our_net must be inside d->spd.this.client
- * and peer_net must be inside d->spd.that.client
- * Note: this host_pair chain also has shunt
- * eroute conns (clear, drop), but they won't
- * be marked as opportunistic.
- */
- for (sr = &d->spd; sr != NULL; sr = sr->next)
+ for (d = hp->connections; d != NULL; d = d->hp_next)
{
-#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
- char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF];
+ struct spd_route *sr;
+ policy_prio_t prio;
- subnettot(our_net, 0, s1, sizeof(s1));
- subnettot(peer_net, 0, d1, sizeof(d1));
- subnettot(&sr->this.client, 0, s3, sizeof(s3));
- subnettot(&sr->that.client, 0, d3, sizeof(d3));
- DBG_log(" fc_try_oppo trying %s:%s -> %s vs %s:%s -> %s"
- , c->name, s1, d1, d->name, s3, d3);
- }
+ if (d->policy & POLICY_GROUP)
+ continue;
+
+ if (!(same_id(&c->spd.this.id, &d->spd.this.id)
+ && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
+ && trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
+ && group_membership(peer_list, d->name, d->spd.that.groups)))
+ continue;
+
+ /* compare protocol and ports */
+ if (d->spd.this.protocol != our_protocol
+ || d->spd.this.port != our_port
+ || d->spd.that.protocol != peer_protocol
+ || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
+ continue;
+
+ /* Opportunistic case:
+ * our_net must be inside d->spd.this.client
+ * and peer_net must be inside d->spd.that.client
+ * Note: this host_pair chain also has shunt
+ * eroute conns (clear, drop), but they won't
+ * be marked as opportunistic.
+ */
+ for (sr = &d->spd; sr != NULL; sr = sr->next)
+ {
+#ifdef DEBUG
+ if (DBGP(DBG_CONTROLMORE))
+ {
+ char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
+ char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF];
+
+ subnettot(our_net, 0, s1, sizeof(s1));
+ subnettot(peer_net, 0, d1, sizeof(d1));
+ subnettot(&sr->this.client, 0, s3, sizeof(s3));
+ subnettot(&sr->that.client, 0, d3, sizeof(d3));
+ DBG_log(" fc_try_oppo trying %s:%s -> %s vs %s:%s -> %s"
+ , c->name, s1, d1, d->name, s3, d3);
+ }
#endif /* DEBUG */
- if (!subnetinsubnet(our_net, &sr->this.client)
- || !subnetinsubnet(peer_net, &sr->that.client))
- continue;
-
- /* The connection is feasible, but we continue looking for the best.
- * The highest priority wins, implementing eroute-like rule.
- * - our smallest client subnet is preferred (longest mask)
- * - given that, his smallest client subnet is preferred
- * - given that, a routed connection is preferrred
- * - given that, the smallest number of ID wildcards are preferred
- * - given that, the shortest CA pathlength is preferred
- */
- prio = PRIO_WEIGHT * (d->prio + routed(sr->routing))
- + WILD_WEIGHT * (MAX_WILDCARDS - wildcards)
- + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen);
- if (prio > best_prio)
- {
- best = d;
- best_prio = prio;
- }
+ if (!subnetinsubnet(our_net, &sr->this.client)
+ || !subnetinsubnet(peer_net, &sr->that.client))
+ continue;
+
+ /* The connection is feasible, but we continue looking for the best.
+ * The highest priority wins, implementing eroute-like rule.
+ * - our smallest client subnet is preferred (longest mask)
+ * - given that, his smallest client subnet is preferred
+ * - given that, a routed connection is preferrred
+ * - given that, the smallest number of ID wildcards are preferred
+ * - given that, the shortest CA pathlength is preferred
+ */
+ prio = PRIO_WEIGHT * (d->prio + routed(sr->routing))
+ + WILD_WEIGHT * (MAX_WILDCARDS - wildcards)
+ + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen);
+ if (prio > best_prio)
+ {
+ best = d;
+ best_prio = prio;
+ }
+ }
+ }
+
+ /* if the best wasn't opportunistic, we fail: it must be a shunt */
+ if (best != NULL
+ && (NEVER_NEGOTIATE(best->policy)
+ || (best->policy & POLICY_OPPO) == LEMPTY))
+ {
+ best = NULL;
}
- }
-
- /* if the best wasn't opportunistic, we fail: it must be a shunt */
- if (best != NULL
- && (NEVER_NEGOTIATE(best->policy)
- || (best->policy & POLICY_OPPO) == LEMPTY))
- {
- best = NULL;
- }
-
- DBG(DBG_CONTROLMORE,
- DBG_log(" fc_try_oppo concluding with %s [%ld]"
- , (best ? best->name : "none"), best_prio)
- )
- return best;
+
+ DBG(DBG_CONTROLMORE,
+ DBG_log(" fc_try_oppo concluding with %s [%ld]"
+ , (best ? best->name : "none"), best_prio)
+ )
+ return best;
}
@@ -3754,28 +3756,28 @@ fc_try_oppo(const struct connection *c
chunk_t
get_peer_ca_and_groups(struct connection *c, const ietfAttrList_t **peer_list)
{
- struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
-
- *peer_list = NULL;
+ struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
- if (p1st != NULL
- && p1st->st_peer_pubkey != NULL
- && p1st->st_peer_pubkey->issuer.ptr != NULL)
- {
- x509acert_t *ac = get_x509acert(p1st->st_peer_pubkey->issuer
- , p1st->st_peer_pubkey->serial);;
+ *peer_list = NULL;
- if (ac != NULL && verify_x509acert(ac, strict_crl_policy))
- *peer_list = ac->groups;
- else
+ if (p1st != NULL
+ && p1st->st_peer_pubkey != NULL
+ && p1st->st_peer_pubkey->issuer.ptr != NULL)
{
- DBG(DBG_CONTROL,
- DBG_log("no valid attribute cert found")
- )
+ x509acert_t *ac = get_x509acert(p1st->st_peer_pubkey->issuer
+ , p1st->st_peer_pubkey->serial);;
+
+ if (ac != NULL && verify_x509acert(ac, strict_crl_policy))
+ *peer_list = ac->groups;
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("no valid attribute cert found")
+ )
+ }
+ return p1st->st_peer_pubkey->issuer;
}
- return p1st->st_peer_pubkey->issuer;
- }
- return empty_chunk;
+ return chunk_empty;
}
struct connection *
@@ -3784,325 +3786,325 @@ find_client_connection(struct connection *c
, const u_int8_t our_protocol, const u_int16_t our_port
, const u_int8_t peer_protocol, const u_int16_t peer_port)
{
- struct connection *d;
- struct spd_route *sr;
+ struct connection *d;
+ struct spd_route *sr;
- const ietfAttrList_t *peer_list = NULL;
- chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_list);
+ const ietfAttrList_t *peer_list = NULL;
+ chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_list);
#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
-
- subnettot(our_net, 0, s1, sizeof(s1));
- subnettot(peer_net, 0, d1, sizeof(d1));
-
- DBG_log("find_client_connection starting with %s"
- , (c ? c->name : "(none)"));
- DBG_log(" looking for %s:%d/%d -> %s:%d/%d"
- , s1, our_protocol, our_port
- , d1, peer_protocol, peer_port);
- }
-#endif /* DEBUG */
+ if (DBGP(DBG_CONTROLMORE))
+ {
+ char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF];
- /* give priority to current connection
- * but even greater priority to a routed concrete connection
- */
- {
- struct connection *unrouted = NULL;
- int srnum = -1;
+ subnettot(our_net, 0, s1, sizeof(s1));
+ subnettot(peer_net, 0, d1, sizeof(d1));
+
+ DBG_log("find_client_connection starting with %s"
+ , (c ? c->name : "(none)"));
+ DBG_log(" looking for %s:%d/%d -> %s:%d/%d"
+ , s1, our_protocol, our_port
+ , d1, peer_protocol, peer_port);
+ }
+#endif /* DEBUG */
- for (sr = &c->spd; unrouted == NULL && sr != NULL; sr = sr->next)
+ /* give priority to current connection
+ * but even greater priority to a routed concrete connection
+ */
{
- srnum++;
+ struct connection *unrouted = NULL;
+ int srnum = -1;
+
+ for (sr = &c->spd; unrouted == NULL && sr != NULL; sr = sr->next)
+ {
+ srnum++;
#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
-
- subnettot(&sr->this.client, 0, s2, sizeof(s2));
- subnettot(&sr->that.client, 0, d2, sizeof(d2));
- DBG_log(" concrete checking against sr#%d %s -> %s"
- , srnum, s2, d2);
- }
+ if (DBGP(DBG_CONTROLMORE))
+ {
+ char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
+
+ subnettot(&sr->this.client, 0, s2, sizeof(s2));
+ subnettot(&sr->that.client, 0, d2, sizeof(d2));
+ DBG_log(" concrete checking against sr#%d %s -> %s"
+ , srnum, s2, d2);
+ }
#endif /* DEBUG */
- if (samesubnet(&sr->this.client, our_net)
- && samesubnet(&sr->that.client, peer_net)
- && sr->this.protocol == our_protocol
- && sr->this.port == our_port
- && sr->that.protocol == peer_protocol
- && sr->that.port == peer_port
- && group_membership(peer_list, c->name, sr->that.groups))
- {
- passert(oriented(*c));
- if (routed(sr->routing))
- return c;
-
- unrouted = c;
- }
- }
+ if (samesubnet(&sr->this.client, our_net)
+ && samesubnet(&sr->that.client, peer_net)
+ && sr->this.protocol == our_protocol
+ && sr->this.port == our_port
+ && sr->that.protocol == peer_protocol
+ && sr->that.port == peer_port
+ && group_membership(peer_list, c->name, sr->that.groups))
+ {
+ passert(oriented(*c));
+ if (routed(sr->routing))
+ return c;
- /* exact match? */
- d = fc_try(c, c->host_pair, NULL, our_net, peer_net
- , our_protocol, our_port, peer_protocol, peer_port
- , peer_ca, peer_list);
+ unrouted = c;
+ }
+ }
- DBG(DBG_CONTROLMORE,
- DBG_log(" fc_try %s gives %s"
- , c->name
- , (d ? d->name : "none"))
- )
+ /* exact match? */
+ d = fc_try(c, c->host_pair, NULL, our_net, peer_net
+ , our_protocol, our_port, peer_protocol, peer_port
+ , peer_ca, peer_list);
- if (d == NULL)
- d = unrouted;
- }
+ DBG(DBG_CONTROLMORE,
+ DBG_log(" fc_try %s gives %s"
+ , c->name
+ , (d ? d->name : "none"))
+ )
- if (d == NULL)
- {
- /* look for an abstract connection to match */
- struct spd_route *sr;
- struct host_pair *hp = NULL;
+ if (d == NULL)
+ d = unrouted;
+ }
- for (sr = &c->spd; hp==NULL && sr != NULL; sr = sr->next)
+ if (d == NULL)
{
- hp = find_host_pair(&sr->this.host_addr
- , sr->this.host_port
- , NULL
- , sr->that.host_port);
+ /* look for an abstract connection to match */
+ struct spd_route *sr;
+ struct host_pair *hp = NULL;
+
+ for (sr = &c->spd; hp==NULL && sr != NULL; sr = sr->next)
+ {
+ hp = find_host_pair(&sr->this.host_addr
+ , sr->this.host_port
+ , NULL
+ , sr->that.host_port);
#ifdef DEBUG
- if (DBGP(DBG_CONTROLMORE))
- {
- char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
+ if (DBGP(DBG_CONTROLMORE))
+ {
+ char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
- subnettot(&sr->this.client, 0, s2, sizeof(s2));
- subnettot(&sr->that.client, 0, d2, sizeof(d2));
+ subnettot(&sr->this.client, 0, s2, sizeof(s2));
+ subnettot(&sr->that.client, 0, d2, sizeof(d2));
- DBG_log(" checking hostpair %s -> %s is %s"
- , s2, d2
- , (hp ? "found" : "not found"));
- }
+ DBG_log(" checking hostpair %s -> %s is %s"
+ , s2, d2
+ , (hp ? "found" : "not found"));
+ }
#endif /* DEBUG */
- }
+ }
- if (hp != NULL)
- {
- /* RW match with actual peer_id or abstract peer_id? */
- d = fc_try(c, hp, NULL, our_net, peer_net
- , our_protocol, our_port, peer_protocol, peer_port
- , peer_ca, peer_list);
-
- if (d == NULL
- && subnetishost(our_net)
- && subnetishost(peer_net))
- {
- /* Opportunistic match?
- * Always use abstract peer_id.
- * Note that later instantiation will result in the same peer_id.
- */
- d = fc_try_oppo(c, hp, our_net, peer_net
- , our_protocol, our_port, peer_protocol, peer_port
- , peer_ca, peer_list);
- }
+ if (hp != NULL)
+ {
+ /* RW match with actual peer_id or abstract peer_id? */
+ d = fc_try(c, hp, NULL, our_net, peer_net
+ , our_protocol, our_port, peer_protocol, peer_port
+ , peer_ca, peer_list);
+
+ if (d == NULL
+ && subnetishost(our_net)
+ && subnetishost(peer_net))
+ {
+ /* Opportunistic match?
+ * Always use abstract peer_id.
+ * Note that later instantiation will result in the same peer_id.
+ */
+ d = fc_try_oppo(c, hp, our_net, peer_net
+ , our_protocol, our_port, peer_protocol, peer_port
+ , peer_ca, peer_list);
+ }
+ }
}
- }
- DBG(DBG_CONTROLMORE,
- DBG_log(" concluding with d = %s"
- , (d ? d->name : "none"))
- )
- return d;
+ DBG(DBG_CONTROLMORE,
+ DBG_log(" concluding with d = %s"
+ , (d ? d->name : "none"))
+ )
+ return d;
}
int
connection_compare(const struct connection *ca
, const struct connection *cb)
{
- int ret;
-
- /* DBG_log("comparing %s to %s", ca->name, cb->name); */
-
- ret = strcasecmp(ca->name, cb->name);
- if (ret != 0)
- return ret;
-
- ret = ca->kind - cb->kind; /* note: enum connection_kind behaves like int */
- if (ret != 0)
- return ret;
-
- /* same name, and same type */
- switch (ca->kind)
- {
- case CK_INSTANCE:
- return ca->instance_serial < cb->instance_serial ? -1
- : ca->instance_serial > cb->instance_serial ? 1
- : 0;
-
- default:
- return ca->prio < cb->prio ? -1
- : ca->prio > cb->prio ? 1
- : 0;
- }
+ int ret;
+
+ /* DBG_log("comparing %s to %s", ca->name, cb->name); */
+
+ ret = strcasecmp(ca->name, cb->name);
+ if (ret != 0)
+ return ret;
+
+ ret = ca->kind - cb->kind; /* note: enum connection_kind behaves like int */
+ if (ret != 0)
+ return ret;
+
+ /* same name, and same type */
+ switch (ca->kind)
+ {
+ case CK_INSTANCE:
+ return ca->instance_serial < cb->instance_serial ? -1
+ : ca->instance_serial > cb->instance_serial ? 1
+ : 0;
+
+ default:
+ return ca->prio < cb->prio ? -1
+ : ca->prio > cb->prio ? 1
+ : 0;
+ }
}
static int
connection_compare_qsort(const void *a, const void *b)
{
- return connection_compare(*(const struct connection *const *)a
- , *(const struct connection *const *)b);
+ return connection_compare(*(const struct connection *const *)a
+ , *(const struct connection *const *)b);
}
void
show_connections_status(bool all, const char *name)
{
- struct connection *c;
- int count, i;
- struct connection **array;
-
- /* make an array of connections, and sort it */
- count = 0;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->ikev1 && (name == NULL || streq(c->name, name)))
- count++;
- }
- array = alloc_bytes(sizeof(struct connection *)*count, "connection array");
-
- count=0;
- for (c = connections; c != NULL; c = c->ac_next)
- {
- if (c->ikev1 && (name == NULL || streq(c->name, name)))
- array[count++]=c;
- }
-
- /* sort it! */
- qsort(array, count, sizeof(struct connection *), connection_compare_qsort);
-
- for (i = 0; i < count; i++)
- {
- const char *ifn;
- char instance[1 + 10 + 1];
- char prio[POLICY_PRIO_BUF];
-
- c = array[i];
-
- ifn = oriented(*c)? c->interface->rname : "";
-
- instance[0] = '\0';
- if (c->kind == CK_INSTANCE && c->instance_serial != 0)
- snprintf(instance, sizeof(instance), "[%lu]", c->instance_serial);
-
- /* show topology */
+ struct connection *c;
+ int count, i;
+ struct connection **array;
+
+ /* make an array of connections, and sort it */
+ count = 0;
+ for (c = connections; c != NULL; c = c->ac_next)
{
- char topo[CONNECTION_BUF];
- struct spd_route *sr = &c->spd;
- int num=0;
-
- while (sr != NULL)
- {
- (void) format_connection(topo, sizeof(topo), c, sr);
- whack_log(RC_COMMENT, "\"%s\"%s: %s; %s; eroute owner: #%lu"
- , c->name, instance, topo
- , enum_name(&routing_story, sr->routing)
- , sr->eroute_owner);
- sr = sr->next;
- num++;
- }
+ if (c->ikev1 && (name == NULL || streq(c->name, name)))
+ count++;
}
+ array = malloc(sizeof(struct connection *)*count);
- if (all)
+ count=0;
+ for (c = connections; c != NULL; c = c->ac_next)
{
- /* show CAs if defined */
- if (c->spd.this.ca.ptr != NULL || c->spd.that.ca.ptr != NULL)
- {
- char this_ca[BUF_LEN], that_ca[BUF_LEN];
-
- dntoa_or_null(this_ca, BUF_LEN, c->spd.this.ca, "%any");
- dntoa_or_null(that_ca, BUF_LEN, c->spd.that.ca, "%any");
-
- whack_log(RC_COMMENT
- , "\"%s\"%s: CAs: '%s'...'%s'"
- , c->name
- , instance
- , this_ca
- , that_ca);
- }
-
- /* show group attributes if defined */
- if (c->spd.that.groups != NULL)
- {
- char buf[BUF_LEN];
-
- format_groups(c->spd.that.groups, buf, BUF_LEN);
- whack_log(RC_COMMENT
- , "\"%s\"%s: groups: %s"
- , c->name
- , instance
- , buf);
- }
-
- whack_log(RC_COMMENT
- , "\"%s\"%s: ike_life: %lus; ipsec_life: %lus;"
- " rekey_margin: %lus; rekey_fuzz: %lu%%; keyingtries: %lu"
- , c->name
- , instance
- , (unsigned long) c->sa_ike_life_seconds
- , (unsigned long) c->sa_ipsec_life_seconds
- , (unsigned long) c->sa_rekey_margin
- , (unsigned long) c->sa_rekey_fuzz
- , (unsigned long) c->sa_keying_tries);
-
- /* show DPD parameters if defined */
-
- if (c->dpd_action != DPD_ACTION_NONE)
- whack_log(RC_COMMENT
- , "\"%s\"%s: dpd_action: %s;"
- " dpd_delay: %lus; dpd_timeout: %lus;"
- , c->name
- , instance
- , enum_show(&dpd_action_names, c->dpd_action)
- , (unsigned long) c->dpd_delay
- , (unsigned long) c->dpd_timeout);
-
- if (c->policy_next)
- {
- whack_log(RC_COMMENT
- , "\"%s\"%s: policy_next: %s"
- , c->name, instance, c->policy_next->name);
- }
-
- /* Note: we display key_from_DNS_on_demand as if policy [lr]KOD */
- fmt_policy_prio(c->prio, prio);
- whack_log(RC_COMMENT
- , "\"%s\"%s: policy: %s%s%s; prio: %s; interface: %s; "
- , c->name
- , instance
- , prettypolicy(c->policy)
- , c->spd.this.key_from_DNS_on_demand? "+lKOD" : ""
- , c->spd.that.key_from_DNS_on_demand? "+rKOD" : ""
- , prio
- , ifn);
+ if (c->ikev1 && (name == NULL || streq(c->name, name)))
+ array[count++]=c;
}
- whack_log(RC_COMMENT
- , "\"%s\"%s: newest ISAKMP SA: #%ld; newest IPsec SA: #%ld; "
- , c->name
- , instance
- , c->newest_isakmp_sa
- , c->newest_ipsec_sa);
-
- if (all)
+ /* sort it! */
+ qsort(array, count, sizeof(struct connection *), connection_compare_qsort);
+
+ for (i = 0; i < count; i++)
{
- ike_alg_show_connection(c, instance);
- kernel_alg_show_connection(c, instance);
+ const char *ifn;
+ char instance[1 + 10 + 1];
+ char prio[POLICY_PRIO_BUF];
+
+ c = array[i];
+
+ ifn = oriented(*c)? c->interface->rname : "";
+
+ instance[0] = '\0';
+ if (c->kind == CK_INSTANCE && c->instance_serial != 0)
+ snprintf(instance, sizeof(instance), "[%lu]", c->instance_serial);
+
+ /* show topology */
+ {
+ char topo[CONNECTION_BUF];
+ struct spd_route *sr = &c->spd;
+ int num=0;
+
+ while (sr != NULL)
+ {
+ (void) format_connection(topo, sizeof(topo), c, sr);
+ whack_log(RC_COMMENT, "\"%s\"%s: %s; %s; eroute owner: #%lu"
+ , c->name, instance, topo
+ , enum_name(&routing_story, sr->routing)
+ , sr->eroute_owner);
+ sr = sr->next;
+ num++;
+ }
+ }
+
+ if (all)
+ {
+ /* show CAs if defined */
+ if (c->spd.this.ca.ptr != NULL || c->spd.that.ca.ptr != NULL)
+ {
+ char this_ca[BUF_LEN], that_ca[BUF_LEN];
+
+ dntoa_or_null(this_ca, BUF_LEN, c->spd.this.ca, "%any");
+ dntoa_or_null(that_ca, BUF_LEN, c->spd.that.ca, "%any");
+
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: CAs: '%s'...'%s'"
+ , c->name
+ , instance
+ , this_ca
+ , that_ca);
+ }
+
+ /* show group attributes if defined */
+ if (c->spd.that.groups != NULL)
+ {
+ char buf[BUF_LEN];
+
+ format_groups(c->spd.that.groups, buf, BUF_LEN);
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: groups: %s"
+ , c->name
+ , instance
+ , buf);
+ }
+
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: ike_life: %lus; ipsec_life: %lus;"
+ " rekey_margin: %lus; rekey_fuzz: %lu%%; keyingtries: %lu"
+ , c->name
+ , instance
+ , (unsigned long) c->sa_ike_life_seconds
+ , (unsigned long) c->sa_ipsec_life_seconds
+ , (unsigned long) c->sa_rekey_margin
+ , (unsigned long) c->sa_rekey_fuzz
+ , (unsigned long) c->sa_keying_tries);
+
+ /* show DPD parameters if defined */
+
+ if (c->dpd_action != DPD_ACTION_NONE)
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: dpd_action: %N;"
+ " dpd_delay: %lus; dpd_timeout: %lus;"
+ , c->name
+ , instance
+ , dpd_action_names, c->dpd_action
+ , (unsigned long) c->dpd_delay
+ , (unsigned long) c->dpd_timeout);
+
+ if (c->policy_next)
+ {
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: policy_next: %s"
+ , c->name, instance, c->policy_next->name);
+ }
+
+ /* Note: we display key_from_DNS_on_demand as if policy [lr]KOD */
+ fmt_policy_prio(c->prio, prio);
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: policy: %s%s%s; prio: %s; interface: %s; "
+ , c->name
+ , instance
+ , prettypolicy(c->policy)
+ , c->spd.this.key_from_DNS_on_demand? "+lKOD" : ""
+ , c->spd.that.key_from_DNS_on_demand? "+rKOD" : ""
+ , prio
+ , ifn);
+ }
+
+ whack_log(RC_COMMENT
+ , "\"%s\"%s: newest ISAKMP SA: #%ld; newest IPsec SA: #%ld; "
+ , c->name
+ , instance
+ , c->newest_isakmp_sa
+ , c->newest_ipsec_sa);
+
+ if (all)
+ {
+ ike_alg_show_connection(c, instance);
+ kernel_alg_show_connection(c, instance);
+ }
}
- }
- if (count > 0)
- whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
+ if (count > 0)
+ whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
- pfree(array);
+ free(array);
}
/* struct pending, the structure representing Quick Mode
@@ -4111,14 +4113,14 @@ show_connections_status(bool all, const char *name)
*/
struct pending {
- int whack_sock;
- struct state *isakmp_sa;
- struct connection *connection;
- lset_t policy;
- unsigned long try;
- so_serial_t replacing;
-
- struct pending *next;
+ int whack_sock;
+ struct state *isakmp_sa;
+ struct connection *connection;
+ lset_t policy;
+ unsigned long try;
+ so_serial_t replacing;
+
+ struct pending *next;
};
/* queue a Quick Mode negotiation pending completion of a suitable Main Mode */
@@ -4130,36 +4132,36 @@ add_pending(int whack_sock
, unsigned long try
, so_serial_t replacing)
{
- bool already_queued = FALSE;
- struct pending *p = c->host_pair->pending;
+ bool already_queued = FALSE;
+ struct pending *p = c->host_pair->pending;
- while (p != NULL)
- {
- if (streq(c->name, p->connection->name))
+ while (p != NULL)
{
- already_queued = TRUE;
- break;
+ if (streq(c->name, p->connection->name))
+ {
+ already_queued = TRUE;
+ break;
+ }
+ p = p->next;
}
- p = p->next;
- }
- DBG(DBG_CONTROL,
- DBG_log("Queuing pending Quick Mode with %s \"%s\"%s"
- , ip_str(&c->spd.that.host_addr)
- , c->name
- , already_queued? " already done" : "")
- )
- if (already_queued)
- return;
-
- p = alloc_thing(struct pending, "struct pending");
- p->whack_sock = whack_sock;
- p->isakmp_sa = isakmp_sa;
- p->connection = c;
- p->policy = policy;
- p->try = try;
- p->replacing = replacing;
- p->next = c->host_pair->pending;
- c->host_pair->pending = p;
+ DBG(DBG_CONTROL,
+ DBG_log("Queuing pending Quick Mode with %s \"%s\"%s"
+ , ip_str(&c->spd.that.host_addr)
+ , c->name
+ , already_queued? " already done" : "")
+ )
+ if (already_queued)
+ return;
+
+ p = malloc_thing(struct pending);
+ p->whack_sock = whack_sock;
+ p->isakmp_sa = isakmp_sa;
+ p->connection = c;
+ p->policy = policy;
+ p->try = try;
+ p->replacing = replacing;
+ p->next = c->host_pair->pending;
+ c->host_pair->pending = p;
}
/* Release all the whacks awaiting the completion of this state.
@@ -4169,157 +4171,157 @@ add_pending(int whack_sock
void
release_pending_whacks(struct state *st, err_t story)
{
- struct pending *p;
- struct stat stst;
+ struct pending *p;
+ struct stat stst;
- if (st->st_whack_sock == NULL_FD || fstat(st->st_whack_sock, &stst) != 0)
- zero(&stst); /* resulting st_dev/st_ino ought to be distinct */
+ if (st->st_whack_sock == NULL_FD || fstat(st->st_whack_sock, &stst) != 0)
+ zero(&stst); /* resulting st_dev/st_ino ought to be distinct */
- release_whack(st);
+ release_whack(st);
- for (p = st->st_connection->host_pair->pending; p != NULL; p = p->next)
- {
- if (p->isakmp_sa == st && p->whack_sock != NULL_FD)
+ for (p = st->st_connection->host_pair->pending; p != NULL; p = p->next)
{
- struct stat pst;
+ if (p->isakmp_sa == st && p->whack_sock != NULL_FD)
+ {
+ struct stat pst;
- if (fstat(p->whack_sock, &pst) == 0
- && (stst.st_dev != pst.st_dev || stst.st_ino != pst.st_ino))
- {
- passert(whack_log_fd == NULL_FD);
- whack_log_fd = p->whack_sock;
- whack_log(RC_COMMENT
- , "%s for ISAKMP SA, but releasing whack for pending IPSEC SA"
- , story);
- whack_log_fd = NULL_FD;
- }
- close(p->whack_sock);
- p->whack_sock = NULL_FD;
+ if (fstat(p->whack_sock, &pst) == 0
+ && (stst.st_dev != pst.st_dev || stst.st_ino != pst.st_ino))
+ {
+ passert(whack_log_fd == NULL_FD);
+ whack_log_fd = p->whack_sock;
+ whack_log(RC_COMMENT
+ , "%s for ISAKMP SA, but releasing whack for pending IPSEC SA"
+ , story);
+ whack_log_fd = NULL_FD;
+ }
+ close(p->whack_sock);
+ p->whack_sock = NULL_FD;
+ }
}
- }
}
static void
delete_pending(struct pending **pp)
{
- struct pending *p = *pp;
+ struct pending *p = *pp;
- *pp = p->next;
- if (p->connection != NULL)
- connection_discard(p->connection);
- close_any(p->whack_sock);
- pfree(p);
+ *pp = p->next;
+ if (p->connection != NULL)
+ connection_discard(p->connection);
+ close_any(p->whack_sock);
+ free(p);
}
void
unpend(struct state *st)
{
- struct pending **pp
- , *p;
+ struct pending **pp
+ , *p;
- for (pp = &st->st_connection->host_pair->pending; (p = *pp) != NULL; )
- {
- if (p->isakmp_sa == st)
- {
- DBG(DBG_CONTROL, DBG_log("unqueuing pending Quick Mode with %s \"%s\""
- , ip_str(&p->connection->spd.that.host_addr)
- , p->connection->name));
- (void) quick_outI1(p->whack_sock, st, p->connection, p->policy
- , p->try, p->replacing);
- p->whack_sock = NULL_FD; /* ownership transferred */
- p->connection = NULL; /* ownership transferred */
- delete_pending(pp);
- }
- else
+ for (pp = &st->st_connection->host_pair->pending; (p = *pp) != NULL; )
{
- pp = &p->next;
+ if (p->isakmp_sa == st)
+ {
+ DBG(DBG_CONTROL, DBG_log("unqueuing pending Quick Mode with %s \"%s\""
+ , ip_str(&p->connection->spd.that.host_addr)
+ , p->connection->name));
+ (void) quick_outI1(p->whack_sock, st, p->connection, p->policy
+ , p->try, p->replacing);
+ p->whack_sock = NULL_FD; /* ownership transferred */
+ p->connection = NULL; /* ownership transferred */
+ delete_pending(pp);
+ }
+ else
+ {
+ pp = &p->next;
+ }
}
- }
}
/* a Main Mode negotiation has been replaced; update any pending */
void
update_pending(struct state *os, struct state *ns)
{
- struct pending *p;
+ struct pending *p;
- for (p = os->st_connection->host_pair->pending; p != NULL; p = p->next)
- {
- if (p->isakmp_sa == os)
- p->isakmp_sa = ns;
- if (p->connection->spd.this.host_port != ns->st_connection->spd.this.host_port)
+ for (p = os->st_connection->host_pair->pending; p != NULL; p = p->next)
{
- p->connection->spd.this.host_port = ns->st_connection->spd.this.host_port;
- p->connection->spd.that.host_port = ns->st_connection->spd.that.host_port;
+ if (p->isakmp_sa == os)
+ p->isakmp_sa = ns;
+ if (p->connection->spd.this.host_port != ns->st_connection->spd.this.host_port)
+ {
+ p->connection->spd.this.host_port = ns->st_connection->spd.this.host_port;
+ p->connection->spd.that.host_port = ns->st_connection->spd.that.host_port;
+ }
}
- }
}
/* a Main Mode negotiation has failed; discard any pending */
void
flush_pending_by_state(struct state *st)
{
- struct host_pair *hp = st->st_connection->host_pair;
-
- if (hp != NULL)
- {
- struct pending **pp
- , *p;
+ struct host_pair *hp = st->st_connection->host_pair;
- for (pp = &hp->pending; (p = *pp) != NULL; )
+ if (hp != NULL)
{
- if (p->isakmp_sa == st)
- delete_pending(pp);
- else
- pp = &p->next;
+ struct pending **pp
+ , *p;
+
+ for (pp = &hp->pending; (p = *pp) != NULL; )
+ {
+ if (p->isakmp_sa == st)
+ delete_pending(pp);
+ else
+ pp = &p->next;
+ }
}
- }
}
/* a connection has been deleted; discard any related pending */
static void
flush_pending_by_connection(struct connection *c)
{
- if (c->host_pair != NULL)
- {
- struct pending **pp
- , *p;
-
- for (pp = &c->host_pair->pending; (p = *pp) != NULL; )
+ if (c->host_pair != NULL)
{
- if (p->connection == c)
- {
- p->connection = NULL; /* prevent delete_pending from releasing */
- delete_pending(pp);
- }
- else
- {
- pp = &p->next;
- }
+ struct pending **pp
+ , *p;
+
+ for (pp = &c->host_pair->pending; (p = *pp) != NULL; )
+ {
+ if (p->connection == c)
+ {
+ p->connection = NULL; /* prevent delete_pending from releasing */
+ delete_pending(pp);
+ }
+ else
+ {
+ pp = &p->next;
+ }
+ }
}
- }
}
void
show_pending_phase2(const struct host_pair *hp, const struct state *st)
{
- const struct pending *p;
+ const struct pending *p;
- for (p = hp->pending; p != NULL; p = p->next)
- {
- if (p->isakmp_sa == st)
+ for (p = hp->pending; p != NULL; p = p->next)
{
- /* connection-name state-number [replacing state-number] */
- char cip[CONN_INST_BUF];
-
- fmt_conn_instance(p->connection, cip);
- whack_log(RC_COMMENT, "#%lu: pending Phase 2 for \"%s\"%s replacing #%lu"
- , p->isakmp_sa->st_serialno
- , p->connection->name
- , cip
- , p->replacing);
+ if (p->isakmp_sa == st)
+ {
+ /* connection-name state-number [replacing state-number] */
+ char cip[CONN_INST_BUF];
+
+ fmt_conn_instance(p->connection, cip);
+ whack_log(RC_COMMENT, "#%lu: pending Phase 2 for \"%s\"%s replacing #%lu"
+ , p->isakmp_sa->st_serialno
+ , p->connection->name
+ , cip
+ , p->replacing);
+ }
}
- }
}
/* Delete a connection if it is an instance and it is no longer in use.
@@ -4329,18 +4331,18 @@ show_pending_phase2(const struct host_pair *hp, const struct state *st)
void
connection_discard(struct connection *c)
{
- if (c->kind == CK_INSTANCE)
- {
- /* see if it is being used by a pending */
- struct pending *p;
+ if (c->kind == CK_INSTANCE)
+ {
+ /* see if it is being used by a pending */
+ struct pending *p;
- for (p = c->host_pair->pending; p != NULL; p = p->next)
- if (p->connection == c)
- return; /* in use, so we're done */
+ for (p = c->host_pair->pending; p != NULL; p = p->next)
+ if (p->connection == c)
+ return; /* in use, so we're done */
- if (!states_use_connection(c))
- delete_connection(c, FALSE);
- }
+ if (!states_use_connection(c))
+ delete_connection(c, FALSE);
+ }
}
@@ -4354,32 +4356,32 @@ long eclipse_count = 0;
struct connection *
eclipsed(struct connection *c, struct spd_route **esrp)
{
- struct connection *ue;
- struct spd_route *sr1 = &c->spd;
+ struct connection *ue;
+ struct spd_route *sr1 = &c->spd;
- ue = NULL;
+ ue = NULL;
- while (sr1 != NULL && ue != NULL)
- {
- for (ue = connections; ue != NULL; ue = ue->ac_next)
+ while (sr1 != NULL && ue != NULL)
{
- struct spd_route *srue = &ue->spd;
-
- while (srue != NULL
- && srue->routing == RT_ROUTED_ECLIPSED
- && !(samesubnet(&sr1->this.client, &srue->this.client)
- && samesubnet(&sr1->that.client, &srue->that.client)))
- {
- srue = srue->next;
- }
- if (srue != NULL && srue->routing==RT_ROUTED_ECLIPSED)
- {
- *esrp = srue;
- break;
- }
+ for (ue = connections; ue != NULL; ue = ue->ac_next)
+ {
+ struct spd_route *srue = &ue->spd;
+
+ while (srue != NULL
+ && srue->routing == RT_ROUTED_ECLIPSED
+ && !(samesubnet(&sr1->this.client, &srue->this.client)
+ && samesubnet(&sr1->that.client, &srue->that.client)))
+ {
+ srue = srue->next;
+ }
+ if (srue != NULL && srue->routing==RT_ROUTED_ECLIPSED)
+ {
+ *esrp = srue;
+ break;
+ }
+ }
}
- }
- return ue;
+ return ue;
}
/*