aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2010-07-29 10:41:36 +0200
committerTobias Brunner <tobias@strongswan.org>2010-09-02 19:04:20 +0200
commit952487d6890031224195ca0ba8df0e7f2b072261 (patch)
tree1b9999f287b336911e7c9303a6761b4f4279d7eb
parentdeea15f04e5bed6bfb4525e6bc286ccaaf2ae1c6 (diff)
downloadstrongswan-952487d6890031224195ca0ba8df0e7f2b072261.tar.bz2
strongswan-952487d6890031224195ca0ba8df0e7f2b072261.tar.xz
pluto: Migrated raw_eroute to libhydra's kernel interface.
This introduces a new struct to pass the protocol information like spis. Also adapted eroute_connection and the simple calls of raw_eroute to the new signature.
-rw-r--r--src/pluto/kernel.c193
1 files changed, 132 insertions, 61 deletions
diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c
index cd6b399fb..0ed8e7702 100644
--- a/src/pluto/kernel.c
+++ b/src/pluto/kernel.c
@@ -164,17 +164,20 @@ static void set_text_said(char *text_said, const ip_address *dst,
bool no_klips = FALSE; /* don't actually use KLIPS */
-static const struct pfkey_proto_info null_proto_info[2] = {
- {
- proto: IPPROTO_ESP,
- encapsulation: ENCAPSULATION_MODE_TRANSPORT,
- reqid: 0
- },
- {
- proto: 0,
- encapsulation: 0,
- reqid: 0
- }
+/**
+ * Struct to store information about the SAs to install in the kernel
+ */
+struct kernel_proto_info {
+ ipsec_mode_t mode;
+ u_int32_t esp_spi;
+ u_int32_t ah_spi;
+ u_int32_t reqid;
+ u_int16_t ipcomp;
+ u_int16_t cpi;
+};
+
+static const struct kernel_proto_info null_proto_info = {
+ .mode = MODE_TRANSPORT,
};
/**
@@ -951,10 +954,10 @@ show_shunt_status(void)
whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
}
-/* Setup an IPsec route entry.
+/**
+ * Setup an IPsec route entry.
* op is one of the ERO_* operators.
*/
-
static bool raw_eroute(const ip_address *this_host,
const ip_subnet *this_client,
const ip_address *that_host,
@@ -963,12 +966,20 @@ static bool raw_eroute(const ip_address *this_host,
unsigned int proto,
unsigned int satype,
unsigned int transport_proto,
- const struct pfkey_proto_info *proto_info,
+ const struct kernel_proto_info *pi,
time_t use_lifetime,
unsigned int op,
const char *opname USED_BY_DEBUG)
{
+ traffic_selector_t *ts_src, *ts_dst;
+ host_t *host_src, *host_dst;
+ policy_type_t type = POLICY_IPSEC;
+ policy_dir_t dir = POLICY_OUT;
+ mark_t mark_none = { 0, 0 };
char text_said[SATOT_BUF];
+ bool ok = TRUE, routed = FALSE,
+ deleting = (op & ERO_MASK) == ERO_DELETE,
+ replacing = op & (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT);
set_text_said(text_said, that_host, spi, proto);
@@ -986,9 +997,80 @@ static bool raw_eroute(const ip_address *this_host,
, text_said, transport_proto);
});
- return kernel_ops->raw_eroute(this_host, this_client
- , that_host, that_client, spi, satype, transport_proto, proto_info
- , use_lifetime, op, text_said);
+ if (satype == SADB_X_SATYPE_INT)
+ {
+ switch (ntohl(spi))
+ {
+ case SPI_PASS:
+ type = POLICY_PASS;
+ break;
+ case SPI_DROP:
+ case SPI_REJECT:
+ type = POLICY_DROP;
+ break;
+ case SPI_TRAP:
+ case SPI_TRAPSUBNET:
+ case SPI_HOLD:
+ if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
+ {
+ return TRUE;
+ }
+ routed = TRUE;
+ break;
+ }
+ }
+
+ if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
+ {
+ dir = POLICY_IN;
+ }
+
+ host_src = host_create_from_sockaddr((sockaddr_t*)this_host);
+ host_dst = host_create_from_sockaddr((sockaddr_t*)that_host);
+ ts_src = traffic_selector_from_subnet(this_client, transport_proto);
+ ts_dst = traffic_selector_from_subnet(that_client, transport_proto);
+
+ if (deleting || replacing)
+ {
+ hydra->kernel_interface->del_policy(hydra->kernel_interface,
+ ts_src, ts_dst, dir, mark_none, routed);
+ }
+
+ if (!deleting)
+ {
+ /* FIXME: use_lifetime? */
+ ok = hydra->kernel_interface->add_policy(hydra->kernel_interface,
+ host_src, host_dst, ts_src, ts_dst, dir, type,
+ pi->esp_spi, pi->ah_spi, pi->reqid, mark_none, pi->mode,
+ pi->ipcomp, pi->cpi, routed) == SUCCESS;
+ }
+
+ if (dir == POLICY_IN)
+ { /* handle forward policy */
+ dir = POLICY_FWD;
+ if (deleting || replacing)
+ {
+ hydra->kernel_interface->del_policy(hydra->kernel_interface,
+ ts_src, ts_dst, dir, mark_none, routed);
+ }
+
+ if (!deleting && ok &&
+ (pi->mode == MODE_TUNNEL || satype == SADB_X_SATYPE_INT))
+ {
+ /* FIXME: use_lifetime? */
+ ok = hydra->kernel_interface->add_policy(hydra->kernel_interface,
+ host_src, host_dst, ts_src, ts_dst, dir, type,
+ pi->esp_spi, pi->ah_spi, pi->reqid, mark_none, pi->mode,
+ pi->ipcomp, pi->cpi, routed) == SUCCESS;
+ }
+ }
+
+ host_src->destroy(host_src);
+ host_dst->destroy(host_dst);
+ ts_src->destroy(ts_src);
+ ts_dst->destroy(ts_dst);
+
+ return ok;
}
/* test to see if %hold remains */
@@ -1034,10 +1116,10 @@ bool replace_bare_shunt(const ip_address *src, const ip_address *dst,
/* is there already a broad host-to-host bare shunt? */
if (bs_pp == NULL)
{
- if (raw_eroute(null_host, &this_broad_client, null_host, &that_broad_client
- , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT
- , 0, null_proto_info
- , SHUNT_PATIENCE, ERO_ADD, why))
+ if (raw_eroute(null_host, &this_broad_client, null_host,
+ &that_broad_client, htonl(shunt_spi), SA_INT,
+ SADB_X_SATYPE_INT, 0, &null_proto_info,
+ SHUNT_PATIENCE, ERO_ADD, why))
{
struct bare_shunt *bs = malloc_thing(struct bare_shunt);
@@ -1059,10 +1141,9 @@ bool replace_bare_shunt(const ip_address *src, const ip_address *dst,
shunt_spi = SPI_HOLD;
}
- if (raw_eroute(null_host, &this_client, null_host, &that_client
- , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT
- , transport_proto, null_proto_info
- , SHUNT_PATIENCE, ERO_DELETE, why))
+ if (raw_eroute(null_host, &this_client, null_host, &that_client,
+ htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT, transport_proto,
+ &null_proto_info, SHUNT_PATIENCE, ERO_DELETE, why))
{
struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client, &that_client
, transport_proto);
@@ -1079,7 +1160,7 @@ bool replace_bare_shunt(const ip_address *src, const ip_address *dst,
static bool eroute_connection(struct spd_route *sr, ipsec_spi_t spi,
unsigned int proto, unsigned int satype,
- const struct pfkey_proto_info *proto_info,
+ const struct kernel_proto_info *proto_info,
unsigned int op, const char *opname)
{
const ip_address *peer = &sr->that.host_addr;
@@ -1092,11 +1173,9 @@ static bool eroute_connection(struct spd_route *sr, ipsec_spi_t spi,
{
peer = aftoinfo(addrtypeof(peer))->any;
}
- return raw_eroute(&sr->this.host_addr, &sr->this.client
- , peer
- , &sr->that.client
- , spi, proto, satype
- , sr->this.protocol, proto_info, 0, op, buf2);
+ return raw_eroute(&sr->this.host_addr, &sr->this.client, peer,
+ &sr->that.client, spi, proto, satype, sr->this.protocol,
+ proto_info, 0, op, buf2);
}
/* assign a bare hold to a connection */
@@ -1139,18 +1218,17 @@ bool assign_hold(connection_t *c USED_BY_DEBUG, struct spd_route *sr,
if (rn != ro)
{
if (erouted(ro)
- ? !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT
- , null_proto_info
- , ERO_REPLACE, "replace %trap with broad %hold")
- : !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT
- , null_proto_info
- , ERO_ADD, "add broad %hold"))
+ ? !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT,
+ &null_proto_info, ERO_REPLACE,
+ "replace %trap with broad %hold")
+ : !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT,
+ &null_proto_info, ERO_ADD, "add broad %hold"))
{
return FALSE;
}
}
- if (!replace_bare_shunt(src, dst, BOTTOM_PRIO, SPI_HOLD, FALSE
- , transport_proto, "delete narrow %hold"))
+ if (!replace_bare_shunt(src, dst, BOTTOM_PRIO, SPI_HOLD, FALSE,
+ transport_proto, "delete narrow %hold"))
{
return FALSE;
}
@@ -1344,17 +1422,13 @@ static bool shunt_eroute(connection_t *c, struct spd_route *sr,
}
}
- ok = TRUE;
- if (kernel_ops->inbound_eroute)
- {
- ok = raw_eroute(&c->spd.that.host_addr, &c->spd.that.client
- , &c->spd.this.host_addr, &c->spd.this.client
- , htonl(spi), SA_INT, SADB_X_SATYPE_INT
- , 0, null_proto_info, 0
- , op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), opname);
- }
- return eroute_connection(sr, htonl(spi), SA_INT, SADB_X_SATYPE_INT
- , null_proto_info, op, opname) && ok;
+ ok = raw_eroute(&c->spd.that.host_addr, &c->spd.that.client,
+ &c->spd.this.host_addr, &c->spd.this.client, htonl(spi),
+ SA_INT, SADB_X_SATYPE_INT, 0, &null_proto_info, 0,
+ op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), opname);
+
+ return eroute_connection(sr, htonl(spi), SA_INT, SADB_X_SATYPE_INT,
+ &null_proto_info, op, opname) && ok;
}
static bool del_spi(ipsec_spi_t spi, int proto,
@@ -2370,17 +2444,14 @@ bool route_and_eroute(connection_t *c USED_BY_KLIPS,
*/
struct bare_shunt *bs = *bspp;
- (void) raw_eroute(&bs->said.dst /* should be useless */
- , &bs->ours
- , &bs->said.dst /* should be useless */
- , &bs->his
- , bs->said.spi /* network order */
- , SA_INT
- , SADB_X_SATYPE_INT
- , 0
- , null_proto_info
- , SHUNT_PATIENCE
- , ERO_REPLACE, "restore");
+ (void) raw_eroute(&bs->said.dst, /* should be useless */
+ &bs->ours,
+ &bs->said.dst, /* should be useless */
+ &bs->his,
+ bs->said.spi, /* network order */
+ SA_INT, SADB_X_SATYPE_INT, 0,
+ &null_proto_info, SHUNT_PATIENCE,
+ ERO_REPLACE, "restore");
}
else if (ero != NULL)
{