summaryrefslogtreecommitdiff
path: root/sbin/ipsecctl
diff options
context:
space:
mode:
authorChristian Weisgerber <naddy@cvs.openbsd.org>2006-06-01 17:32:21 +0000
committerChristian Weisgerber <naddy@cvs.openbsd.org>2006-06-01 17:32:21 +0000
commit8210d890ba7ea1fdc9a45fedad61fe17cb7a458c (patch)
tree60f0ff1e1e1b970c148e55abd4fb497e394c5b85 /sbin/ipsecctl
parenta1f456f05a84ed5c74278b565bea5ff800fc5d8a (diff)
Support flows with port modifiers for proto tcp/udp, e.g.
flow proto udp from 1.2.3.4 port ntp to 5.6.7.8 ok hshoexer@ msf@
Diffstat (limited to 'sbin/ipsecctl')
-rw-r--r--sbin/ipsecctl/ipsecctl.c24
-rw-r--r--sbin/ipsecctl/ipsecctl.h4
-rw-r--r--sbin/ipsecctl/parse.y69
-rw-r--r--sbin/ipsecctl/pfkey.c40
4 files changed, 115 insertions, 22 deletions
diff --git a/sbin/ipsecctl/ipsecctl.c b/sbin/ipsecctl/ipsecctl.c
index 4271e7faaba..fe0c8d3745d 100644
--- a/sbin/ipsecctl/ipsecctl.c
+++ b/sbin/ipsecctl/ipsecctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsecctl.c,v 1.53 2006/06/01 16:41:38 hshoexer Exp $ */
+/* $OpenBSD: ipsecctl.c,v 1.54 2006/06/01 17:32:20 naddy Exp $ */
/*
* Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
*
@@ -47,6 +47,7 @@ int ipsecctl_add_rule(struct ipsecctl *, struct ipsec_rule *);
void ipsecctl_free_rule(struct ipsec_rule *);
void ipsecctl_print_addr(struct ipsec_addr_wrap *);
void ipsecctl_print_proto(u_int8_t);
+void ipsecctl_print_port(u_int16_t, const char *);
void ipsecctl_print_key(struct ipsec_key *);
void ipsecctl_print_flow(struct ipsec_rule *, int);
void ipsecctl_print_sa(struct ipsec_rule *, int);
@@ -262,6 +263,17 @@ ipsecctl_print_proto(u_int8_t proto)
}
void
+ipsecctl_print_port(u_int16_t port, const char *proto)
+{
+ struct servent *s;
+
+ if ((s = getservbyport(port, proto)) != NULL)
+ printf("%s", s->s_name);
+ else
+ printf("%u", ntohs(port));
+}
+
+void
ipsecctl_print_key(struct ipsec_key *key)
{
int i;
@@ -281,8 +293,18 @@ ipsecctl_print_flow(struct ipsec_rule *r, int opts)
}
printf(" from ");
ipsecctl_print_addr(r->src);
+ if (r->sport) {
+ printf(" port ");
+ ipsecctl_print_port(r->sport,
+ r->proto == IPPROTO_TCP ? "tcp" : "udp");
+ }
printf(" to ");
ipsecctl_print_addr(r->dst);
+ if (r->dport) {
+ printf(" port ");
+ ipsecctl_print_port(r->dport,
+ r->proto == IPPROTO_TCP ? "tcp" : "udp");
+ }
if (r->local) {
printf(" local ");
ipsecctl_print_addr(r->local);
diff --git a/sbin/ipsecctl/ipsecctl.h b/sbin/ipsecctl/ipsecctl.h
index 8b3e7ba8067..7e8cf6e5876 100644
--- a/sbin/ipsecctl/ipsecctl.h
+++ b/sbin/ipsecctl/ipsecctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsecctl.h,v 1.42 2006/06/01 16:13:01 markus Exp $ */
+/* $OpenBSD: ipsecctl.h,v 1.43 2006/06/01 17:32:20 naddy Exp $ */
/*
* Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
*
@@ -163,6 +163,8 @@ struct ipsec_rule {
u_int8_t direction;
u_int8_t flowtype;
u_int8_t ikemode;
+ u_int16_t sport;
+ u_int16_t dport;
u_int32_t spi;
u_int32_t spi2;
u_int32_t nr;
diff --git a/sbin/ipsecctl/parse.y b/sbin/ipsecctl/parse.y
index c96e0422505..6084ee58f14 100644
--- a/sbin/ipsecctl/parse.y
+++ b/sbin/ipsecctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.87 2006/06/01 15:33:08 markus Exp $ */
+/* $OpenBSD: parse.y,v 1.88 2006/06/01 17:32:20 naddy Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -163,8 +163,9 @@ struct ipsec_rule *create_sa(u_int8_t, u_int8_t, struct ipsec_addr_wrap *,
struct ipsec_key *);
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, u_int8_t, struct
- ipsec_addr_wrap *, struct ipsec_addr_wrap *,
+struct ipsec_rule *create_flow(u_int8_t, u_int8_t,
+ struct ipsec_addr_wrap *, u_int16_t,
+ struct ipsec_addr_wrap *, u_int16_t,
struct ipsec_addr_wrap *, struct ipsec_addr_wrap *,
u_int8_t, char *, char *, u_int8_t);
int expand_rule(struct ipsec_rule *, u_int8_t, u_int32_t,
@@ -191,7 +192,10 @@ typedef struct {
struct {
struct ipsec_addr_wrap *src;
struct ipsec_addr_wrap *dst;
+ u_int16_t sport;
+ u_int16_t dport;
} hosts;
+ u_int16_t port;
struct {
struct ipsec_addr_wrap *peer;
struct ipsec_addr_wrap *local;
@@ -233,7 +237,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 LOCAL PROTO USE ACQUIRE REQUIRE DONTACQ GROUP
+%token TYPE DENY BYPASS LOCAL PROTO USE ACQUIRE REQUIRE DONTACQ GROUP PORT
%token <v.string> STRING
%type <v.string> string
%type <v.dir> dir
@@ -242,6 +246,7 @@ typedef struct {
%type <v.tmode> tmode
%type <v.number> number
%type <v.hosts> hosts
+%type <v.port> port
%type <v.peers> peers
%type <v.singlehost> singlehost
%type <v.host> host host_list
@@ -323,8 +328,9 @@ sarule : satype tmode hosts spispec transforms authkeyspec
flowrule : FLOW satype dir proto hosts peers ids type {
struct ipsec_rule *r;
- r = create_flow($3, $4, $5.src, $5.dst, $6.local,
- $6.peer, $2, $7.srcid, $7.dstid, $8);
+ r = create_flow($3, $4, $5.src, $5.sport, $5.dst,
+ $5.dport, $6.local, $6.peer, $2, $7.srcid,
+ $7.dstid, $8);
if (r == NULL)
YYERROR;
@@ -383,13 +389,38 @@ dir : /* empty */ { $$ = IPSEC_INOUT; }
| OUT { $$ = IPSEC_OUT; }
;
-hosts : FROM host TO host {
+hosts : FROM host port TO host port {
$$.src = $2;
- $$.dst = $4;
+ $$.sport = $3;
+ $$.dst = $5;
+ $$.dport = $6;
}
- | TO host FROM host {
- $$.src = $4;
+ | TO host port FROM host port {
+ $$.src = $5;
+ $$.sport = $6;
$$.dst = $2;
+ $$.dport = $3;
+ }
+ ;
+
+port : /* empty */ { $$ = 0; }
+ | PORT STRING {
+ struct servent *s;
+ const char *errstr;
+ int port;
+
+ if ((s = getservbyname($2, "tcp")) != NULL ||
+ (s = getservbyname($2, "udp")) != NULL) {
+ $$ = s->s_port;
+ } else {
+ errstr = NULL;
+ port = strtonum($2, 0, USHRT_MAX, &errstr);
+ if (errstr) {
+ yyerror("unknown port: %s", $2);
+ YYERROR;
+ }
+ $$ = htons(port);
+ }
}
;
@@ -794,6 +825,7 @@ lookup(char *s)
{ "out", OUT },
{ "passive", PASSIVE },
{ "peer", PEER },
+ { "port", PORT },
{ "proto", PROTO },
{ "psk", PSK },
{ "quick", QUICK },
@@ -1730,6 +1762,8 @@ copyrule(struct ipsec_rule *rule)
r->tmode = rule->tmode;
r->direction = rule->direction;
r->flowtype = rule->flowtype;
+ r->sport = rule->sport;
+ r->dport = rule->dport;
r->ikemode = rule->ikemode;
r->spi = rule->spi;
r->nr = rule->nr;
@@ -1895,9 +1929,9 @@ reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey,
struct ipsec_rule *
create_flow(u_int8_t dir, u_int8_t proto, struct ipsec_addr_wrap *src,
- struct ipsec_addr_wrap *dst, struct ipsec_addr_wrap *local,
- struct ipsec_addr_wrap *peer, u_int8_t satype, char *srcid, char *dstid,
- u_int8_t type)
+ u_int16_t sport, struct ipsec_addr_wrap *dst, u_int16_t dport,
+ struct ipsec_addr_wrap *local, struct ipsec_addr_wrap *peer,
+ u_int8_t satype, char *srcid, char *dstid, u_int8_t type)
{
struct ipsec_rule *r;
@@ -1915,7 +1949,14 @@ create_flow(u_int8_t dir, u_int8_t proto, struct ipsec_addr_wrap *src,
r->satype = satype;
r->proto = proto;
r->src = src;
+ r->sport = sport;
r->dst = dst;
+ r->dport = dport;
+ if ((sport != 0 || dport != 0) &&
+ (proto != IPPROTO_TCP && proto != IPPROTO_UDP)) {
+ yyerror("no protocol supplied with source/destination ports");
+ goto errout;
+ }
if (type == TYPE_DENY || type == TYPE_BYPASS) {
r->flowtype = type;
@@ -2032,6 +2073,8 @@ reverse_rule(struct ipsec_rule *rule)
reverse->flowtype = rule->flowtype;
reverse->src = copyhost(rule->dst);
reverse->dst = copyhost(rule->src);
+ reverse->sport = rule->dport;
+ reverse->dport = rule->sport;
if (rule->local)
reverse->local = copyhost(rule->local);
if (rule->peer)
diff --git a/sbin/ipsecctl/pfkey.c b/sbin/ipsecctl/pfkey.c
index 3e70713b389..3b49ba09018 100644
--- a/sbin/ipsecctl/pfkey.c
+++ b/sbin/ipsecctl/pfkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.42 2006/06/01 12:19:59 markus Exp $ */
+/* $OpenBSD: pfkey.c,v 1.43 2006/06/01 17:32:20 naddy Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
* Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org>
@@ -42,7 +42,8 @@ static int fd;
static u_int32_t sadb_msg_seq = 1;
static int pfkey_flow(int, u_int8_t, u_int8_t, u_int8_t, u_int8_t,
- struct ipsec_addr_wrap *, struct ipsec_addr_wrap *,
+ struct ipsec_addr_wrap *, u_int16_t,
+ struct ipsec_addr_wrap *, u_int16_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,
@@ -57,7 +58,8 @@ int pfkey_init(void);
static int
pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction,
- u_int8_t proto, struct ipsec_addr_wrap *src, struct ipsec_addr_wrap *dst,
+ u_int8_t proto, struct ipsec_addr_wrap *src, u_int16_t sport,
+ struct ipsec_addr_wrap *dst, u_int16_t dport,
struct ipsec_addr_wrap *local, struct ipsec_addr_wrap *peer,
struct ipsec_auth *auth, u_int8_t flowtype)
{
@@ -81,11 +83,19 @@ pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction,
((struct sockaddr_in *)&ssrc)->sin_addr = src->address.v4;
ssrc.ss_len = sizeof(struct sockaddr_in);
((struct sockaddr_in *)&smask)->sin_addr = src->mask.v4;
+ if (sport) {
+ ((struct sockaddr_in *)&ssrc)->sin_port = sport;
+ ((struct sockaddr_in *)&smask)->sin_port = 0xffff;
+ }
break;
case AF_INET6:
((struct sockaddr_in6 *)&ssrc)->sin6_addr = src->address.v6;
ssrc.ss_len = sizeof(struct sockaddr_in6);
((struct sockaddr_in6 *)&smask)->sin6_addr = src->mask.v6;
+ if (sport) {
+ ((struct sockaddr_in6 *)&ssrc)->sin6_port = sport;
+ ((struct sockaddr_in6 *)&smask)->sin6_port = 0xffff;
+ }
break;
default:
warnx("unsupported address family %d", src->af);
@@ -101,11 +111,19 @@ pfkey_flow(int sd, u_int8_t satype, u_int8_t action, u_int8_t direction,
((struct sockaddr_in *)&sdst)->sin_addr = dst->address.v4;
sdst.ss_len = sizeof(struct sockaddr_in);
((struct sockaddr_in *)&dmask)->sin_addr = dst->mask.v4;
+ if (dport) {
+ ((struct sockaddr_in *)&sdst)->sin_port = dport;
+ ((struct sockaddr_in *)&dmask)->sin_port = 0xffff;
+ }
break;
case AF_INET6:
((struct sockaddr_in6 *)&sdst)->sin6_addr = dst->address.v6;
sdst.ss_len = sizeof(struct sockaddr_in6);
((struct sockaddr_in6 *)&dmask)->sin6_addr = dst->mask.v6;
+ if (dport) {
+ ((struct sockaddr_in6 *)&sdst)->sin6_port = dport;
+ ((struct sockaddr_in6 *)&dmask)->sin6_port = 0xffff;
+ }
break;
default:
warnx("unsupported address family %d", dst->af);
@@ -822,11 +840,15 @@ pfkey_parse(struct sadb_msg *msg, struct ipsec_rule *rule)
bcopy(&((struct sockaddr_in *)sa)->sin_addr,
&rule->src->address.v4,
sizeof(struct in_addr));
+ rule->sport =
+ ((struct sockaddr_in *)sa)->sin_port;
break;
case AF_INET6:
bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
&rule->src->address.v6,
sizeof(struct in6_addr));
+ rule->sport =
+ ((struct sockaddr_in6 *)sa)->sin6_port;
break;
default:
return (1);
@@ -850,11 +872,15 @@ pfkey_parse(struct sadb_msg *msg, struct ipsec_rule *rule)
bcopy(&((struct sockaddr_in *)sa)->sin_addr,
&rule->dst->address.v4,
sizeof(struct in_addr));
+ rule->dport =
+ ((struct sockaddr_in *)sa)->sin_port;
break;
case AF_INET6:
bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr,
&rule->dst->address.v6,
sizeof(struct in6_addr));
+ rule->dport =
+ ((struct sockaddr_in6 *)sa)->sin6_port;
break;
default:
return (1);
@@ -965,14 +991,14 @@ pfkey_ipsec_establish(int action, struct ipsec_rule *r)
switch (action) {
case ACTION_ADD:
ret = pfkey_flow(fd, satype, SADB_X_ADDFLOW, direction,
- r->proto, r->src, r->dst, r->local, r->peer, r->auth,
- r->flowtype);
+ r->proto, r->src, r->sport, r->dst, r->dport,
+ 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->proto, r->src, r->dst, NULL, NULL, NULL,
- r->flowtype);
+ r->proto, r->src, r->sport, r->dst, r->dport,
+ NULL, NULL, NULL, r->flowtype);
break;
default:
return -1;