pluto: Removed KLIPS specific bare shunt scanning.
This commit is contained in:
parent
749d3cccaf
commit
54f42e350e
|
@ -77,7 +77,6 @@ ENUM(dpd_action_names, DPD_ACTION_NONE, DPD_ACTION_RESTART,
|
|||
ENUM(timer_event_names, EVENT_NULL, EVENT_LOG_DAILY,
|
||||
"EVENT_NULL",
|
||||
"EVENT_REINIT_SECRET",
|
||||
"EVENT_SHUNT_SCAN",
|
||||
"EVENT_SO_DISCARD",
|
||||
"EVENT_RETRANSMIT",
|
||||
"EVENT_SA_REPLACE",
|
||||
|
|
|
@ -246,9 +246,6 @@ extern enum_name_t *timer_event_names;
|
|||
enum event_type {
|
||||
EVENT_NULL, /* non-event */
|
||||
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_RETRANSMIT, /* Retransmit packet */
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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 => tun0x1002@10.19.75.145
|
||||
* 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,
|
||||
const ip_address *src, const ip_address *dest)
|
||||
{
|
||||
|
@ -2371,11 +2049,6 @@ void init_kernel(void)
|
|||
/* register SA types that we can negotiate */
|
||||
can_do_IPcomp = FALSE; /* until we get a response from KLIPS */
|
||||
kernel_ops->pfkey_register();
|
||||
|
||||
if (!kernel_ops->policy_lifetime)
|
||||
{
|
||||
event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -152,8 +152,6 @@ extern void record_and_initiate_opportunistic(const ip_subnet *
|
|||
|
||||
extern void init_kernel(void);
|
||||
|
||||
extern void scan_proc_shunts(void);
|
||||
|
||||
extern bool trap_connection(struct connection *c);
|
||||
extern void unroute_connection(struct connection *c);
|
||||
|
||||
|
|
|
@ -233,13 +233,6 @@ void handle_timer_event(void)
|
|||
init_secret();
|
||||
break;
|
||||
|
||||
#ifdef KLIPS
|
||||
case EVENT_SHUNT_SCAN:
|
||||
passert(st == NULL);
|
||||
scan_proc_shunts();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EVENT_LOG_DAILY:
|
||||
daily_log_event();
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue