summaryrefslogtreecommitdiff
path: root/src/pluto/state.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/state.c')
-rw-r--r--src/pluto/state.c1358
1 files changed, 674 insertions, 684 deletions
diff --git a/src/pluto/state.c b/src/pluto/state.c
index 5372e86f5..6ce0d50e5 100644
--- a/src/pluto/state.c
+++ b/src/pluto/state.c
@@ -11,8 +11,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: state.c 4924 2009-03-10 21:13:18Z andreas $
*/
#include <stdio.h>
@@ -28,29 +26,28 @@
#include <freeswan.h>
+#include <library.h>
+#include <crypto/rngs/rng.h>
+
#include "constants.h"
#include "defs.h"
#include "connections.h"
#include "state.h"
#include "kernel.h"
#include "log.h"
-#include "packet.h" /* so we can calculate sizeof(struct isakmp_hdr) */
-#include "keys.h" /* for free_public_key */
-#include "rnd.h"
+#include "packet.h" /* so we can calculate sizeof(struct isakmp_hdr) */
+#include "keys.h" /* for free_public_key */
#include "timer.h"
#include "whack.h"
-#include "demux.h" /* needs packet.h */
-#include "ipsec_doi.h" /* needs demux.h and state.h */
-
-#include "sha1.h"
-#include "md5.h"
-#include "crypto.h" /* requires sha1.h and md5.h */
+#include "demux.h" /* needs packet.h */
+#include "ipsec_doi.h" /* needs demux.h and state.h */
+#include "crypto.h"
/*
* Global variables: had to go somewhere, might as well be this file.
*/
-u_int16_t pluto_port = IKE_UDP_PORT; /* Pluto's port */
+u_int16_t pluto_port = IKE_UDP_PORT; /* Pluto's port */
/*
* This file has the functions that handle the
@@ -79,51 +76,53 @@ u_int16_t pluto_port = IKE_UDP_PORT; /* Pluto's port */
struct msgid_list
{
- msgid_t msgid; /* network order */
- struct msgid_list *next;
+ msgid_t msgid; /* network order */
+ struct msgid_list *next;
};
-bool
-reserve_msgid(struct state *isakmp_sa, msgid_t msgid)
+bool reserve_msgid(struct state *isakmp_sa, msgid_t msgid)
{
- struct msgid_list *p;
+ struct msgid_list *p;
- passert(msgid != MAINMODE_MSGID);
- passert(IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state));
+ passert(msgid != MAINMODE_MSGID);
+ passert(IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state));
- for (p = isakmp_sa->st_used_msgids; p != NULL; p = p->next)
- if (p->msgid == msgid)
- return FALSE;
+ for (p = isakmp_sa->st_used_msgids; p != NULL; p = p->next)
+ if (p->msgid == msgid)
+ return FALSE;
- p = alloc_thing(struct msgid_list, "msgid");
- p->msgid = msgid;
- p->next = isakmp_sa->st_used_msgids;
- isakmp_sa->st_used_msgids = p;
- return TRUE;
+ p = malloc_thing(struct msgid_list);
+ p->msgid = msgid;
+ p->next = isakmp_sa->st_used_msgids;
+ isakmp_sa->st_used_msgids = p;
+ return TRUE;
}
-msgid_t
-generate_msgid(struct state *isakmp_sa)
+msgid_t generate_msgid(struct state *isakmp_sa)
{
- int timeout = 100; /* only try so hard for unique msgid */
- msgid_t msgid;
+ int timeout = 100; /* only try so hard for unique msgid */
+ msgid_t msgid;
+ rng_t *rng;
- passert(IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state));
+ passert(IS_ISAKMP_ENCRYPTED(isakmp_sa->st_state));
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- for (;;)
- {
- get_rnd_bytes((void *) &msgid, sizeof(msgid));
- if (msgid != 0 && reserve_msgid(isakmp_sa, msgid))
- break;
-
- if (--timeout == 0)
+ for (;;)
{
- plog("gave up looking for unique msgid; using 0x%08lx"
- , (unsigned long) msgid);
- break;
+ rng->get_bytes(rng, sizeof(msgid), (void *) &msgid);
+ if (msgid != 0 && reserve_msgid(isakmp_sa, msgid))
+ {
+ break;
+ }
+ if (--timeout == 0)
+ {
+ plog("gave up looking for unique msgid; using 0x%08lx"
+ , (unsigned long) msgid);
+ break;
+ }
}
- }
- return msgid;
+ rng->destroy(rng);
+ return msgid;
}
@@ -133,63 +132,61 @@ generate_msgid(struct state *isakmp_sa)
static struct state *statetable[STATE_TABLE_SIZE];
-static struct state **
-state_hash(const u_char *icookie, const u_char *rcookie, const ip_address *peer)
+static struct state **state_hash(const u_char *icookie, const u_char *rcookie,
+ const ip_address *peer)
{
- u_int i = 0, j;
- const unsigned char *byte_ptr;
- size_t length = addrbytesptr(peer, &byte_ptr);
+ u_int i = 0, j;
+ const unsigned char *byte_ptr;
+ size_t length = addrbytesptr(peer, &byte_ptr);
- DBG(DBG_RAW | DBG_CONTROL,
- DBG_dump("ICOOKIE:", icookie, COOKIE_SIZE);
- DBG_dump("RCOOKIE:", rcookie, COOKIE_SIZE);
- DBG_dump("peer:", byte_ptr, length));
+ DBG(DBG_RAW | DBG_CONTROL,
+ DBG_dump("ICOOKIE:", icookie, COOKIE_SIZE);
+ DBG_dump("RCOOKIE:", rcookie, COOKIE_SIZE);
+ DBG_dump("peer:", byte_ptr, length));
- /* XXX the following hash is pretty pathetic */
+ /* XXX the following hash is pretty pathetic */
- for (j = 0; j < COOKIE_SIZE; j++)
- i = i * 407 + icookie[j] + rcookie[j];
+ for (j = 0; j < COOKIE_SIZE; j++)
+ i = i * 407 + icookie[j] + rcookie[j];
- for (j = 0; j < length; j++)
- i = i * 613 + byte_ptr[j];
+ for (j = 0; j < length; j++)
+ i = i * 613 + byte_ptr[j];
- i = i % STATE_TABLE_SIZE;
+ i = i % STATE_TABLE_SIZE;
- DBG(DBG_CONTROL, DBG_log("state hash entry %d", i));
+ DBG(DBG_CONTROL, DBG_log("state hash entry %d", i));
- return &statetable[i];
+ return &statetable[i];
}
/* Get a state object.
* Caller must schedule an event for this object so that it doesn't leak.
* Caller must insert_state().
*/
-struct state *
-new_state(void)
+struct state *new_state(void)
{
- static const struct state blank_state; /* initialized all to zero & NULL */
- static so_serial_t next_so = SOS_FIRST;
- struct state *st;
-
- st = clone_thing(blank_state, "struct state in new_state()");
- st->st_serialno = next_so++;
- passert(next_so > SOS_FIRST); /* overflow can't happen! */
- st->st_whack_sock = NULL_FD;
- DBG(DBG_CONTROL, DBG_log("creating state object #%lu at %p",
- st->st_serialno, (void *) st));
- return st;
+ static const struct state blank_state; /* initialized all to zero & NULL */
+ static so_serial_t next_so = SOS_FIRST;
+ struct state *st;
+
+ st = clone_thing(blank_state);
+ st->st_serialno = next_so++;
+ passert(next_so > SOS_FIRST); /* overflow can't happen! */
+ st->st_whack_sock = NULL_FD;
+ DBG(DBG_CONTROL, DBG_log("creating state object #%lu at %p",
+ st->st_serialno, (void *) st));
+ return st;
}
/*
* Initialize the state table (and mask*).
*/
-void
-init_states(void)
+void init_states(void)
{
- int i;
+ int i;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- statetable[i] = (struct state *) NULL;
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
+ statetable[i] = (struct state *) NULL;
}
/* Find the state object with this serial number.
@@ -199,627 +196,619 @@ init_states(void)
* If this turns out to be a significant CPU hog, it could be
* improved to use a hash table rather than sequential seartch.
*/
-struct state *
-state_with_serialno(so_serial_t sn)
+struct state *state_with_serialno(so_serial_t sn)
{
- if (sn >= SOS_FIRST)
- {
- struct state *st;
- int i;
+ if (sn >= SOS_FIRST)
+ {
+ struct state *st;
+ int i;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (st->st_serialno == sn)
- return st;
- }
- return NULL;
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ if (st->st_serialno == sn)
+ return st;
+ }
+ return NULL;
}
/* Insert a state object in the hash table. The object is inserted
* at the begining of list.
* Needs cookies, connection, and msgid.
*/
-void
-insert_state(struct state *st)
+void insert_state(struct state *st)
{
- struct state **p = state_hash(st->st_icookie, st->st_rcookie
- , &st->st_connection->spd.that.host_addr);
-
- passert(st->st_hashchain_prev == NULL && st->st_hashchain_next == NULL);
-
- if (*p != NULL)
- {
- passert((*p)->st_hashchain_prev == NULL);
- (*p)->st_hashchain_prev = st;
- }
- st->st_hashchain_next = *p;
- *p = st;
-
- /* Ensure that somebody is in charge of killing this state:
- * if no event is scheduled for it, schedule one to discard the state.
- * If nothing goes wrong, this event will be replaced by
- * a more appropriate one.
- */
- if (st->st_event == NULL)
- event_schedule(EVENT_SO_DISCARD, 0, st);
+ struct state **p = state_hash(st->st_icookie, st->st_rcookie
+ , &st->st_connection->spd.that.host_addr);
+
+ passert(st->st_hashchain_prev == NULL && st->st_hashchain_next == NULL);
+
+ if (*p != NULL)
+ {
+ passert((*p)->st_hashchain_prev == NULL);
+ (*p)->st_hashchain_prev = st;
+ }
+ st->st_hashchain_next = *p;
+ *p = st;
+
+ /* Ensure that somebody is in charge of killing this state:
+ * if no event is scheduled for it, schedule one to discard the state.
+ * If nothing goes wrong, this event will be replaced by
+ * a more appropriate one.
+ */
+ if (st->st_event == NULL)
+ event_schedule(EVENT_SO_DISCARD, 0, st);
}
/* unlink a state object from the hash table, but don't free it
*/
-void
-unhash_state(struct state *st)
+void unhash_state(struct state *st)
{
- /* unlink from forward chain */
- struct state **p = st->st_hashchain_prev == NULL
- ? state_hash(st->st_icookie, st->st_rcookie
- , &st->st_connection->spd.that.host_addr)
- : &st->st_hashchain_prev->st_hashchain_next;
-
- /* unlink from forward chain */
- passert(*p == st);
- *p = st->st_hashchain_next;
-
- /* unlink from backward chain */
- if (st->st_hashchain_next != NULL)
- {
- passert(st->st_hashchain_next->st_hashchain_prev == st);
- st->st_hashchain_next->st_hashchain_prev = st->st_hashchain_prev;
- }
-
- st->st_hashchain_next = st->st_hashchain_prev = NULL;
+ /* unlink from forward chain */
+ struct state **p = st->st_hashchain_prev == NULL
+ ? state_hash(st->st_icookie, st->st_rcookie
+ , &st->st_connection->spd.that.host_addr)
+ : &st->st_hashchain_prev->st_hashchain_next;
+
+ /* unlink from forward chain */
+ passert(*p == st);
+ *p = st->st_hashchain_next;
+
+ /* unlink from backward chain */
+ if (st->st_hashchain_next != NULL)
+ {
+ passert(st->st_hashchain_next->st_hashchain_prev == st);
+ st->st_hashchain_next->st_hashchain_prev = st->st_hashchain_prev;
+ }
+
+ st->st_hashchain_next = st->st_hashchain_prev = NULL;
}
/* Free the Whack socket file descriptor.
* This has the side effect of telling Whack that we're done.
*/
-void
-release_whack(struct state *st)
+void release_whack(struct state *st)
{
- close_any(st->st_whack_sock);
+ close_any(st->st_whack_sock);
}
-/* delete a state object */
-void
-delete_state(struct state *st)
+/**
+ * Delete a state object
+ */
+void delete_state(struct state *st)
{
- struct connection *const c = st->st_connection;
- struct state *old_cur_state = cur_state == st? NULL : cur_state;
-
- set_cur_state(st);
+ struct connection *const c = st->st_connection;
+ struct state *old_cur_state = cur_state == st? NULL : cur_state;
- /* If DPD is enabled on this state object, clear any pending events */
- if(st->st_dpd_event != NULL)
- delete_dpd_event(st);
+ set_cur_state(st);
- /* if there is a suspended state transition, disconnect us */
- if (st->st_suspended_md != NULL)
- {
- passert(st->st_suspended_md->st == st);
- st->st_suspended_md->st = NULL;
- }
+ /* If DPD is enabled on this state object, clear any pending events */
+ if(st->st_dpd_event != NULL)
+ delete_dpd_event(st);
- /* tell the other side of any IPSEC SAs that are going down */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- || IS_ISAKMP_SA_ESTABLISHED(st->st_state))
- send_delete(st);
+ /* if there is a suspended state transition, disconnect us */
+ if (st->st_suspended_md != NULL)
+ {
+ passert(st->st_suspended_md->st == st);
+ st->st_suspended_md->st = NULL;
+ }
- delete_event(st); /* delete any pending timer event */
+ /* tell the other side of any IPSEC SAs that are going down */
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
+ || IS_ISAKMP_SA_ESTABLISHED(st->st_state))
+ send_delete(st);
- /* Ditch anything pending on ISAKMP SA being established.
- * Note: this must be done before the unhash_state to prevent
- * flush_pending_by_state inadvertently and prematurely
- * deleting our connection.
- */
- flush_pending_by_state(st);
+ delete_event(st); /* delete any pending timer event */
- /* effectively, this deletes any ISAKMP SA that this state represents */
- unhash_state(st);
+ /* Ditch anything pending on ISAKMP SA being established.
+ * Note: this must be done before the unhash_state to prevent
+ * flush_pending_by_state inadvertently and prematurely
+ * deleting our connection.
+ */
+ flush_pending_by_state(st);
- /* tell kernel to delete any IPSEC SA
- * ??? we ought to tell peer to delete IPSEC SAs
- */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- delete_ipsec_sa(st, FALSE);
- else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
- delete_ipsec_sa(st, TRUE);
+ /* effectively, this deletes any ISAKMP SA that this state represents */
+ unhash_state(st);
- if (c->newest_ipsec_sa == st->st_serialno)
- c->newest_ipsec_sa = SOS_NOBODY;
+ /* tell kernel to delete any IPSEC SA
+ * ??? we ought to tell peer to delete IPSEC SAs
+ */
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
+ delete_ipsec_sa(st, FALSE);
+ else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state))
+ delete_ipsec_sa(st, TRUE);
- if (c->newest_isakmp_sa == st->st_serialno)
- c->newest_isakmp_sa = SOS_NOBODY;
+ if (c->newest_ipsec_sa == st->st_serialno)
+ c->newest_ipsec_sa = SOS_NOBODY;
- st->st_connection = NULL; /* we might be about to free it */
- cur_state = old_cur_state; /* without st_connection, st isn't complete */
- connection_discard(c);
+ if (c->newest_isakmp_sa == st->st_serialno)
+ c->newest_isakmp_sa = SOS_NOBODY;
- release_whack(st);
+ st->st_connection = NULL; /* we might be about to free it */
+ cur_state = old_cur_state; /* without st_connection, st isn't complete */
+ connection_discard(c);
- /* from here on we are just freeing RAM */
+ release_whack(st);
- {
- struct msgid_list *p = st->st_used_msgids;
+ /* from here on we are just freeing RAM */
- while (p != NULL)
{
- struct msgid_list *q = p;
- p = p->next;
- pfree(q);
+ struct msgid_list *p = st->st_used_msgids;
+
+ while (p != NULL)
+ {
+ struct msgid_list *q = p;
+ p = p->next;
+ free(q);
+ }
}
- }
-
- unreference_key(&st->st_peer_pubkey);
-
- if (st->st_sec_in_use)
- mpz_clear(&(st->st_sec));
-
- pfreeany(st->st_tpacket.ptr);
- pfreeany(st->st_rpacket.ptr);
- pfreeany(st->st_p1isa.ptr);
- pfreeany(st->st_gi.ptr);
- pfreeany(st->st_gr.ptr);
- pfreeany(st->st_shared.ptr);
- pfreeany(st->st_ni.ptr);
- pfreeany(st->st_nr.ptr);
- pfreeany(st->st_skeyid.ptr);
- pfreeany(st->st_skeyid_d.ptr);
- pfreeany(st->st_skeyid_a.ptr);
- pfreeany(st->st_skeyid_e.ptr);
- pfreeany(st->st_enc_key.ptr);
- pfreeany(st->st_ah.our_keymat);
- pfreeany(st->st_ah.peer_keymat);
- pfreeany(st->st_esp.our_keymat);
- pfreeany(st->st_esp.peer_keymat);
-
- pfree(st);
+
+ unreference_key(&st->st_peer_pubkey);
+
+ DESTROY_IF(st->st_dh);
+
+ free(st->st_tpacket.ptr);
+ free(st->st_rpacket.ptr);
+ free(st->st_p1isa.ptr);
+ free(st->st_gi.ptr);
+ free(st->st_gr.ptr);
+ free(st->st_shared.ptr);
+ free(st->st_ni.ptr);
+ free(st->st_nr.ptr);
+ free(st->st_skeyid.ptr);
+ free(st->st_skeyid_d.ptr);
+ free(st->st_skeyid_a.ptr);
+ free(st->st_skeyid_e.ptr);
+ free(st->st_enc_key.ptr);
+ free(st->st_ah.our_keymat);
+ free(st->st_ah.peer_keymat);
+ free(st->st_esp.our_keymat);
+ free(st->st_esp.peer_keymat);
+
+ free(st);
}
-/*
+/**
* Is a connection in use by some state?
*/
-bool
-states_use_connection(struct connection *c)
+bool states_use_connection(struct connection *c)
{
- /* are there any states still using it? */
- struct state *st = NULL;
- int i;
+ /* are there any states still using it? */
+ struct state *st = NULL;
+ int i;
- for (i = 0; st == NULL && i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (st->st_connection == c)
- return TRUE;
+ for (i = 0; st == NULL && i < STATE_TABLE_SIZE; i++)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ if (st->st_connection == c)
+ return TRUE;
- return FALSE;
+ return FALSE;
}
-/*
- * delete all states that were created for a given connection.
+/**
+ * Delete all states that were created for a given connection.
* if relations == TRUE, then also delete states that share
* the same phase 1 SA.
*/
-void
-delete_states_by_connection(struct connection *c, bool relations)
+void delete_states_by_connection(struct connection *c, bool relations)
{
- int pass;
- /* this kludge avoids an n^2 algorithm */
- enum connection_kind ck = c->kind;
- struct spd_route *sr;
-
- /* save this connection's isakmp SA, since it will get set to later SOS_NOBODY */
- so_serial_t parent_sa = c->newest_isakmp_sa;
-
- if (ck == CK_INSTANCE)
- c->kind = CK_GOING_AWAY;
-
- /* We take two passes so that we delete any ISAKMP SAs last.
- * This allows Delete Notifications to be sent.
- * ?? We could probably double the performance by caching any
- * ISAKMP SA states found in the first pass, avoiding a second.
- */
- for (pass = 0; pass != 2; pass++)
- {
- int i;
-
- /* For each hash chain... */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
+ int pass;
+ /* this kludge avoids an n^2 algorithm */
+ enum connection_kind ck = c->kind;
+ struct spd_route *sr;
+
+ /* save this connection's isakmp SA, since it will get set to later SOS_NOBODY */
+ so_serial_t parent_sa = c->newest_isakmp_sa;
+
+ if (ck == CK_INSTANCE)
+ c->kind = CK_GOING_AWAY;
+
+ /* We take two passes so that we delete any ISAKMP SAs last.
+ * This allows Delete Notifications to be sent.
+ * ?? We could probably double the performance by caching any
+ * ISAKMP SA states found in the first pass, avoiding a second.
+ */
+ for (pass = 0; pass != 2; pass++)
{
- struct state *st;
+ int i;
- /* For each state in the hash chain... */
- for (st = statetable[i]; st != NULL; )
- {
- struct state *this = st;
+ /* For each hash chain... */
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
+ {
+ struct state *st;
+
+ /* For each state in the hash chain... */
+ for (st = statetable[i]; st != NULL; )
+ {
+ struct state *this = st;
- st = st->st_hashchain_next; /* before this is deleted */
+ st = st->st_hashchain_next; /* before this is deleted */
- if ((this->st_connection == c
- || (relations && parent_sa != SOS_NOBODY
- && this->st_clonedfrom == parent_sa))
- && (pass == 1 || !IS_ISAKMP_SA_ESTABLISHED(this->st_state)))
- {
- struct state *old_cur_state
- = cur_state == this? NULL : cur_state;
+ if ((this->st_connection == c
+ || (relations && parent_sa != SOS_NOBODY
+ && this->st_clonedfrom == parent_sa))
+ && (pass == 1 || !IS_ISAKMP_SA_ESTABLISHED(this->st_state)))
+ {
+ struct state *old_cur_state
+ = cur_state == this? NULL : cur_state;
#ifdef DEBUG
- lset_t old_cur_debugging = cur_debugging;
+ lset_t old_cur_debugging = cur_debugging;
#endif
- set_cur_state(this);
- plog("deleting state (%s)"
- , enum_show(&state_names, this->st_state));
- delete_state(this);
- cur_state = old_cur_state;
+ set_cur_state(this);
+ plog("deleting state (%s)"
+ , enum_show(&state_names, this->st_state));
+ delete_state(this);
+ cur_state = old_cur_state;
#ifdef DEBUG
- cur_debugging = old_cur_debugging;
+ cur_debugging = old_cur_debugging;
#endif
+ }
+ }
}
- }
}
- }
-
- sr = &c->spd;
- while (sr != NULL)
- {
- passert(sr->eroute_owner == SOS_NOBODY);
- passert(sr->routing != RT_ROUTED_TUNNEL);
- sr = sr->next;
- }
- c->kind = ck;
+
+ sr = &c->spd;
+ while (sr != NULL)
+ {
+ passert(sr->eroute_owner == SOS_NOBODY);
+ passert(sr->routing != RT_ROUTED_TUNNEL);
+ sr = sr->next;
+ }
+ c->kind = ck;
}
-/* Walk through the state table, and delete each state whose phase 1 (IKE)
+/**
+ * Walk through the state table, and delete each state whose phase 1 (IKE)
* peer is among those given.
*/
-void
-delete_states_by_peer(ip_address *peer)
+void delete_states_by_peer(ip_address *peer)
{
- char peerstr[ADDRTOT_BUF];
- int i;
-
- addrtot(peer, 0, peerstr, sizeof(peerstr));
+ char peerstr[ADDRTOT_BUF];
+ int i;
- /* For each hash chain... */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
+ addrtot(peer, 0, peerstr, sizeof(peerstr));
- /* For each state in the hash chain... */
- for (st = statetable[i]; st != NULL; )
+ /* For each hash chain... */
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- struct state *this = st;
- struct spd_route *sr;
- struct connection *c = this->st_connection;
-
- st = st->st_hashchain_next; /* before this is deleted */
+ struct state *st;
- /* ??? Is it not the case that the peer is the same for all spds? */
- for (sr = &c->spd; sr != NULL; sr = sr->next)
- {
- if (sameaddr(&sr->that.host_addr, peer))
+ /* For each state in the hash chain... */
+ for (st = statetable[i]; st != NULL; )
{
- plog("peer %s for connection %s deleting - claimed to have crashed"
- , peerstr
- , c->name);
- delete_states_by_connection(c, TRUE);
- if (c->kind == CK_INSTANCE)
- delete_connection(c, TRUE);
- break; /* can only delete it once */
+ struct state *this = st;
+ struct spd_route *sr;
+ struct connection *c = this->st_connection;
+
+ st = st->st_hashchain_next; /* before this is deleted */
+
+ /* ??? Is it not the case that the peer is the same for all spds? */
+ for (sr = &c->spd; sr != NULL; sr = sr->next)
+ {
+ if (sameaddr(&sr->that.host_addr, peer))
+ {
+ plog("peer %s for connection %s deleting - claimed to have crashed"
+ , peerstr
+ , c->name);
+ delete_states_by_connection(c, TRUE);
+ if (c->kind == CK_INSTANCE)
+ delete_connection(c, TRUE);
+ break; /* can only delete it once */
+ }
+ }
}
- }
}
- }
}
/* Duplicate a Phase 1 state object, to create a Phase 2 object.
* Caller must schedule an event for this object so that it doesn't leak.
* Caller must insert_state().
*/
-struct state *
-duplicate_state(struct state *st)
+struct state *duplicate_state(struct state *st)
{
- struct state *nst;
-
- DBG(DBG_CONTROL, DBG_log("duplicating state object #%lu",
- st->st_serialno));
-
- /* record use of the Phase 1 state */
- st->st_outbound_count++;
- st->st_outbound_time = now();
-
- nst = new_state();
-
- memcpy(nst->st_icookie, st->st_icookie, COOKIE_SIZE);
- memcpy(nst->st_rcookie, st->st_rcookie, COOKIE_SIZE);
-
- nst->st_connection = st->st_connection;
- nst->st_doi = st->st_doi;
- nst->st_situation = st->st_situation;
- nst->st_clonedfrom = st->st_serialno;
- nst->st_oakley = st->st_oakley;
- nst->st_modecfg = st->st_modecfg;
-
-# define clone_chunk(ch, name) \
- clonetochunk(nst->ch, st->ch.ptr, st->ch.len, name)
-
- clone_chunk(st_skeyid_d, "st_skeyid_d in duplicate_state");
- clone_chunk(st_skeyid_a, "st_skeyid_a in duplicate_state");
- clone_chunk(st_skeyid_e, "st_skeyid_e in duplicate_state");
- clone_chunk(st_enc_key, "st_enc_key in duplicate_state");
-
-# undef clone_chunk
-
- return nst;
+ struct state *nst;
+
+ DBG(DBG_CONTROL, DBG_log("duplicating state object #%lu",
+ st->st_serialno));
+
+ /* record use of the Phase 1 state */
+ st->st_outbound_count++;
+ st->st_outbound_time = now();
+
+ nst = new_state();
+
+ memcpy(nst->st_icookie, st->st_icookie, COOKIE_SIZE);
+ memcpy(nst->st_rcookie, st->st_rcookie, COOKIE_SIZE);
+
+ nst->st_connection = st->st_connection;
+ nst->st_doi = st->st_doi;
+ nst->st_situation = st->st_situation;
+ nst->st_clonedfrom = st->st_serialno;
+ nst->st_oakley = st->st_oakley;
+ nst->st_modecfg = st->st_modecfg;
+ nst->st_skeyid_d = chunk_clone(st->st_skeyid_d);
+ nst->st_skeyid_a = chunk_clone(st->st_skeyid_a);
+ nst->st_skeyid_e = chunk_clone(st->st_skeyid_e);
+ nst->st_enc_key = chunk_clone(st->st_enc_key);
+
+ return nst;
}
#if 1
void for_each_state(void *(f)(struct state *, void *data), void *data)
{
- struct state *st, *ocs = cur_state;
- int i;
- for (i=0; i<STATE_TABLE_SIZE; i++) {
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next) {
- set_cur_state(st);
- f(st, data);
+ struct state *st, *ocs = cur_state;
+ int i;
+ for (i=0; i<STATE_TABLE_SIZE; i++) {
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next) {
+ set_cur_state(st);
+ f(st, data);
+ }
}
- }
- cur_state = ocs;
+ cur_state = ocs;
}
#endif
-/*
+/**
* Find a state object.
*/
-struct state *
-find_state(const u_char *icookie
-, const u_char *rcookie
-, const ip_address *peer
-, msgid_t /*network order*/ msgid)
+struct state *find_state(const u_char *icookie, const u_char *rcookie,
+ const ip_address *peer, msgid_t msgid)
{
- struct state *st = *state_hash(icookie, rcookie, peer);
-
- while (st != (struct state *) NULL)
- if (sameaddr(peer, &st->st_connection->spd.that.host_addr)
- && memcmp(icookie, st->st_icookie, COOKIE_SIZE) == 0
- && memcmp(rcookie, st->st_rcookie, COOKIE_SIZE) == 0
- && msgid == st->st_msgid)
- break;
- else
- st = st->st_hashchain_next;
-
- DBG(DBG_CONTROL,
- if (st == NULL)
- DBG_log("state object not found");
- else
- DBG_log("state object #%lu found, in %s"
- , st->st_serialno
- , enum_show(&state_names, st->st_state)));
+ struct state *st = *state_hash(icookie, rcookie, peer);
- return st;
+ while (st != (struct state *) NULL)
+ {
+ if (sameaddr(peer, &st->st_connection->spd.that.host_addr)
+ && memeq(icookie, st->st_icookie, COOKIE_SIZE)
+ && memeq(rcookie, st->st_rcookie, COOKIE_SIZE)
+ && msgid == st->st_msgid)
+ {
+ break;
+ }
+ else
+ {
+ st = st->st_hashchain_next;
+ }
+ }
+ DBG(DBG_CONTROL,
+ if (st == NULL)
+ DBG_log("state object not found");
+ else
+ DBG_log("state object #%lu found, in %s"
+ , st->st_serialno
+ , enum_show(&state_names, st->st_state)));
+
+ return st;
}
-/* Find the state that sent a packet
+/**
+ * Find the state that sent a packet
* ??? this could be expensive -- it should be rate-limited to avoid DoS
*/
-struct state *
-find_sender(size_t packet_len, u_char *packet)
+struct state *find_sender(size_t packet_len, u_char *packet)
{
- int i;
- struct state *st;
-
- if (packet_len >= sizeof(struct isakmp_hdr))
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (st->st_tpacket.ptr != NULL
- && st->st_tpacket.len == packet_len
- && memcmp(st->st_tpacket.ptr, packet, packet_len) == 0)
- return st;
+ int i;
+ struct state *st;
- return NULL;
+ if (packet_len >= sizeof(struct isakmp_hdr))
+ {
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
+ {
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ {
+ if (st->st_tpacket.ptr != NULL
+ && st->st_tpacket.len == packet_len
+ && memeq(st->st_tpacket.ptr, packet, packet_len))
+ {
+ return st;
+ }
+ }
+ }
+ }
+ return NULL;
}
-struct state *
-find_phase2_state_to_delete(const struct state *p1st
-, u_int8_t protoid
-, ipsec_spi_t spi
-, bool *bogus)
+struct state *find_phase2_state_to_delete(const struct state *p1st,
+ u_int8_t protoid, ipsec_spi_t spi,
+ bool *bogus)
{
- struct state *st;
- int i;
+ struct state *st;
+ int i;
- *bogus = FALSE;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ *bogus = FALSE;
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- && p1st->st_connection->host_pair == st->st_connection->host_pair
- && same_peer_ids(p1st->st_connection, st->st_connection, NULL))
- {
- struct ipsec_proto_info *pr = protoid == PROTO_IPSEC_AH
- ? &st->st_ah : &st->st_esp;
-
- if (pr->present)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
{
- if (pr->attrs.spi == spi)
- return st;
- if (pr->our_spi == spi)
- *bogus = TRUE;
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
+ && p1st->st_connection->host_pair == st->st_connection->host_pair
+ && same_peer_ids(p1st->st_connection, st->st_connection, NULL))
+ {
+ struct ipsec_proto_info *pr = protoid == PROTO_IPSEC_AH
+ ? &st->st_ah : &st->st_esp;
+
+ if (pr->present)
+ {
+ if (pr->attrs.spi == spi)
+ return st;
+ if (pr->our_spi == spi)
+ *bogus = TRUE;
+ }
+ }
}
- }
}
- }
- return NULL;
+ return NULL;
}
-/* Find newest Phase 1 negotiation state object for suitable for connection c
+/**
+ * Find newest Phase 1 negotiation state object for suitable for connection c
*/
-struct state *
-find_phase1_state(const struct connection *c, lset_t ok_states)
+struct state *find_phase1_state(const struct connection *c, lset_t ok_states)
{
- struct state
- *st,
- *best = NULL;
- int i;
-
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
- if (LHAS(ok_states, st->st_state)
- && c->host_pair == st->st_connection->host_pair
- && same_peer_ids(c, st->st_connection, NULL)
- && (best == NULL || best->st_serialno < st->st_serialno))
- best = st;
-
- return best;
+ struct state
+ *st,
+ *best = NULL;
+ int i;
+
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ if (LHAS(ok_states, st->st_state)
+ && c->host_pair == st->st_connection->host_pair
+ && same_peer_ids(c, st->st_connection, NULL)
+ && (best == NULL || best->st_serialno < st->st_serialno))
+ best = st;
+
+ return best;
}
-void
-state_eroute_usage(ip_subnet *ours, ip_subnet *his
-, unsigned long count, time_t nw)
+void state_eroute_usage(ip_subnet *ours, ip_subnet *his, unsigned long count,
+ time_t nw)
{
- struct state *st;
- int i;
+ struct state *st;
+ int i;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- struct connection *c = st->st_connection;
-
- /* XXX spd-enum */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
- && c->spd.eroute_owner == st->st_serialno
- && c->spd.routing == RT_ROUTED_TUNNEL
- && samesubnet(&c->spd.this.client, ours)
- && samesubnet(&c->spd.that.client, his))
- {
- if (st->st_outbound_count != count)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
{
- st->st_outbound_count = count;
- st->st_outbound_time = nw;
+ struct connection *c = st->st_connection;
+
+ /* XXX spd-enum */
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state)
+ && c->spd.eroute_owner == st->st_serialno
+ && c->spd.routing == RT_ROUTED_TUNNEL
+ && samesubnet(&c->spd.this.client, ours)
+ && samesubnet(&c->spd.that.client, his))
+ {
+ if (st->st_outbound_count != count)
+ {
+ st->st_outbound_count = count;
+ st->st_outbound_time = nw;
+ }
+ return;
+ }
}
- return;
- }
}
- }
- DBG(DBG_CONTROL,
- {
- char ourst[SUBNETTOT_BUF];
- char hist[SUBNETTOT_BUF];
-
- subnettot(ours, 0, ourst, sizeof(ourst));
- subnettot(his, 0, hist, sizeof(hist));
- DBG_log("unknown tunnel eroute %s -> %s found in scan"
- , ourst, hist);
- });
+ DBG(DBG_CONTROL,
+ {
+ char ourst[SUBNETTOT_BUF];
+ char hist[SUBNETTOT_BUF];
+
+ subnettot(ours, 0, ourst, sizeof(ourst));
+ subnettot(his, 0, hist, sizeof(hist));
+ DBG_log("unknown tunnel eroute %s -> %s found in scan"
+ , ourst, hist);
+ });
}
-void fmt_state(bool all, struct state *st, time_t n
-, char *state_buf, size_t state_buf_len
-, char *state_buf2, size_t state_buf2_len)
+void fmt_state(bool all, struct state *st, time_t n, char *state_buf,
+ size_t state_buf_len, char *state_buf2, size_t state_buf2_len)
{
- /* what the heck is interesting about a state? */
- const struct connection *c = st->st_connection;
-
- long delta = st->st_event->ev_time >= n
- ? (long)(st->st_event->ev_time - n)
- : -(long)(n - st->st_event->ev_time);
-
- char inst[CONN_INST_BUF];
- const char *np1 = c->newest_isakmp_sa == st->st_serialno
- ? "; newest ISAKMP" : "";
- const char *np2 = c->newest_ipsec_sa == st->st_serialno
- ? "; newest IPSEC" : "";
- /* XXX spd-enum */
- const char *eo = c->spd.eroute_owner == st->st_serialno
- ? "; eroute owner" : "";
- const char *dpd = (all && st->st_dpd && c->dpd_action != DPD_ACTION_NONE)
- ? "; DPD active" : "";
-
- passert(st->st_event != 0);
-
- fmt_conn_instance(c, inst);
-
- snprintf(state_buf, state_buf_len
- , "#%lu: \"%s\"%s %s (%s); %s in %lds%s%s%s%s"
- , st->st_serialno
- , c->name, inst
- , enum_name(&state_names, st->st_state)
- , state_story[st->st_state - STATE_MAIN_R0]
- , enum_name(&timer_event_names, st->st_event->ev_type)
- , delta
- , np1, np2, eo, dpd);
-
- /* print out SPIs if SAs are established */
- if (state_buf2_len != 0)
- state_buf2[0] = '\0'; /* default to empty */
- if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
- {
-
- bool tunnel;
- char buf[SATOT_BUF*6 + 2*20 + 1];
- const char *p_end = buf + sizeof(buf);
- char *p = buf;
-
-# define add_said(adst, aspi, aproto) { \
- ip_said s; \
- \
- initsaid(adst, aspi, aproto, &s); \
- if (p < p_end - 1) \
- { \
- *p++ = ' '; \
- p += satot(&s, 0, p, p_end - p) - 1; \
- } \
- }
+ /* what the heck is interesting about a state? */
+ const struct connection *c = st->st_connection;
+
+ long delta = st->st_event->ev_time >= n
+ ? (long)(st->st_event->ev_time - n)
+ : -(long)(n - st->st_event->ev_time);
+
+ char inst[CONN_INST_BUF];
+ const char *np1 = c->newest_isakmp_sa == st->st_serialno
+ ? "; newest ISAKMP" : "";
+ const char *np2 = c->newest_ipsec_sa == st->st_serialno
+ ? "; newest IPSEC" : "";
+ /* XXX spd-enum */
+ const char *eo = c->spd.eroute_owner == st->st_serialno
+ ? "; eroute owner" : "";
+ const char *dpd = (all && st->st_dpd && c->dpd_action != DPD_ACTION_NONE)
+ ? "; DPD active" : "";
+
+ passert(st->st_event != 0);
+
+ fmt_conn_instance(c, inst);
+
+ snprintf(state_buf, state_buf_len
+ , "#%lu: \"%s\"%s %s (%s); %N in %lds%s%s%s%s"
+ , st->st_serialno
+ , c->name, inst
+ , enum_name(&state_names, st->st_state)
+ , state_story[st->st_state - STATE_MAIN_R0]
+ , timer_event_names, st->st_event->ev_type
+ , delta
+ , np1, np2, eo, dpd);
+
+ /* print out SPIs if SAs are established */
+ if (state_buf2_len != 0)
+ state_buf2[0] = '\0'; /* default to empty */
+ if (IS_IPSEC_SA_ESTABLISHED(st->st_state))
+ {
-# define add_sa_info(st, inbound) { \
- u_int bytes; \
- time_t use_time; \
- \
- if (get_sa_info(st, inbound, &bytes, &use_time)) \
- { \
- p += snprintf(p, p_end - p, " (%'u bytes", bytes); \
- if (bytes > 0 && use_time != UNDEFINED_TIME) \
- p += snprintf(p, p_end - p, ", %ds ago", (int)(now - use_time)); \
- p += snprintf(p, p_end - p, ")"); \
- } \
- }
+ bool tunnel;
+ char buf[SATOT_BUF*6 + 2*20 + 1];
+ const char *p_end = buf + sizeof(buf);
+ char *p = buf;
+
+# define add_said(adst, aspi, aproto) { \
+ ip_said s; \
+ \
+ initsaid(adst, aspi, aproto, &s); \
+ if (p < p_end - 1) \
+ { \
+ *p++ = ' '; \
+ p += satot(&s, 0, p, p_end - p) - 1; \
+ } \
+ }
- *p = '\0';
- if (st->st_ah.present)
- {
- add_said(&c->spd.that.host_addr, st->st_ah.attrs.spi, SA_AH);
- add_said(&c->spd.this.host_addr, st->st_ah.our_spi, SA_AH);
- }
- if (st->st_esp.present)
- {
- time_t now = time(NULL);
+# define add_sa_info(st, inbound) { \
+ u_int bytes; \
+ time_t use_time; \
+ \
+ if (get_sa_info(st, inbound, &bytes, &use_time)) \
+ { \
+ p += snprintf(p, p_end - p, " (%'u bytes", bytes); \
+ if (bytes > 0 && use_time != UNDEFINED_TIME) \
+ p += snprintf(p, p_end - p, ", %ds ago", (int)(now - use_time)); \
+ p += snprintf(p, p_end - p, ")"); \
+ } \
+ }
- add_said(&c->spd.that.host_addr, st->st_esp.attrs.spi, SA_ESP);
- add_sa_info(st, FALSE);
- add_said(&c->spd.this.host_addr, st->st_esp.our_spi, SA_ESP);
- add_sa_info(st, TRUE);
- }
- if (st->st_ipcomp.present)
- {
- add_said(&c->spd.that.host_addr, st->st_ipcomp.attrs.spi, SA_COMP);
- add_said(&c->spd.this.host_addr, st->st_ipcomp.our_spi, SA_COMP);
- }
+ *p = '\0';
+ if (st->st_ah.present)
+ {
+ add_said(&c->spd.that.host_addr, st->st_ah.attrs.spi, SA_AH);
+ add_said(&c->spd.this.host_addr, st->st_ah.our_spi, SA_AH);
+ }
+ if (st->st_esp.present)
+ {
+ time_t now = time(NULL);
+
+ add_said(&c->spd.that.host_addr, st->st_esp.attrs.spi, SA_ESP);
+ add_sa_info(st, FALSE);
+ add_said(&c->spd.this.host_addr, st->st_esp.our_spi, SA_ESP);
+ add_sa_info(st, TRUE);
+ }
+ if (st->st_ipcomp.present)
+ {
+ add_said(&c->spd.that.host_addr, st->st_ipcomp.attrs.spi, SA_COMP);
+ add_said(&c->spd.this.host_addr, st->st_ipcomp.our_spi, SA_COMP);
+ }
#ifdef KLIPS
- tunnel = st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
- || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL;
- p += snprintf(p, p_end - p, "; %s", tunnel? "tunnel":"transport");
+ tunnel = st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
+ || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL
+ || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL;
+ p += snprintf(p, p_end - p, "; %s", tunnel? "tunnel":"transport");
#endif
- snprintf(state_buf2, state_buf2_len
- , "#%lu: \"%s\"%s%s"
- , st->st_serialno
- , c->name, inst
- , buf);
+ snprintf(state_buf2, state_buf2_len
+ , "#%lu: \"%s\"%s%s"
+ , st->st_serialno
+ , c->name, inst
+ , buf);
-# undef add_said
-# undef add_sa_info
- }
+# undef add_said
+# undef add_sa_info
+ }
}
/*
@@ -831,82 +820,80 @@ void fmt_state(bool all, struct state *st, time_t n
* isakmp_sa (XXX probably wrong)
*
*/
-static int
-state_compare(const void *a, const void *b)
+static int state_compare(const void *a, const void *b)
{
- const struct state *sap = *(const struct state *const *)a;
- struct connection *ca = sap->st_connection;
- const struct state *sbp = *(const struct state *const *)b;
- struct connection *cb = sbp->st_connection;
+ const struct state *sap = *(const struct state *const *)a;
+ struct connection *ca = sap->st_connection;
+ const struct state *sbp = *(const struct state *const *)b;
+ struct connection *cb = sbp->st_connection;
- /* DBG_log("comparing %s to %s", ca->name, cb->name); */
+ /* DBG_log("comparing %s to %s", ca->name, cb->name); */
- return connection_compare(ca, cb);
+ return connection_compare(ca, cb);
}
-void
-show_states_status(bool all, const char *name)
+void show_states_status(bool all, const char *name)
{
- time_t n = now();
- int i;
- char state_buf[LOG_WIDTH];
- char state_buf2[LOG_WIDTH];
- int count;
- struct state **array;
-
- /* make count of states */
- count = 0;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
+ time_t n = now();
+ int i;
+ char state_buf[LOG_WIDTH];
+ char state_buf2[LOG_WIDTH];
+ int count;
+ struct state **array;
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ /* make count of states */
+ count = 0;
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- if (name == NULL || streq(name, st->st_connection->name))
- count++;
- }
- }
+ struct state *st;
- /* build the array */
- array = alloc_bytes(sizeof(struct state *)*count, "state array");
- count = 0;
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ {
+ if (name == NULL || streq(name, st->st_connection->name))
+ count++;
+ }
+ }
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ /* build the array */
+ array = malloc(sizeof(struct state *)*count);
+ count = 0;
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- if (name == NULL || streq(name, st->st_connection->name))
- array[count++]=st;
+ struct state *st;
+
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ {
+ if (name == NULL || streq(name, st->st_connection->name))
+ array[count++]=st;
+ }
}
- }
- /* sort it! */
- qsort(array, count, sizeof(struct state *), state_compare);
+ /* sort it! */
+ qsort(array, count, sizeof(struct state *), state_compare);
- /* now print sorted results */
- for (i = 0; i < count; i++)
- {
- struct state *st;
+ /* now print sorted results */
+ for (i = 0; i < count; i++)
+ {
+ struct state *st;
- st = array[i];
+ st = array[i];
- fmt_state(all, st, n
- , state_buf, sizeof(state_buf)
- , state_buf2, sizeof(state_buf2));
- whack_log(RC_COMMENT, state_buf);
- if (state_buf2[0] != '\0')
- whack_log(RC_COMMENT, state_buf2);
+ fmt_state(all, st, n
+ , state_buf, sizeof(state_buf)
+ , state_buf2, sizeof(state_buf2));
+ whack_log(RC_COMMENT, state_buf);
+ if (state_buf2[0] != '\0')
+ whack_log(RC_COMMENT, state_buf2);
- /* show any associated pending Phase 2s */
- if (IS_PHASE1(st->st_state))
- show_pending_phase2(st->st_connection->host_pair, st);
- }
- if (count > 0)
- whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
+ /* show any associated pending Phase 2s */
+ if (IS_PHASE1(st->st_state))
+ show_pending_phase2(st->st_connection->host_pair, st);
+ }
+ if (count > 0)
+ whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
- /* free the array */
- pfree(array);
+ /* free the array */
+ free(array);
}
/* Given that we've used up a range of unused CPI's,
@@ -915,49 +902,48 @@ show_states_status(bool all, const char *name)
* If we can't find one easily, choose 0 (a bad SPI,
* no matter what order) indicating failure.
*/
-void
-find_my_cpi_gap(cpi_t *latest_cpi, cpi_t *first_busy_cpi)
+void find_my_cpi_gap(cpi_t *latest_cpi, cpi_t *first_busy_cpi)
{
- int tries = 0;
- cpi_t base = *latest_cpi;
- cpi_t closest;
- int i;
+ int tries = 0;
+ cpi_t base = *latest_cpi;
+ cpi_t closest;
+ int i;
startover:
- closest = ~0; /* not close at all */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *st;
-
- for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
+ closest = ~0; /* not close at all */
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- if (st->st_ipcomp.present)
- {
- cpi_t c = ntohl(st->st_ipcomp.our_spi) - base;
+ struct state *st;
- if (c < closest)
+ for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)
{
- if (c == 0)
- {
- /* oops: next spot is occupied; start over */
- if (++tries == 20)
+ if (st->st_ipcomp.present)
{
- /* FAILURE */
- *latest_cpi = *first_busy_cpi = 0;
- return;
+ cpi_t c = ntohl(st->st_ipcomp.our_spi) - base;
+
+ if (c < closest)
+ {
+ if (c == 0)
+ {
+ /* oops: next spot is occupied; start over */
+ if (++tries == 20)
+ {
+ /* FAILURE */
+ *latest_cpi = *first_busy_cpi = 0;
+ return;
+ }
+ base++;
+ if (base > IPCOMP_LAST_NEGOTIATED)
+ base = IPCOMP_FIRST_NEGOTIATED;
+ goto startover; /* really a tail call */
+ }
+ closest = c;
+ }
}
- base++;
- if (base > IPCOMP_LAST_NEGOTIATED)
- base = IPCOMP_FIRST_NEGOTIATED;
- goto startover; /* really a tail call */
- }
- closest = c;
}
- }
}
- }
- *latest_cpi = base; /* base is first in next free range */
- *first_busy_cpi = closest + base; /* and this is the roof */
+ *latest_cpi = base; /* base is first in next free range */
+ *first_busy_cpi = closest + base; /* and this is the roof */
}
/* Muck with high-order 16 bits of this SPI in order to make
@@ -968,38 +954,42 @@ startover:
* If we can't find one easily, return 0 (a bad SPI,
* no matter what order) indicating failure.
*/
-ipsec_spi_t
-uniquify_his_cpi(ipsec_spi_t cpi, struct state *st)
+ipsec_spi_t uniquify_his_cpi(ipsec_spi_t cpi, struct state *st)
{
- int tries = 0;
- int i;
+ int tries = 0;
+ int i;
+ rng_t *rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
startover:
- /* network order makes first two bytes our target */
- get_rnd_bytes((u_char *)&cpi, 2);
-
- /* Make sure that the result is unique.
- * Hard work. If there is no unique value, we'll loop forever!
- */
- for (i = 0; i < STATE_TABLE_SIZE; i++)
- {
- struct state *s;
+ /* network order makes first two bytes our target */
+ rng->get_bytes(rng, 2, (u_char *)&cpi);
- for (s = statetable[i]; s != NULL; s = s->st_hashchain_next)
+ /* Make sure that the result is unique.
+ * Hard work. If there is no unique value, we'll loop forever!
+ */
+ for (i = 0; i < STATE_TABLE_SIZE; i++)
{
- if (s->st_ipcomp.present
- && sameaddr(&s->st_connection->spd.that.host_addr
- , &st->st_connection->spd.that.host_addr)
- && cpi == s->st_ipcomp.attrs.spi)
- {
- if (++tries == 20)
- return 0; /* FAILURE */
- goto startover;
- }
+ struct state *s;
+
+ for (s = statetable[i]; s != NULL; s = s->st_hashchain_next)
+ {
+ if (s->st_ipcomp.present
+ && sameaddr(&s->st_connection->spd.that.host_addr
+ , &st->st_connection->spd.that.host_addr)
+ && cpi == s->st_ipcomp.attrs.spi)
+ {
+ if (++tries == 20)
+ {
+ rng->destroy(rng);
+ return 0; /* FAILURE */
+ }
+ goto startover;
+ }
+ }
}
- }
- return cpi;
+ rng->destroy(rng);
+ return cpi;
}
/*