diff options
author | Christian Weisgerber <naddy@cvs.openbsd.org> | 2006-06-01 17:32:21 +0000 |
---|---|---|
committer | Christian Weisgerber <naddy@cvs.openbsd.org> | 2006-06-01 17:32:21 +0000 |
commit | 8210d890ba7ea1fdc9a45fedad61fe17cb7a458c (patch) | |
tree | 60f0ff1e1e1b970c148e55abd4fb497e394c5b85 /sbin/ipsecctl | |
parent | a1f456f05a84ed5c74278b565bea5ff800fc5d8a (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.c | 24 | ||||
-rw-r--r-- | sbin/ipsecctl/ipsecctl.h | 4 | ||||
-rw-r--r-- | sbin/ipsecctl/parse.y | 69 | ||||
-rw-r--r-- | sbin/ipsecctl/pfkey.c | 40 |
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; |