summaryrefslogtreecommitdiff
path: root/sbin/ipsecctl
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2006-03-30 12:44:21 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2006-03-30 12:44:21 +0000
commit83b85debd5c8628d50897246c6639bafeb73e261 (patch)
tree78da9591258454546269eea10881033d358be860 /sbin/ipsecctl
parent51def059c38d8d7e87cd814ba4489e9a2e0f29a3 (diff)
allow specification of outer local ips in flows (SADB_EXT_ADDRESS_SRC); ok hshoexer, reyk
Diffstat (limited to 'sbin/ipsecctl')
-rw-r--r--sbin/ipsecctl/ipsec.conf.514
-rw-r--r--sbin/ipsecctl/ipsecctl.c14
-rw-r--r--sbin/ipsecctl/ipsecctl.h3
-rw-r--r--sbin/ipsecctl/parse.y38
-rw-r--r--sbin/ipsecctl/pfkey.c64
5 files changed, 105 insertions, 28 deletions
diff --git a/sbin/ipsecctl/ipsec.conf.5 b/sbin/ipsecctl/ipsec.conf.5
index 90d1517964b..4b5ad686a6a 100644
--- a/sbin/ipsecctl/ipsec.conf.5
+++ b/sbin/ipsecctl/ipsec.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ipsec.conf.5,v 1.33 2006/03/22 16:01:23 reyk Exp $
+.\" $OpenBSD: ipsec.conf.5,v 1.34 2006/03/30 12:44:20 markus Exp $
.\"
.\" Copyright (c) 2004 Mathieu Sauve-Frankel All rights reserved.
.\"
@@ -112,6 +112,8 @@ Thus packets in both directions will be matched.
.Aq Ar src
.Ar to
.Aq Ar dst
+.Ar local
+.Aq Ar localip
.Ar peer
.Aq Ar remote
.Xc
@@ -124,8 +126,12 @@ The keyword
.Ar any
will match any address (i.e. 0.0.0.0/0).
The
+.Ar local
+parameter specifies the address of the local endpoint of this particular
+flow and can be usually left out.
+The
.Ar peer
-parameter specifies the address of the remote endpoint of this particular
+parameter specifies the address of the remote endpoint of this
flow.
For host-to-host connections where
.Aq Ar dst
@@ -526,6 +532,10 @@ flow esp from 192.168.7.0/24 to 192.168.8.0/24 peer 192.168.3.12
flow esp out from 192.168.7.0/24 to 192.168.8.0/24 peer 192.168.3.12
flow esp in from 192.168.8.0/24 to 192.168.7.0/24 peer 192.168.3.12
+# Same as above, but explicitly specifying the local gateway ip
+flow esp from 192.168.7.0/24 to 192.168.8.0/24 \e
+ local 192.168.1.1 peer 192.168.3.12
+
# Set up IPsec SAs for flows between 192.168.3.14 and 192.168.3.12
esp from 192.168.3.14 to 192.168.3.12 spi 0xdeadbeef:0xbeefdead \e
auth hmac-sha2-256 enc aesctr authkey file "auth14:auth12" \e
diff --git a/sbin/ipsecctl/ipsecctl.c b/sbin/ipsecctl/ipsecctl.c
index 6a055c6d2b7..4291691484d 100644
--- a/sbin/ipsecctl/ipsecctl.c
+++ b/sbin/ipsecctl/ipsecctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsecctl.c,v 1.43 2006/03/22 16:01:23 reyk Exp $ */
+/* $OpenBSD: ipsecctl.c,v 1.44 2006/03/30 12:44:20 markus Exp $ */
/*
* Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
*
@@ -167,6 +167,10 @@ ipsecctl_commit(int action, struct ipsecctl *ipsec)
free(rp->dst->name);
free(rp->dst);
+ if (rp->local) {
+ free(rp->local->name);
+ free(rp->local);
+ }
if (rp->peer) {
free(rp->peer->name);
free(rp->peer);
@@ -249,6 +253,10 @@ ipsecctl_print_flow(struct ipsec_rule *r, int opts)
ipsecctl_print_addr(r->src);
printf(" to ");
ipsecctl_print_addr(r->dst);
+ if (r->local) {
+ printf(" local ");
+ ipsecctl_print_addr(r->local);
+ }
if (r->peer) {
printf(" peer ");
ipsecctl_print_addr(r->peer);
@@ -423,6 +431,10 @@ ipsecctl_show_flows(int opts)
free(rp->src);
free(rp->dst->name);
free(rp->dst);
+ if (rp->local) {
+ free(rp->local->name);
+ free(rp->local);
+ }
if (rp->peer) {
free(rp->peer->name);
free(rp->peer);
diff --git a/sbin/ipsecctl/ipsecctl.h b/sbin/ipsecctl/ipsecctl.h
index 455e72acd47..4854a95453e 100644
--- a/sbin/ipsecctl/ipsecctl.h
+++ b/sbin/ipsecctl/ipsecctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsecctl.h,v 1.29 2006/03/22 16:01:23 reyk Exp $ */
+/* $OpenBSD: ipsecctl.h,v 1.30 2006/03/30 12:44:20 markus Exp $ */
/*
* Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
*
@@ -134,6 +134,7 @@ struct ipsec_rule {
struct ipsec_addr_wrap *src;
struct ipsec_addr_wrap *dst;
+ struct ipsec_addr_wrap *local;
struct ipsec_addr_wrap *peer;
struct ipsec_auth *auth;
struct ike_auth *ikeauth;
diff --git a/sbin/ipsecctl/parse.y b/sbin/ipsecctl/parse.y
index 25b7bc281ef..97d544f2007 100644
--- a/sbin/ipsecctl/parse.y
+++ b/sbin/ipsecctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.53 2006/03/22 16:01:23 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.54 2006/03/30 12:44:20 markus Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -132,8 +132,9 @@ struct ipsec_rule *create_sa(u_int8_t, u_int8_t, struct ipsec_addr_wrap *,
struct ipsec_rule *reverse_sa(struct ipsec_rule *, u_int32_t,
struct ipsec_key *, struct ipsec_key *);
struct ipsec_rule *create_flow(u_int8_t, struct ipsec_addr_wrap *, struct
- ipsec_addr_wrap *, struct ipsec_addr_wrap *,
- u_int8_t, char *, char *, u_int8_t);
+ ipsec_addr_wrap *, struct ipsec_addr_wrap *, struct
+ ipsec_addr_wrap *, u_int8_t, char *, char *,
+ u_int8_t);
struct ipsec_rule *reverse_rule(struct ipsec_rule *);
struct ipsec_rule *create_ike(struct ipsec_addr_wrap *, struct
ipsec_addr_wrap *, struct ipsec_addr_wrap *,
@@ -155,6 +156,7 @@ typedef struct {
struct ipsec_addr_wrap *src;
struct ipsec_addr_wrap *dst;
} hosts;
+ struct ipsec_addr_wrap *local;
struct ipsec_addr_wrap *peer;
struct ipsec_addr_wrap *host;
struct {
@@ -192,7 +194,7 @@ typedef struct {
%token FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI
%token AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK PASSIVE
%token ACTIVE ANY IPIP IPCOMP COMPXF TUNNEL TRANSPORT DYNAMIC
-%token TYPE DENY BYPASS
+%token TYPE DENY BYPASS LOCAL
%token <v.string> STRING
%type <v.string> string
%type <v.dir> dir
@@ -200,6 +202,7 @@ typedef struct {
%type <v.tmode> tmode
%type <v.number> number
%type <v.hosts> hosts
+%type <v.local> local
%type <v.peer> peer
%type <v.host> host
%type <v.ids> ids
@@ -297,11 +300,11 @@ sarule : protocol tmode hosts spispec transforms authkeyspec
}
;
-flowrule : FLOW protocol dir hosts peer ids type {
+flowrule : FLOW protocol dir hosts local peer ids type {
struct ipsec_rule *r;
- r = create_flow($3, $4.src, $4.dst, $5, $2, $6.srcid,
- $6.dstid, $7);
+ r = create_flow($3, $4.src, $4.dst, $5, $6, $2,
+ $7.srcid, $7.dstid, $8);
if (r == NULL)
YYERROR;
r->nr = ipsec->rule_nr++;
@@ -310,7 +313,7 @@ flowrule : FLOW protocol dir hosts peer ids type {
errx(1, "flowrule: ipsecctl_add_rule");
/* Create and add reverse flow rule. */
- if ($7 == TYPE_UNKNOWN && $3 == IPSEC_INOUT) {
+ if ($8 == TYPE_UNKNOWN && $3 == IPSEC_INOUT) {
r = reverse_rule(r);
r->nr = ipsec->rule_nr++;
@@ -372,6 +375,17 @@ peer : /* empty */ { $$ = NULL; }
}
;
+local : /* empty */ { $$ = NULL; }
+ | LOCAL STRING {
+ if (($$ = host($2)) == NULL) {
+ free($2);
+ yyerror("could not parse host specification");
+ YYERROR;
+ }
+ free($2);
+ }
+ ;
+
host : STRING {
if (($$ = host($1)) == NULL) {
free($1);
@@ -684,6 +698,7 @@ lookup(char *s)
{ "in", IN },
{ "ipcomp", IPCOMP },
{ "ipip", IPIP },
+ { "local", LOCAL },
{ "main", MAIN },
{ "out", OUT },
{ "passive", PASSIVE },
@@ -1506,8 +1521,8 @@ reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey,
struct ipsec_rule *
create_flow(u_int8_t dir, struct ipsec_addr_wrap *src, struct ipsec_addr_wrap
- *dst, struct ipsec_addr_wrap *peer, u_int8_t proto, char *srcid, char
- *dstid, u_int8_t type)
+ *dst, struct ipsec_addr_wrap *local, struct ipsec_addr_wrap *peer,
+ u_int8_t proto, char *srcid, char *dstid, u_int8_t type)
{
struct ipsec_rule *r;
@@ -1536,6 +1551,7 @@ create_flow(u_int8_t dir, struct ipsec_addr_wrap *src, struct ipsec_addr_wrap
else
r->flowtype = TYPE_REQUIRE;
+ r->local = local;
if (peer == NULL) {
/* Set peer to remote host. Must be a host address. */
if (r->direction == IPSEC_IN) {
@@ -1596,6 +1612,8 @@ reverse_rule(struct ipsec_rule *rule)
reverse->src = copyhost(rule->dst);
reverse->dst = copyhost(rule->src);
+ if (rule->local)
+ reverse->local = copyhost(rule->local);
reverse->peer = copyhost(rule->peer);
reverse->proto = (u_int8_t)rule->proto;
diff --git a/sbin/ipsecctl/pfkey.c b/sbin/ipsecctl/pfkey.c
index 1e3e3c91104..c4d169e12dd 100644
--- a/sbin/ipsecctl/pfkey.c
+++ b/sbin/ipsecctl/pfkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.33 2006/03/07 00:30:28 reyk Exp $ */
+/* $OpenBSD: pfkey.c,v 1.34 2006/03/30 12:44:20 markus Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
* Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org>
@@ -43,7 +43,8 @@ static u_int32_t sadb_msg_seq = 1;
static int pfkey_flow(int, u_int8_t, u_int8_t, u_int8_t,
struct ipsec_addr_wrap *, struct ipsec_addr_wrap *,
- struct ipsec_addr_wrap *, struct ipsec_auth *, u_int8_t);
+ struct ipsec_addr_wrap *, struct ipsec_addr_wrap *,
+ struct ipsec_auth *, u_int8_t);
static int pfkey_sa(int, u_int8_t, u_int8_t, u_int32_t,
struct ipsec_addr_wrap *, struct ipsec_addr_wrap *,
struct ipsec_transforms *, struct ipsec_key *,
@@ -57,13 +58,15 @@ int pfkey_init(void);
static int
pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction,
struct ipsec_addr_wrap *src, struct ipsec_addr_wrap *dst,
- struct ipsec_addr_wrap *peer, struct ipsec_auth *auth, u_int8_t flowtype)
+ struct ipsec_addr_wrap *local, struct ipsec_addr_wrap *peer,
+ struct ipsec_auth *auth, u_int8_t flowtype)
{
struct sadb_msg smsg;
- struct sadb_address sa_src, sa_dst, sa_peer, sa_smask, sa_dmask;
+ struct sadb_address sa_src, sa_dst, sa_local, sa_peer, sa_smask,
+ sa_dmask;
struct sadb_protocol sa_flowtype, sa_protocol;
struct sadb_ident *sa_srcid, *sa_dstid;
- struct sockaddr_storage ssrc, sdst, speer, smask, dmask;
+ struct sockaddr_storage ssrc, sdst, slocal, speer, smask, dmask;
struct iovec iov[IOV_CNT];
ssize_t n;
int iov_cnt, len, ret = 0;
@@ -104,6 +107,22 @@ pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction,
dmask.ss_family = sdst.ss_family;
dmask.ss_len = sdst.ss_len;
+ bzero(&slocal, sizeof(slocal));
+ if (local) {
+ switch (local->af) {
+ case AF_INET:
+ ((struct sockaddr_in *)&slocal)->sin_addr =
+ local->address.v4;
+ slocal.ss_len = sizeof(struct sockaddr_in);
+ slocal.ss_family = AF_INET;
+ break;
+ case AF_INET6:
+ default:
+ warnx("unsupported address family %d", local->af);
+ return -1;
+ }
+ }
+
bzero(&speer, sizeof(speer));
if (peer) {
switch (peer->af) {
@@ -116,7 +135,7 @@ pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction,
case AF_INET6:
default:
warnx("unsupported address family %d", peer->af);
- return -1;
+ return -1;
}
}
@@ -175,10 +194,18 @@ pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction,
sa_dmask.sadb_address_len =
(sizeof(sa_dmask) + ROUNDUP(dmask.ss_len)) / 8;
- bzero(&sa_peer, sizeof(sa_peer));
- sa_peer.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
- sa_peer.sadb_address_len =
- (sizeof(sa_peer) + ROUNDUP(speer.ss_len)) / 8;
+ if (local) {
+ bzero(&sa_local, sizeof(sa_local));
+ sa_local.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ sa_local.sadb_address_len =
+ (sizeof(sa_local) + ROUNDUP(slocal.ss_len)) / 8;
+ }
+ if (peer) {
+ bzero(&sa_peer, sizeof(sa_peer));
+ sa_peer.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ sa_peer.sadb_address_len =
+ (sizeof(sa_peer) + ROUNDUP(speer.ss_len)) / 8;
+ }
if (auth && auth->srcid) {
len = ROUNDUP(strlen(auth->srcid) + 1) + sizeof(*sa_srcid);
@@ -222,6 +249,17 @@ pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction,
smsg.sadb_msg_len += sa_flowtype.sadb_protocol_len;
iov_cnt++;
+ /* local ip */
+ if (local) {
+ iov[iov_cnt].iov_base = &sa_local;
+ iov[iov_cnt].iov_len = sizeof(sa_local);
+ iov_cnt++;
+ iov[iov_cnt].iov_base = &slocal;
+ iov[iov_cnt].iov_len = ROUNDUP(slocal.ss_len);
+ smsg.sadb_msg_len += sa_local.sadb_address_len;
+ iov_cnt++;
+ }
+
/* remote peer */
if (peer) {
iov[iov_cnt].iov_base = &sa_peer;
@@ -599,7 +637,6 @@ pfkey_parse(struct sadb_msg *msg, struct ipsec_rule *rule)
ext->sadb_ext_len * PFKEYV2_CHUNK)) {
switch (ext->sadb_ext_type) {
case SADB_EXT_ADDRESS_SRC:
-#ifdef notyet
saddr = (struct sadb_address *)ext;
sa = (struct sockaddr *)(saddr + 1);
@@ -618,7 +655,6 @@ pfkey_parse(struct sadb_msg *msg, struct ipsec_rule *rule)
default:
return (1);
}
-#endif
break;
@@ -865,12 +901,12 @@ pfkey_ipsec_establish(int action, struct ipsec_rule *r)
switch (action) {
case ACTION_ADD:
ret = pfkey_flow(fd, satype, SADB_X_ADDFLOW, direction,
- r->src, r->dst, r->peer, r->auth, r->flowtype);
+ r->src, r->dst, r->local, r->peer, r->auth, r->flowtype);
break;
case ACTION_DELETE:
/* No peer for flow deletion. */
ret = pfkey_flow(fd, satype, SADB_X_DELFLOW, direction,
- r->src, r->dst, NULL, NULL, r->flowtype);
+ r->src, r->dst, NULL, NULL, NULL, r->flowtype);
break;
default:
return -1;