pluto: Store xfrm marks on connection and use them when installing SAs and policies.

This commit is contained in:
Tobias Brunner
2010-09-02 19:04:25 +02:00
parent a0d13f42e6
commit a280ba9525
3 changed files with 42 additions and 29 deletions
+5
View File
@@ -1193,6 +1193,11 @@ void add_connection(const whack_message_t *wm)
c->spd.next = NULL; c->spd.next = NULL;
c->spd.reqid = gen_reqid(); c->spd.reqid = gen_reqid();
c->spd.mark_in.value = wm->mark_in.value;
c->spd.mark_in.mask = wm->mark_in.mask;
c->spd.mark_out.value = wm->mark_out.value;
c->spd.mark_out.mask = wm->mark_out.mask;
/* set internal fields */ /* set internal fields */
c->instance_serial = 0; c->instance_serial = 0;
c->ac_next = connections; c->ac_next = connections;
+2
View File
@@ -168,6 +168,8 @@ struct spd_route {
so_serial_t eroute_owner; so_serial_t eroute_owner;
enum routing_t routing; /* level of routing in place */ enum routing_t routing; /* level of routing in place */
uint32_t reqid; uint32_t reqid;
mark_t mark_in;
mark_t mark_out;
}; };
typedef struct connection connection_t; typedef struct connection connection_t;
+34 -28
View File
@@ -749,6 +749,7 @@ static bool raw_eroute(const ip_address *this_host,
const ip_subnet *this_client, const ip_subnet *this_client,
const ip_address *that_host, const ip_address *that_host,
const ip_subnet *that_client, const ip_subnet *that_client,
mark_t mark,
ipsec_spi_t spi, ipsec_spi_t spi,
unsigned int proto, unsigned int proto,
unsigned int satype, unsigned int satype,
@@ -762,7 +763,6 @@ static bool raw_eroute(const ip_address *this_host,
host_t *host_src, *host_dst; host_t *host_src, *host_dst;
policy_type_t type = POLICY_IPSEC; policy_type_t type = POLICY_IPSEC;
policy_dir_t dir = POLICY_OUT; policy_dir_t dir = POLICY_OUT;
mark_t mark_none = { 0, 0 };
char text_said[SATOT_BUF]; char text_said[SATOT_BUF];
bool ok = TRUE, routed = FALSE, bool ok = TRUE, routed = FALSE,
deleting = (op & ERO_MASK) == ERO_DELETE, deleting = (op & ERO_MASK) == ERO_DELETE,
@@ -820,7 +820,7 @@ static bool raw_eroute(const ip_address *this_host,
if (deleting || replacing) if (deleting || replacing)
{ {
hydra->kernel_interface->del_policy(hydra->kernel_interface, hydra->kernel_interface->del_policy(hydra->kernel_interface,
ts_src, ts_dst, dir, mark_none, routed); ts_src, ts_dst, dir, mark, routed);
} }
if (!deleting) if (!deleting)
@@ -828,7 +828,7 @@ static bool raw_eroute(const ip_address *this_host,
/* FIXME: use_lifetime? */ /* FIXME: use_lifetime? */
ok = hydra->kernel_interface->add_policy(hydra->kernel_interface, ok = hydra->kernel_interface->add_policy(hydra->kernel_interface,
host_src, host_dst, ts_src, ts_dst, dir, type, sa, host_src, host_dst, ts_src, ts_dst, dir, type, sa,
mark_none, routed) == SUCCESS; mark, routed) == SUCCESS;
} }
if (dir == POLICY_IN) if (dir == POLICY_IN)
@@ -837,7 +837,7 @@ static bool raw_eroute(const ip_address *this_host,
if (deleting || replacing) if (deleting || replacing)
{ {
hydra->kernel_interface->del_policy(hydra->kernel_interface, hydra->kernel_interface->del_policy(hydra->kernel_interface,
ts_src, ts_dst, dir, mark_none, routed); ts_src, ts_dst, dir, mark, routed);
} }
if (!deleting && ok && if (!deleting && ok &&
@@ -846,7 +846,7 @@ static bool raw_eroute(const ip_address *this_host,
/* FIXME: use_lifetime? */ /* FIXME: use_lifetime? */
ok = hydra->kernel_interface->add_policy(hydra->kernel_interface, ok = hydra->kernel_interface->add_policy(hydra->kernel_interface,
host_src, host_dst, ts_src, ts_dst, dir, type, sa, host_src, host_dst, ts_src, ts_dst, dir, type, sa,
mark_none, routed) == SUCCESS; mark, routed) == SUCCESS;
} }
} }
@@ -874,8 +874,8 @@ static bool eroute_connection(struct spd_route *sr, ipsec_spi_t spi,
peer = aftoinfo(addrtypeof(peer))->any; peer = aftoinfo(addrtypeof(peer))->any;
} }
return raw_eroute(&sr->this.host_addr, &sr->this.client, peer, return raw_eroute(&sr->this.host_addr, &sr->this.client, peer,
&sr->that.client, spi, proto, satype, sr->this.protocol, &sr->that.client, sr->mark_out, spi, proto, satype,
sa, 0, op, buf2); sr->this.protocol, sa, 0, op, buf2);
} }
/* assign a bare hold to a connection */ /* assign a bare hold to a connection */
@@ -1093,9 +1093,9 @@ static bool shunt_eroute(connection_t *c, struct spd_route *sr,
} }
} }
ok = raw_eroute(&c->spd.that.host_addr, &c->spd.that.client, ok = raw_eroute(&sr->that.host_addr, &sr->that.client,
&c->spd.this.host_addr, &c->spd.this.client, htonl(spi), &sr->this.host_addr, &sr->this.client, sr->mark_in,
SA_INT, SADB_X_SATYPE_INT, sr->this.protocol, htonl(spi), SA_INT, SADB_X_SATYPE_INT, sr->this.protocol,
&null_ipsec_sa, 0, &null_ipsec_sa, 0,
op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), opname); op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), opname);
@@ -1111,7 +1111,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
ipsec_mode_t mode = MODE_TRANSPORT; ipsec_mode_t mode = MODE_TRANSPORT;
ipsec_sa_cfg_t sa = { .mode = 0 }; ipsec_sa_cfg_t sa = { .mode = 0 };
lifetime_cfg_t lt_none = { .time = { .rekey = 0 } }; lifetime_cfg_t lt_none = { .time = { .rekey = 0 } };
mark_t mark_none = { 0, 0 }; mark_t mark;
bool ok = TRUE; bool ok = TRUE;
/* SPIs, saved for undoing, if necessary */ /* SPIs, saved for undoing, if necessary */
struct kernel_sa said[EM_MAXRELSPIS], *said_next = said; struct kernel_sa said[EM_MAXRELSPIS], *said_next = said;
@@ -1119,11 +1119,13 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
{ {
src = &c->spd.that; src = &c->spd.that;
dst = &c->spd.this; dst = &c->spd.this;
mark = c->spd.mark_in;
} }
else else
{ {
src = &c->spd.this; src = &c->spd.this;
dst = &c->spd.that; dst = &c->spd.that;
mark = c->spd.mark_out;
} }
host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr); host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr);
@@ -1168,7 +1170,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src, if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src,
host_dst, ipcomp_spi, said_next->proto, c->spd.reqid, host_dst, ipcomp_spi, said_next->proto, c->spd.reqid,
mark_none, &lt_none, ENCR_UNDEFINED, chunk_empty, mark, &lt_none, ENCR_UNDEFINED, chunk_empty,
AUTH_UNDEFINED, chunk_empty, mode, AUTH_UNDEFINED, chunk_empty, mode,
st->st_ipcomp.attrs.transid, 0 /* cpi */, FALSE, st->st_ipcomp.attrs.transid, 0 /* cpi */, FALSE,
inbound, NULL, NULL) != SUCCESS) inbound, NULL, NULL) != SUCCESS)
@@ -1277,7 +1279,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src, if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src,
host_dst, esp_spi, said_next->proto, c->spd.reqid, host_dst, esp_spi, said_next->proto, c->spd.reqid,
mark_none, &lt_none, enc_alg, enc_key, mark, &lt_none, enc_alg, enc_key,
auth_alg, auth_key, mode, IPCOMP_NONE, 0 /* cpi */, auth_alg, auth_key, mode, IPCOMP_NONE, 0 /* cpi */,
encap, inbound, NULL, NULL) != SUCCESS) encap, inbound, NULL, NULL) != SUCCESS)
{ {
@@ -1310,7 +1312,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src, if (hydra->kernel_interface->add_sa(hydra->kernel_interface, host_src,
host_dst, ah_spi, said_next->proto, c->spd.reqid, host_dst, ah_spi, said_next->proto, c->spd.reqid,
mark_none, &lt_none, ENCR_UNDEFINED, chunk_empty, mark, &lt_none, ENCR_UNDEFINED, chunk_empty,
auth_alg, auth_key, mode, IPCOMP_NONE, 0 /* cpi */, auth_alg, auth_key, mode, IPCOMP_NONE, 0 /* cpi */,
FALSE, inbound, NULL, NULL) != SUCCESS) FALSE, inbound, NULL, NULL) != SUCCESS)
{ {
@@ -1323,7 +1325,7 @@ static bool setup_half_ipsec_sa(struct state *st, bool inbound)
if (inbound && c->spd.eroute_owner == SOS_NOBODY) if (inbound && c->spd.eroute_owner == SOS_NOBODY)
{ {
(void) raw_eroute(&src->host_addr, &src->client, &dst->host_addr, (void) raw_eroute(&src->host_addr, &src->client, &dst->host_addr,
&dst->client, 256, SA_IPIP, SADB_SATYPE_UNSPEC, &dst->client, mark, 256, SA_IPIP, SADB_SATYPE_UNSPEC,
c->spd.this.protocol, &sa, 0, ERO_ADD_INBOUND, c->spd.this.protocol, &sa, 0, ERO_ADD_INBOUND,
"add inbound"); "add inbound");
} }
@@ -1337,7 +1339,7 @@ fail:
hydra->kernel_interface->del_sa(hydra->kernel_interface, host_src, hydra->kernel_interface->del_sa(hydra->kernel_interface, host_src,
host_dst, said_next->spi, host_dst, said_next->spi,
said_next->proto, 0 /* cpi */, said_next->proto, 0 /* cpi */,
mark_none); mark);
} }
ok = FALSE; ok = FALSE;
@@ -1353,18 +1355,19 @@ static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
const struct end *src, *dst; const struct end *src, *dst;
host_t *host_src, *host_dst; host_t *host_src, *host_dst;
ipsec_spi_t spi; ipsec_spi_t spi;
mark_t mark_none = { 0, 0 }; mark_t mark;
bool result = TRUE; bool result = TRUE;
if (inbound) if (inbound)
{ {
src = &c->spd.that; src = &c->spd.that;
dst = &c->spd.this; dst = &c->spd.this;
mark = c->spd.mark_in;
if (c->spd.eroute_owner == SOS_NOBODY) if (c->spd.eroute_owner == SOS_NOBODY)
{ {
(void) raw_eroute(&src->host_addr, &src->client, &dst->host_addr, (void) raw_eroute(&src->host_addr, &src->client, &dst->host_addr,
&dst->client, 256, IPSEC_PROTO_ANY, &dst->client, mark, 256, IPSEC_PROTO_ANY,
SADB_SATYPE_UNSPEC, c->spd.this.protocol, SADB_SATYPE_UNSPEC, c->spd.this.protocol,
&null_ipsec_sa, 0, ERO_DEL_INBOUND, &null_ipsec_sa, 0, ERO_DEL_INBOUND,
"delete inbound"); "delete inbound");
@@ -1374,6 +1377,7 @@ static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
{ {
src = &c->spd.this; src = &c->spd.this;
dst = &c->spd.that; dst = &c->spd.that;
mark = c->spd.mark_out;
} }
host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr); host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr);
@@ -1384,7 +1388,7 @@ static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
spi = inbound ? st->st_ah.our_spi : st->st_ah.attrs.spi; spi = inbound ? st->st_ah.our_spi : st->st_ah.attrs.spi;
result &= hydra->kernel_interface->del_sa(hydra->kernel_interface, result &= hydra->kernel_interface->del_sa(hydra->kernel_interface,
host_src, host_dst, spi, IPPROTO_AH, host_src, host_dst, spi, IPPROTO_AH,
0 /* cpi */, mark_none) == SUCCESS; 0 /* cpi */, mark) == SUCCESS;
} }
if (st->st_esp.present) if (st->st_esp.present)
@@ -1392,7 +1396,7 @@ static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
spi = inbound ? st->st_esp.our_spi : st->st_esp.attrs.spi; spi = inbound ? st->st_esp.our_spi : st->st_esp.attrs.spi;
result &= hydra->kernel_interface->del_sa(hydra->kernel_interface, result &= hydra->kernel_interface->del_sa(hydra->kernel_interface,
host_src, host_dst, spi, IPPROTO_ESP, host_src, host_dst, spi, IPPROTO_ESP,
0 /* cpi */, mark_none) == SUCCESS; 0 /* cpi */, mark) == SUCCESS;
} }
if (st->st_ipcomp.present) if (st->st_ipcomp.present)
@@ -1400,7 +1404,7 @@ static bool teardown_half_ipsec_sa(struct state *st, bool inbound)
spi = inbound ? st->st_ipcomp.our_spi : st->st_ipcomp.attrs.spi; spi = inbound ? st->st_ipcomp.our_spi : st->st_ipcomp.attrs.spi;
result &= hydra->kernel_interface->del_sa(hydra->kernel_interface, result &= hydra->kernel_interface->del_sa(hydra->kernel_interface,
host_src, host_dst, spi, IPPROTO_COMP, host_src, host_dst, spi, IPPROTO_COMP,
0 /* cpi */, mark_none) == SUCCESS; 0 /* cpi */, mark) == SUCCESS;
} }
host_src->destroy(host_src); host_src->destroy(host_src);
@@ -1419,7 +1423,7 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
host_t *host_src = NULL, *host_dst = NULL; host_t *host_src = NULL, *host_dst = NULL;
const struct end *src, *dst; const struct end *src, *dst;
ipsec_spi_t spi; ipsec_spi_t spi;
mark_t mark_none = { 0, 0 }; mark_t mark;
u_int64_t bytes_kernel = 0; u_int64_t bytes_kernel = 0;
bool result = FALSE; bool result = FALSE;
@@ -1434,12 +1438,14 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
{ {
src = &c->spd.that; src = &c->spd.that;
dst = &c->spd.this; dst = &c->spd.this;
mark = c->spd.mark_in;
spi = st->st_esp.our_spi; spi = st->st_esp.our_spi;
} }
else else
{ {
src = &c->spd.this; src = &c->spd.this;
dst = &c->spd.that; dst = &c->spd.that;
mark = c->spd.mark_out;
spi = st->st_esp.attrs.spi; spi = st->st_esp.attrs.spi;
} }
@@ -1448,7 +1454,7 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
switch(hydra->kernel_interface->query_sa(hydra->kernel_interface, host_src, switch(hydra->kernel_interface->query_sa(hydra->kernel_interface, host_src,
host_dst, spi, IPPROTO_ESP, host_dst, spi, IPPROTO_ESP,
mark_none, &bytes_kernel)) mark, &bytes_kernel))
{ {
case FAILED: case FAILED:
goto failed; goto failed;
@@ -1469,7 +1475,7 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
if (hydra->kernel_interface->query_policy(hydra->kernel_interface, if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
ts_src, ts_dst, inbound ? POLICY_IN : POLICY_OUT, ts_src, ts_dst, inbound ? POLICY_IN : POLICY_OUT,
mark_none, &time_kernel) != SUCCESS) mark, &time_kernel) != SUCCESS)
{ {
goto failed; goto failed;
} }
@@ -1479,7 +1485,7 @@ bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time)
st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)
{ {
if (hydra->kernel_interface->query_policy(hydra->kernel_interface, if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
ts_src, ts_dst, POLICY_FWD, mark_none, ts_src, ts_dst, POLICY_FWD, mark,
&time_kernel) != SUCCESS) &time_kernel) != SUCCESS)
{ {
goto failed; goto failed;
@@ -2034,11 +2040,11 @@ static bool update_nat_t_ipsec_esp_sa (struct state *st, bool inbound)
{ {
connection_t *c = st->st_connection; connection_t *c = st->st_connection;
host_t *host_src, *host_dst, *new_src, *new_dst; host_t *host_src, *host_dst, *new_src, *new_dst;
mark_t mark_none = { 0, 0 };
bool result;
ipsec_spi_t spi = inbound ? st->st_esp.our_spi : st->st_esp.attrs.spi; ipsec_spi_t spi = inbound ? st->st_esp.our_spi : st->st_esp.attrs.spi;
struct end *src = inbound ? &c->spd.that : &c->spd.this, struct end *src = inbound ? &c->spd.that : &c->spd.this,
*dst = inbound ? &c->spd.this : &c->spd.that; *dst = inbound ? &c->spd.this : &c->spd.that;
mark_t mark = inbound ? c->spd.mark_in : c->spd.mark_out;
bool result;
host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr); host_src = host_create_from_sockaddr((sockaddr_t*)&src->host_addr);
host_dst = host_create_from_sockaddr((sockaddr_t*)&dst->host_addr); host_dst = host_create_from_sockaddr((sockaddr_t*)&dst->host_addr);
@@ -2051,7 +2057,7 @@ static bool update_nat_t_ipsec_esp_sa (struct state *st, bool inbound)
result = hydra->kernel_interface->update_sa(hydra->kernel_interface, result = hydra->kernel_interface->update_sa(hydra->kernel_interface,
spi, IPPROTO_ESP, 0 /* cpi */, host_src, host_dst, spi, IPPROTO_ESP, 0 /* cpi */, host_src, host_dst,
new_src, new_dst, TRUE /* encap */, TRUE /* new_encap */, new_src, new_dst, TRUE /* encap */, TRUE /* new_encap */,
mark_none) == SUCCESS; mark) == SUCCESS;
host_src->destroy(host_src); host_src->destroy(host_src);
host_dst->destroy(host_dst); host_dst->destroy(host_dst);