pluto: Removed KLIPS specific bare shunt scanning.
This commit is contained in:
@@ -77,7 +77,6 @@ ENUM(dpd_action_names, DPD_ACTION_NONE, DPD_ACTION_RESTART,
|
|||||||
ENUM(timer_event_names, EVENT_NULL, EVENT_LOG_DAILY,
|
ENUM(timer_event_names, EVENT_NULL, EVENT_LOG_DAILY,
|
||||||
"EVENT_NULL",
|
"EVENT_NULL",
|
||||||
"EVENT_REINIT_SECRET",
|
"EVENT_REINIT_SECRET",
|
||||||
"EVENT_SHUNT_SCAN",
|
|
||||||
"EVENT_SO_DISCARD",
|
"EVENT_SO_DISCARD",
|
||||||
"EVENT_RETRANSMIT",
|
"EVENT_RETRANSMIT",
|
||||||
"EVENT_SA_REPLACE",
|
"EVENT_SA_REPLACE",
|
||||||
|
|||||||
@@ -246,9 +246,6 @@ extern enum_name_t *timer_event_names;
|
|||||||
enum event_type {
|
enum event_type {
|
||||||
EVENT_NULL, /* non-event */
|
EVENT_NULL, /* non-event */
|
||||||
EVENT_REINIT_SECRET, /* Refresh cookie secret */
|
EVENT_REINIT_SECRET, /* Refresh cookie secret */
|
||||||
#ifdef KLIPS
|
|
||||||
EVENT_SHUNT_SCAN, /* scan shunt eroutes known to kernel */
|
|
||||||
#endif
|
|
||||||
EVENT_SO_DISCARD, /* discard unfinished state object */
|
EVENT_SO_DISCARD, /* discard unfinished state object */
|
||||||
EVENT_RETRANSMIT, /* Retransmit packet */
|
EVENT_RETRANSMIT, /* Retransmit packet */
|
||||||
EVENT_SA_REPLACE, /* SA replacement event */
|
EVENT_SA_REPLACE, /* SA replacement event */
|
||||||
|
|||||||
@@ -1343,328 +1343,6 @@ static bool shunt_eroute(connection_t *c, struct spd_route *sr,
|
|||||||
, null_proto_info, op, opname) && ok;
|
, null_proto_info, op, opname) && ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is only called when s is a likely SAID with trailing protocol i.e.
|
|
||||||
* it has the form :-
|
|
||||||
*
|
|
||||||
* %<keyword>:p
|
|
||||||
* <ip-proto><spi>@a.b.c.d:p
|
|
||||||
*
|
|
||||||
* The task here is to remove the ":p" part so that the rest can be read
|
|
||||||
* by another routine.
|
|
||||||
*/
|
|
||||||
static const char *read_proto(const char * s, size_t * len, int * transport_proto)
|
|
||||||
{
|
|
||||||
const char * p;
|
|
||||||
const char * ugh;
|
|
||||||
unsigned long proto;
|
|
||||||
size_t l;
|
|
||||||
|
|
||||||
l = *len;
|
|
||||||
p = memchr(s, ':', l);
|
|
||||||
if (p == 0)
|
|
||||||
{
|
|
||||||
*transport_proto = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ugh = ttoul(p+1, l-((p-s)+1), 10, &proto);
|
|
||||||
if (ugh != 0)
|
|
||||||
{
|
|
||||||
return ugh;
|
|
||||||
}
|
|
||||||
if (proto > 65535)
|
|
||||||
{
|
|
||||||
return "protocol number is too large, legal range is 0-65535";
|
|
||||||
}
|
|
||||||
*len = p-s;
|
|
||||||
*transport_proto = proto;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* scan /proc/net/ipsec_eroute every once in a while, looking for:
|
|
||||||
*
|
|
||||||
* - %hold shunts of which Pluto isn't aware. This situation could
|
|
||||||
* be caused by lost ACQUIRE messages. When found, they will
|
|
||||||
* added to orphan_holds. This in turn will lead to Opportunistic
|
|
||||||
* initiation.
|
|
||||||
*
|
|
||||||
* - other kinds of shunts that haven't been used recently. These will be
|
|
||||||
* deleted. They represent OE failures.
|
|
||||||
*
|
|
||||||
* - recording recent uses of tunnel eroutes so that rekeying decisions
|
|
||||||
* can be made for OE connections.
|
|
||||||
*
|
|
||||||
* Here are some sample lines:
|
|
||||||
* 10 10.3.2.1.0/24 -> 0.0.0.0/0 => %trap
|
|
||||||
* 259 10.3.2.1.115/32 -> 10.19.75.161/32 => [email protected]
|
|
||||||
* 71 10.44.73.97/32 -> 0.0.0.0/0 => %trap
|
|
||||||
* 4119 10.44.73.97/32 -> 10.114.121.41/32 => %pass
|
|
||||||
* Newer versions of KLIPS start each line with a 32-bit packet count.
|
|
||||||
* If available, the count is used to detect whether a %pass shunt is in use.
|
|
||||||
*
|
|
||||||
* NOTE: execution time is quadratic in the number of eroutes since the
|
|
||||||
* searching for each is sequential. If this becomes a problem, faster
|
|
||||||
* searches could be implemented (hash or radix tree, for example).
|
|
||||||
*/
|
|
||||||
void scan_proc_shunts(void)
|
|
||||||
{
|
|
||||||
static const char procname[] = "/proc/net/ipsec_eroute";
|
|
||||||
FILE *f;
|
|
||||||
time_t nw = now();
|
|
||||||
int lino;
|
|
||||||
struct eroute_info *expired = NULL;
|
|
||||||
|
|
||||||
event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL);
|
|
||||||
|
|
||||||
DBG(DBG_CONTROL,
|
|
||||||
DBG_log("scanning for shunt eroutes")
|
|
||||||
)
|
|
||||||
|
|
||||||
/* free any leftover entries: they will be refreshed if still current */
|
|
||||||
while (orphaned_holds != NULL)
|
|
||||||
{
|
|
||||||
struct eroute_info *p = orphaned_holds;
|
|
||||||
|
|
||||||
orphaned_holds = p->next;
|
|
||||||
free(orphaned_holds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* decode the /proc file. Don't do anything strenuous to it
|
|
||||||
* (certainly no PF_KEY stuff) to minimize the chance that it
|
|
||||||
* might change underfoot.
|
|
||||||
*/
|
|
||||||
|
|
||||||
f = fopen(procname, "r");
|
|
||||||
if (f == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for each line... */
|
|
||||||
for (lino = 1; ; lino++)
|
|
||||||
{
|
|
||||||
unsigned char buf[1024]; /* should be big enough */
|
|
||||||
chunk_t field[10]; /* 10 is loose upper bound */
|
|
||||||
chunk_t *ff = NULL; /* fixed fields (excluding optional count) */
|
|
||||||
int fi;
|
|
||||||
struct eroute_info eri;
|
|
||||||
char *cp;
|
|
||||||
err_t context = ""
|
|
||||||
, ugh = NULL;
|
|
||||||
|
|
||||||
cp = fgets(buf, sizeof(buf), f);
|
|
||||||
if (cp == NULL)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* break out each field
|
|
||||||
* Note: if there are too many fields, just stop;
|
|
||||||
* it will be diagnosed a little later.
|
|
||||||
*/
|
|
||||||
for (fi = 0; fi < (int)countof(field); fi++)
|
|
||||||
{
|
|
||||||
static const char sep[] = " \t\n"; /* field-separating whitespace */
|
|
||||||
size_t w;
|
|
||||||
|
|
||||||
cp += strspn(cp, sep); /* find start of field */
|
|
||||||
w = strcspn(cp, sep); /* find width of field */
|
|
||||||
field[fi] = chunk_create(cp, w);
|
|
||||||
cp += w;
|
|
||||||
if (w == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This odd do-hickey is to share error reporting code.
|
|
||||||
* A break will get to that common code. The setting
|
|
||||||
* of "ugh" and "context" parameterize it.
|
|
||||||
*/
|
|
||||||
do {
|
|
||||||
/* Old entries have no packet count; new ones do.
|
|
||||||
* check if things are as they should be.
|
|
||||||
*/
|
|
||||||
if (fi == 5)
|
|
||||||
{
|
|
||||||
ff = &field[0]; /* old form, with no count */
|
|
||||||
}
|
|
||||||
else if (fi == 6)
|
|
||||||
{
|
|
||||||
ff = &field[1]; /* new form, with count */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ugh = "has wrong number of fields";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ff[1].len != 2
|
|
||||||
|| strncmp(ff[1].ptr, "->", 2) != 0
|
|
||||||
|| ff[3].len != 2
|
|
||||||
|| strncmp(ff[3].ptr, "=>", 2) != 0)
|
|
||||||
{
|
|
||||||
ugh = "is missing -> or =>";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* actually digest fields of interest */
|
|
||||||
|
|
||||||
/* packet count */
|
|
||||||
|
|
||||||
eri.count = 0;
|
|
||||||
if (ff != field)
|
|
||||||
{
|
|
||||||
context = "count field is malformed: ";
|
|
||||||
ugh = ttoul(field[0].ptr, field[0].len, 10, &eri.count);
|
|
||||||
if (ugh != NULL)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* our client */
|
|
||||||
|
|
||||||
context = "source subnet field malformed: ";
|
|
||||||
ugh = ttosubnet(ff[0].ptr, ff[0].len, AF_INET, &eri.ours);
|
|
||||||
if (ugh != NULL)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* his client */
|
|
||||||
|
|
||||||
context = "destination subnet field malformed: ";
|
|
||||||
ugh = ttosubnet(ff[2].ptr, ff[2].len, AF_INET, &eri.his);
|
|
||||||
if (ugh != NULL)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SAID */
|
|
||||||
|
|
||||||
context = "SA ID field malformed: ";
|
|
||||||
ugh = read_proto(ff[4].ptr, &ff[4].len, &eri.transport_proto);
|
|
||||||
if (ugh != NULL)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ugh = ttosa(ff[4].ptr, ff[4].len, &eri.said);
|
|
||||||
} while (FALSE);
|
|
||||||
|
|
||||||
if (ugh != NULL)
|
|
||||||
{
|
|
||||||
plog("INTERNAL ERROR: %s line %d %s%s"
|
|
||||||
, procname, lino, context, ugh);
|
|
||||||
continue; /* ignore rest of line */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now we have decoded eroute, let's consider it.
|
|
||||||
* For shunt eroutes:
|
|
||||||
*
|
|
||||||
* %hold: if not known, add to orphaned_holds list for initiation
|
|
||||||
* because ACQUIRE might have been lost.
|
|
||||||
*
|
|
||||||
* %pass, %drop, %reject: determine if idle; if so, blast it away.
|
|
||||||
* Can occur bare (if DNS provided insufficient information)
|
|
||||||
* or with a connection (failure context).
|
|
||||||
* Could even be installed by ipsec manual.
|
|
||||||
*
|
|
||||||
* %trap: always welcome.
|
|
||||||
*
|
|
||||||
* For other eroutes: find state and record count change
|
|
||||||
*/
|
|
||||||
if (eri.said.proto == SA_INT)
|
|
||||||
{
|
|
||||||
/* shunt eroute */
|
|
||||||
switch (ntohl(eri.said.spi))
|
|
||||||
{
|
|
||||||
case SPI_HOLD:
|
|
||||||
if (bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto) == NULL
|
|
||||||
&& shunt_owner(&eri.ours, &eri.his) == NULL)
|
|
||||||
{
|
|
||||||
int ourport = ntohs(portof(&eri.ours.addr));
|
|
||||||
int hisport = ntohs(portof(&eri.his.addr));
|
|
||||||
char ourst[SUBNETTOT_BUF];
|
|
||||||
char hist[SUBNETTOT_BUF];
|
|
||||||
char sat[SATOT_BUF];
|
|
||||||
|
|
||||||
subnettot(&eri.ours, 0, ourst, sizeof(ourst));
|
|
||||||
subnettot(&eri.his, 0, hist, sizeof(hist));
|
|
||||||
satot(&eri.said, 0, sat, sizeof(sat));
|
|
||||||
|
|
||||||
DBG(DBG_CONTROL,
|
|
||||||
DBG_log("add orphaned shunt %s:%d -> %s:%d => %s:%d"
|
|
||||||
, ourst, ourport, hist, hisport, sat, eri.transport_proto)
|
|
||||||
)
|
|
||||||
eri.next = orphaned_holds;
|
|
||||||
orphaned_holds = clone_thing(eri);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SPI_PASS:
|
|
||||||
case SPI_DROP:
|
|
||||||
case SPI_REJECT:
|
|
||||||
/* nothing sensible to do if we don't have counts */
|
|
||||||
if (ff != field)
|
|
||||||
{
|
|
||||||
struct bare_shunt **bs_pp
|
|
||||||
= bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto);
|
|
||||||
|
|
||||||
if (bs_pp != NULL)
|
|
||||||
{
|
|
||||||
struct bare_shunt *bs = *bs_pp;
|
|
||||||
|
|
||||||
if (eri.count != bs->count)
|
|
||||||
{
|
|
||||||
bs->count = eri.count;
|
|
||||||
bs->last_activity = nw;
|
|
||||||
}
|
|
||||||
else if (nw - bs->last_activity > SHUNT_PATIENCE)
|
|
||||||
{
|
|
||||||
eri.next = expired;
|
|
||||||
expired = clone_thing(eri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SPI_TRAP:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
bad_case(ntohl(eri.said.spi));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* regular (non-shunt) eroute */
|
|
||||||
state_eroute_usage(&eri.ours, &eri.his, eri.count, nw);
|
|
||||||
}
|
|
||||||
} /* for each line */
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
/* Now that we've finished processing the /proc file,
|
|
||||||
* it is safe to delete the expired %pass shunts.
|
|
||||||
*/
|
|
||||||
while (expired != NULL)
|
|
||||||
{
|
|
||||||
struct eroute_info *p = expired;
|
|
||||||
ip_address src, dst;
|
|
||||||
|
|
||||||
networkof(&p->ours, &src);
|
|
||||||
networkof(&p->his, &dst);
|
|
||||||
(void) replace_bare_shunt(&src, &dst
|
|
||||||
, BOTTOM_PRIO /* not used because we are deleting. This value is a filler */
|
|
||||||
, SPI_PASS /* not used because we are deleting. This value is a filler */
|
|
||||||
, FALSE, p->transport_proto, "delete expired bare shunts");
|
|
||||||
expired = p->next;
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool del_spi(ipsec_spi_t spi, int proto,
|
static bool del_spi(ipsec_spi_t spi, int proto,
|
||||||
const ip_address *src, const ip_address *dest)
|
const ip_address *src, const ip_address *dest)
|
||||||
{
|
{
|
||||||
@@ -2371,11 +2049,6 @@ void init_kernel(void)
|
|||||||
/* register SA types that we can negotiate */
|
/* register SA types that we can negotiate */
|
||||||
can_do_IPcomp = FALSE; /* until we get a response from KLIPS */
|
can_do_IPcomp = FALSE; /* until we get a response from KLIPS */
|
||||||
kernel_ops->pfkey_register();
|
kernel_ops->pfkey_register();
|
||||||
|
|
||||||
if (!kernel_ops->policy_lifetime)
|
|
||||||
{
|
|
||||||
event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -152,8 +152,6 @@ extern void record_and_initiate_opportunistic(const ip_subnet *
|
|||||||
|
|
||||||
extern void init_kernel(void);
|
extern void init_kernel(void);
|
||||||
|
|
||||||
extern void scan_proc_shunts(void);
|
|
||||||
|
|
||||||
extern bool trap_connection(struct connection *c);
|
extern bool trap_connection(struct connection *c);
|
||||||
extern void unroute_connection(struct connection *c);
|
extern void unroute_connection(struct connection *c);
|
||||||
|
|
||||||
|
|||||||
@@ -233,13 +233,6 @@ void handle_timer_event(void)
|
|||||||
init_secret();
|
init_secret();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef KLIPS
|
|
||||||
case EVENT_SHUNT_SCAN:
|
|
||||||
passert(st == NULL);
|
|
||||||
scan_proc_shunts();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case EVENT_LOG_DAILY:
|
case EVENT_LOG_DAILY:
|
||||||
daily_log_event();
|
daily_log_event();
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user