Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions sbin/iked/iked.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ struct iked_flow {
struct iked_addr flow_src;
struct iked_addr flow_dst;
unsigned int flow_dir; /* in/out */
int flow_rdomain;
struct iked_addr flow_prenat;

unsigned int flow_loaded; /* pfkey done */
Expand Down Expand Up @@ -261,6 +262,7 @@ struct iked_policy {
uint8_t pol_certreqtype;

int pol_af;
int pol_rdomain;
uint8_t pol_saproto;
unsigned int pol_ipproto;

Expand Down
4 changes: 3 additions & 1 deletion sbin/iked/ikev2.c
Original file line number Diff line number Diff line change
Expand Up @@ -5371,6 +5371,7 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa,
flowa->flow_dir = IPSP_DIRECTION_OUT;
flowa->flow_saproto = ic ? IKEV2_SAPROTO_IPCOMP :
prop->prop_protoid;
flowa->flow_rdomain = sa->sa_policy->pol_rdomain;
flowa->flow_local = &sa->sa_local;
flowa->flow_peer = &sa->sa_peer;
flowa->flow_ikesa = sa;
Expand Down Expand Up @@ -6440,14 +6441,15 @@ ikev2_info_flow(struct iked *env, int dolog, const char *msg, struct iked_flow *
int buflen;

buflen = asprintf(&buf,
"%s: %p %s %s %s/%d -> %s/%d [%u] (%s) @%p\n", msg, flow,
"%s: %p %s %s %s/%d -> %s/%d [%u]@%d (%s) @%p\n", msg, flow,
print_map(flow->flow_saproto, ikev2_saproto_map),
flow->flow_dir == IPSP_DIRECTION_IN ? "in" : "out",
print_host((struct sockaddr *)&flow->flow_src.addr, NULL, 0),
flow->flow_src.addr_mask,
print_host((struct sockaddr *)&flow->flow_dst.addr, NULL, 0),
flow->flow_dst.addr_mask,
flow->flow_ipproto,
flow->flow_rdomain,
flow->flow_loaded ? "L" : "",
flow->flow_ikesa);

Expand Down
33 changes: 25 additions & 8 deletions sbin/iked/parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,8 @@ void copy_transforms(unsigned int,
const struct ipsec_xf **, unsigned int,
struct iked_transform **, unsigned int *,
struct iked_transform *, size_t);
int create_ike(char *, int, uint8_t, struct ipsec_hosts *,
int create_ike(char *, int, uint8_t,
int, struct ipsec_hosts *,
struct ipsec_hosts *, struct ipsec_mode *,
struct ipsec_mode *, uint8_t,
uint8_t, char *, char *,
Expand Down Expand Up @@ -408,7 +409,7 @@ typedef struct {
%token PASSIVE ACTIVE ANY TAG TAP PROTO LOCAL GROUP NAME CONFIG EAP USER
%token IKEV1 FLOW SA TCPMD5 TUNNEL TRANSPORT COUPLE DECOUPLE SET
%token INCLUDE LIFETIME BYTES INET INET6 QUICK SKIP DEFAULT
%token IPCOMP OCSP IKELIFETIME MOBIKE NOMOBIKE
%token IPCOMP OCSP IKELIFETIME MOBIKE NOMOBIKE RDOMAIN
%token FRAGMENTATION NOFRAGMENTATION
%token <v.string> STRING
%token <v.number> NUMBER
Expand All @@ -418,7 +419,7 @@ typedef struct {
%type <v.number> protoval
%type <v.hosts> hosts hosts_list
%type <v.port> port
%type <v.number> portval af
%type <v.number> portval af rdomain
%type <v.peers> peers
%type <v.anyhost> anyhost
%type <v.host> host host_spec
Expand Down Expand Up @@ -491,12 +492,12 @@ user : USER STRING STRING {
}
;

ikev2rule : IKEV2 name ikeflags satype af proto hosts_list peers
ikev2rule : IKEV2 name ikeflags satype af proto rdomain hosts_list peers
ike_sas child_sas ids ikelifetime lifetime ikeauth ikecfg
filters {
if (create_ike($2, $5, $6, $7, &$8, $9, $10, $4, $3,
$11.srcid, $11.dstid, $12, &$13, &$14,
$16, $15) == -1) {
if (create_ike($2, $5, $6, $7, $8, &$9, $10, $11, $4,
$3, $12.srcid, $12.dstid, $13, &$14, &$15,
$17, $16) == -1) {
yyerror("create_ike failed");
YYERROR;
}
Expand Down Expand Up @@ -577,6 +578,15 @@ protoval : STRING {
}
;

rdomain : /* empty */ { $$ = -1; }
| RDOMAIN NUMBER {
if ($2 > 255 || $2 < 0) {
yyerror("rdomain outside range");
YYERROR;
}
$$ = $2;
}

hosts_list : hosts { $$ = $1; }
| hosts_list comma hosts {
if ($3 == NULL)
Expand Down Expand Up @@ -1264,6 +1274,7 @@ lookup(char *s)
{ "proto", PROTO },
{ "psk", PSK },
{ "quick", QUICK },
{ "rdomain", RDOMAIN },
{ "sa", SA },
{ "set", SET },
{ "skip", SKIP },
Expand Down Expand Up @@ -2497,6 +2508,9 @@ print_policy(struct iked_policy *pol)
print_verbose(" inet6");
}

if (pol->pol_rdomain)
print_verbose(" rdomain %d", pol->pol_rdomain);

RB_FOREACH(flow, iked_flows, &pol->pol_flows) {
print_verbose(" from %s",
print_host((struct sockaddr *)&flow->flow_src.addr, NULL,
Expand Down Expand Up @@ -2679,7 +2693,8 @@ copy_transforms(unsigned int type,
}

int
create_ike(char *name, int af, uint8_t ipproto, struct ipsec_hosts *hosts,
create_ike(char *name, int af, uint8_t ipproto,
int rdomain, struct ipsec_hosts *hosts,
struct ipsec_hosts *peers, struct ipsec_mode *ike_sa,
struct ipsec_mode *ipsec_sa, uint8_t saproto,
uint8_t flags, char *srcid, char *dstid,
Expand Down Expand Up @@ -2709,6 +2724,7 @@ create_ike(char *name, int af, uint8_t ipproto, struct ipsec_hosts *hosts,
pol.pol_saproto = saproto;
pol.pol_ipproto = ipproto;
pol.pol_flags = flags;
pol.pol_rdomain = rdomain;
memcpy(&pol.pol_auth, authtype, sizeof(struct iked_auth));

if (name != NULL) {
Expand Down Expand Up @@ -2969,6 +2985,7 @@ create_ike(char *name, int af, uint8_t ipproto, struct ipsec_hosts *hosts,
}

flow->flow_ipproto = ipproto;
flow->flow_rdomain = rdomain;

if (RB_INSERT(iked_flows, &pol.pol_flows, flow) == NULL)
pol.pol_nflows++;
Expand Down
102 changes: 100 additions & 2 deletions sbin/iked/pfkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#include "ikev2.h"

#define ROUNDUP(x) (((x) + (PFKEYV2_CHUNK - 1)) & ~(PFKEYV2_CHUNK - 1))
#define IOV_CNT 20
#define IOV_CNT 21

#define PFKEYV2_CHUNK sizeof(uint64_t)
#define PFKEY_REPLY_TIMEOUT 1000
Expand All @@ -51,6 +51,8 @@
static uint32_t sadb_msg_seq = 0;
static unsigned int sadb_decoupled = 0;

static int iked_rdomain = 0;

static struct event pfkey_timer_ev;
static struct timeval pfkey_timer_tv;

Expand Down Expand Up @@ -184,6 +186,7 @@ pfkey_flow(int sd, uint8_t satype, uint8_t action, struct iked_flow *flow)
struct sadb_address sa_src, sa_dst, sa_local, sa_peer, sa_smask,
sa_dmask;
struct sadb_protocol sa_flowtype, sa_protocol;
struct sadb_x_rdomain sa_rdomain;
struct sadb_ident *sa_srcid, *sa_dstid;
struct sockaddr_storage ssrc, sdst, slocal, speer, smask, dmask;
struct iovec iov[IOV_CNT];
Expand Down Expand Up @@ -335,6 +338,14 @@ pfkey_flow(int sd, uint8_t satype, uint8_t action, struct iked_flow *flow)
SADB_EXT_IDENTITY_DST);
}

if (flow->flow_rdomain >= 0) {
/* install flow in specific rdomain */
bzero(&sa_rdomain, sizeof(sa_rdomain));
sa_rdomain.sadb_x_rdomain_exttype = SADB_X_EXT_RDOMAIN;
sa_rdomain.sadb_x_rdomain_len = sizeof(sa_rdomain) / 8;
sa_rdomain.sadb_x_rdomain_dom1 = flow->flow_rdomain;
}

iov_cnt = 0;

/* header */
Expand Down Expand Up @@ -427,6 +438,13 @@ pfkey_flow(int sd, uint8_t satype, uint8_t action, struct iked_flow *flow)
iov_cnt++;
}

if (flow->flow_rdomain >= 0) {
iov[iov_cnt].iov_base = &sa_rdomain;
iov[iov_cnt].iov_len = sizeof(sa_rdomain);
smsg.sadb_msg_len += sa_rdomain.sadb_x_rdomain_len;
iov_cnt++;
}

ret = pfkey_write(sd, &smsg, iov, iov_cnt, NULL, NULL);

free(sa_srcid);
Expand All @@ -447,6 +465,7 @@ pfkey_sa(int sd, uint8_t satype, uint8_t action, struct iked_childsa *sa)
struct sadb_x_tag sa_tag;
char *tag = NULL;
struct sadb_x_tap sa_tap;
struct sadb_x_rdomain sa_rdomain;
struct sockaddr_storage ssrc, sdst, spxy;
struct sadb_ident *sa_srcid, *sa_dstid;
struct iked_lifetime *lt;
Expand Down Expand Up @@ -532,6 +551,24 @@ pfkey_sa(int sd, uint8_t satype, uint8_t action, struct iked_childsa *sa)
bzero(&sa_ltime_hard, sizeof(sa_ltime_hard));
bzero(&sa_ltime_soft, sizeof(sa_ltime_soft));

if (pol->pol_rdomain >= 0) {
bzero(&sa_rdomain, sizeof(sa_rdomain));
sa_rdomain.sadb_x_rdomain_exttype = SADB_X_EXT_RDOMAIN;
sa_rdomain.sadb_x_rdomain_len = sizeof(sa_rdomain) / 8;
if (satype == SADB_X_SATYPE_IPCOMP) {
/* IPCOMP SAs are always in the pol_rdomain */
sa_rdomain.sadb_x_rdomain_dom1 = pol->pol_rdomain;
sa_rdomain.sadb_x_rdomain_dom2 = pol->pol_rdomain;
} else if (sa->csa_dir == IPSP_DIRECTION_OUT) {
/* switch rdomain on encrypt/decrypt */
sa_rdomain.sadb_x_rdomain_dom1 = pol->pol_rdomain;
sa_rdomain.sadb_x_rdomain_dom2 = iked_rdomain;
} else {
sa_rdomain.sadb_x_rdomain_dom1 = iked_rdomain;
sa_rdomain.sadb_x_rdomain_dom2 = pol->pol_rdomain;
}
}

if (action == SADB_DELETE)
goto send;

Expand Down Expand Up @@ -775,6 +812,13 @@ pfkey_sa(int sd, uint8_t satype, uint8_t action, struct iked_childsa *sa)
iov_cnt++;
}

if (pol->pol_rdomain >= 0) {
iov[iov_cnt].iov_base = &sa_rdomain;
iov[iov_cnt].iov_len = sizeof(sa_rdomain);
smsg.sadb_msg_len += sa_rdomain.sadb_x_rdomain_len;
iov_cnt++;
}

ret = pfkey_write(sd, &smsg, iov, iov_cnt, NULL, NULL);

free(sa_srcid);
Expand All @@ -786,15 +830,17 @@ pfkey_sa(int sd, uint8_t satype, uint8_t action, struct iked_childsa *sa)
int
pfkey_sa_last_used(int sd, struct iked_childsa *sa, uint64_t *last_used)
{
struct iked_policy *pol = sa->csa_ikesa->sa_policy;
struct sadb_msg *msg, smsg;
struct sadb_address sa_src, sa_dst;
struct sadb_sa sadb;
struct sadb_x_rdomain sa_rdomain;
struct sadb_lifetime *sa_life;
struct sockaddr_storage ssrc, sdst;
struct iovec iov[IOV_CNT];
uint8_t *data;
ssize_t n;
int iov_cnt, ret = -1;
int iov_cnt, ret = -1, rdomain;
uint8_t satype;

*last_used = 0;
Expand Down Expand Up @@ -831,6 +877,15 @@ pfkey_sa_last_used(int sd, struct iked_childsa *sa, uint64_t *last_used)
sadb.sadb_sa_state = SADB_SASTATE_MATURE;
sadb.sadb_sa_replay = 64;

if (pol->pol_rdomain >= 0) {
rdomain = (sa->csa_dir == IPSP_DIRECTION_IN) ?
iked_rdomain : pol->pol_rdomain;
bzero(&sa_rdomain, sizeof(sa_rdomain));
sa_rdomain.sadb_x_rdomain_exttype = SADB_X_EXT_RDOMAIN;
sa_rdomain.sadb_x_rdomain_len = sizeof(sa_rdomain) / 8;
sa_rdomain.sadb_x_rdomain_dom1 = rdomain;
}

bzero(&sa_src, sizeof(sa_src));
sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8;
sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
Expand Down Expand Up @@ -870,6 +925,13 @@ pfkey_sa_last_used(int sd, struct iked_childsa *sa, uint64_t *last_used)
smsg.sadb_msg_len += sa_dst.sadb_address_len;
iov_cnt++;

if (pol->pol_rdomain >= 0) {
iov[iov_cnt].iov_base = &sa_rdomain;
iov[iov_cnt].iov_len = sizeof(sa_rdomain);
smsg.sadb_msg_len += sa_rdomain.sadb_x_rdomain_len;
iov_cnt++;
}

if ((ret = pfkey_write(sd, &smsg, iov, iov_cnt, &data, &n)) != 0)
return (-1);

Expand Down Expand Up @@ -1010,8 +1072,11 @@ pfkey_sagroup(int sd, uint8_t satype1, uint8_t action,
struct sadb_address sa_dst1, sa_dst2;
struct sockaddr_storage sdst1, sdst2;
struct sadb_protocol sa_proto;
struct sadb_x_rdomain sa_rdomain;
struct iked_policy *pol;
struct iovec iov[IOV_CNT];
int iov_cnt;
int group_rdomain;
uint8_t satype2;

if (pfkey_map(pfkey_satype, sa2->csa_saproto, &satype2) == -1)
Expand Down Expand Up @@ -1052,6 +1117,28 @@ pfkey_sagroup(int sd, uint8_t satype1, uint8_t action,
sadb2.sadb_sa_exttype = SADB_X_EXT_SA2;
sadb2.sadb_sa_spi = htonl(sa2->csa_spi.spi);
sadb2.sadb_sa_state = SADB_SASTATE_MATURE;

/* Incoming SA1 (IPCOMP) and SA2 (ESP) are in different/other rdomain */
group_rdomain =
(pol = sa1->csa_ikesa->sa_policy) != NULL &&
pol->pol_rdomain >= 0 &&
satype1 == SADB_X_SATYPE_IPCOMP &&
satype2 == SADB_SATYPE_ESP;
if (group_rdomain) {
bzero(&sa_rdomain, sizeof(sa_rdomain));
sa_rdomain.sadb_x_rdomain_exttype = SADB_X_EXT_RDOMAIN;
sa_rdomain.sadb_x_rdomain_len = sizeof(sa_rdomain) / 8;
if (sa1->csa_dir == IPSP_DIRECTION_IN) {
/* only ESP SA is iked's rdomain */
sa_rdomain.sadb_x_rdomain_dom1 = pol->pol_rdomain;
sa_rdomain.sadb_x_rdomain_dom2 = iked_rdomain;
} else {
/* both SAs are in pol_rdomain */
sa_rdomain.sadb_x_rdomain_dom1 = pol->pol_rdomain;
sa_rdomain.sadb_x_rdomain_dom2 = pol->pol_rdomain;
}
}

iov_cnt = 0;

bzero(&sa_dst1, sizeof(sa_dst1));
Expand Down Expand Up @@ -1111,6 +1198,14 @@ pfkey_sagroup(int sd, uint8_t satype1, uint8_t action,
smsg.sadb_msg_len += sa_proto.sadb_protocol_len;
iov_cnt++;

/* SA1 and SA2 are from different rdomains */
if (group_rdomain) {
iov[iov_cnt].iov_base = &sa_rdomain;
iov[iov_cnt].iov_len = sizeof(sa_rdomain);
smsg.sadb_msg_len += sa_rdomain.sadb_x_rdomain_len;
iov_cnt++;
}

return (pfkey_write(sd, &smsg, iov, iov_cnt, NULL, NULL));
}

Expand Down Expand Up @@ -1467,6 +1562,8 @@ pfkey_init(struct iked *env, int fd)
struct sadb_msg smsg;
struct iovec iov;

iked_rdomain = getrtable();

/* Set up a timer to process messages deferred by the pfkey_reply */
pfkey_timer_tv.tv_sec = 1;
pfkey_timer_tv.tv_usec = 0;
Expand Down Expand Up @@ -1787,6 +1884,7 @@ pfkey_process(struct iked *env, struct pfkey_message *pm)
goto out;
}
flow.flow_dir = sa_proto->sadb_protocol_direction;
flow.flow_rdomain = -1; /* XXX get from kernel */

log_debug("%s: flow %s from %s/%s to %s/%s via %s", __func__,
flow.flow_dir == IPSP_DIRECTION_IN ? "in" : "out",
Expand Down
2 changes: 2 additions & 0 deletions sbin/iked/policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,8 @@ flow_cmp(struct iked_flow *a, struct iked_flow *b)
{
int diff = 0;

if (!diff)
diff = a->flow_rdomain - b->flow_rdomain;
if (!diff)
diff = (int)a->flow_ipproto - (int)b->flow_ipproto;
if (!diff)
Expand Down
Loading