summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/relayd/parse.y')
-rw-r--r--usr.sbin/relayd/parse.y108
1 files changed, 85 insertions, 23 deletions
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y
index 1fa08a74550..6843c951044 100644
--- a/usr.sbin/relayd/parse.y
+++ b/usr.sbin/relayd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.122 2008/07/22 23:17:37 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.123 2008/09/29 09:58:51 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -30,6 +30,7 @@
#include <sys/queue.h>
#include <net/if.h>
+#include <net/pfvar.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
@@ -100,11 +101,12 @@ static in_port_t tableport = 0;
struct address *host_v4(const char *);
struct address *host_v6(const char *);
int host_dns(const char *, struct addresslist *,
- int, in_port_t, const char *);
+ int, struct portrange *, const char *);
int host(const char *, struct addresslist *,
- int, in_port_t, const char *);
+ int, struct portrange *, const char *);
struct table *table_inherit(struct table *);
+int getservice(char *);
typedef struct {
union {
@@ -113,6 +115,7 @@ typedef struct {
struct host *host;
struct timeval tv;
struct table *table;
+ struct portrange port;
struct {
enum digest_type type;
char *digest;
@@ -134,8 +137,9 @@ typedef struct {
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.string> interface hostname table
-%type <v.number> port http_type loglevel sslcache optssl mark parent
+%type <v.number> http_type loglevel sslcache optssl mark parent
%type <v.number> proto_type dstmode retry log flag direction forwardmode
+%type <v.port> port
%type <v.host> host
%type <v.tv> timeout
%type <v.digest> digest
@@ -231,15 +235,29 @@ eflags : STYLE STRING
;
port : PORT STRING {
- struct servent *servent;
+ char *a, *b;
+ int p[2];
- servent = getservbyname($2, "tcp");
- if (servent == NULL) {
- yyerror("port %s is invalid", $2);
+ p[0] = p[1] = 0;
+
+ a = $2;
+ b = strchr($2, ':');
+ if (b == NULL)
+ $$.op = PF_OP_EQ;
+ else {
+ *b++ = '\0';
+ if ((p[1] = getservice(b)) == -1) {
+ free($2);
+ YYERROR;
+ }
+ $$.op = PF_OP_RRG;
+ }
+ if ((p[0] = getservice(a)) == -1) {
free($2);
YYERROR;
}
- $$ = servent->s_port;
+ $$.val[0] = p[0];
+ $$.val[1] = p[1];
free($2);
}
| PORT NUMBER {
@@ -247,7 +265,8 @@ port : PORT STRING {
yyerror("invalid port: %d", $2);
YYERROR;
}
- $$ = htons($2);
+ $$.val[0] = htons($2);
+ $$.op = PF_OP_EQ;
}
;
@@ -424,7 +443,7 @@ rdroptsl : forwardmode TO tablespec interface {
}
| LISTEN ON STRING port interface {
if (host($3, &rdr->virts,
- SRV_MAX_VIRTS, $4, $5) <= 0) {
+ SRV_MAX_VIRTS, &$4, $5) <= 0) {
yyerror("invalid virtual ip: %s", $3);
free($3);
free($5);
@@ -433,7 +452,7 @@ rdroptsl : forwardmode TO tablespec interface {
free($3);
free($5);
if (rdr->conf.port == 0)
- rdr->conf.port = $4;
+ rdr->conf.port = $4.val[0];
tableport = rdr->conf.port;
}
| DISABLE { rdr->conf.flags |= F_DISABLE; }
@@ -539,6 +558,8 @@ tablespec : table {
struct table *tb;
if (table->conf.port == 0)
table->conf.port = tableport;
+ else
+ table->conf.flags |= F_PORT;
if ((tb = table_inherit(table)) == NULL)
YYERROR;
$$ = tb;
@@ -550,7 +571,13 @@ tableopts_l : tableopts tableopts_l
;
tableopts : CHECK tablecheck
- | port { table->conf.port = $1; }
+ | port {
+ if ($1.op != PF_OP_EQ) {
+ yyerror("invalid port");
+ YYERROR;
+ }
+ table->conf.port = $1.val[0];
+ }
| TIMEOUT timeout {
bcopy(&$2, &table->conf.timeout,
sizeof(struct timeval));
@@ -1117,11 +1144,17 @@ relayoptsl : LISTEN ON STRING port optssl {
if (rlay->rl_conf.ss.ss_family != AF_UNSPEC) {
yyerror("relay %s listener already specified",
rlay->rl_conf.name);
+ free($3);
+ YYERROR;
+ }
+ if ($4.op != PF_OP_EQ) {
+ yyerror("invalid port");
+ free($3);
YYERROR;
}
TAILQ_INIT(&al);
- if (host($3, &al, 1, $4, NULL) <= 0) {
+ if (host($3, &al, 1, &$4, NULL) <= 0) {
yyerror("invalid listen ip: %s", $3);
free($3);
YYERROR;
@@ -1129,12 +1162,12 @@ relayoptsl : LISTEN ON STRING port optssl {
free($3);
h = TAILQ_FIRST(&al);
bcopy(&h->ss, &rlay->rl_conf.ss, sizeof(rlay->rl_conf.ss));
- rlay->rl_conf.port = h->port;
+ rlay->rl_conf.port = h->port.val[0];
if ($5) {
rlay->rl_conf.flags |= F_SSL;
conf->sc_flags |= F_SSL;
}
- tableport = h->port;
+ tableport = h->port.val[0];
}
| forwardmode TO forwardspec interface dstaf {
rlay->rl_conf.fwdmode = $1;
@@ -1207,9 +1240,14 @@ forwardspec : tablespec {
free($1);
YYERROR;
}
+ if ($2.op != PF_OP_EQ) {
+ yyerror("invalid port");
+ free($1);
+ YYERROR;
+ }
TAILQ_INIT(&al);
- if (host($1, &al, 1, $2, NULL) <= 0) {
+ if (host($1, &al, 1, &$2, NULL) <= 0) {
yyerror("invalid listen ip: %s", $1);
free($1);
YYERROR;
@@ -1218,7 +1256,7 @@ forwardspec : tablespec {
h = TAILQ_FIRST(&al);
bcopy(&h->ss, &rlay->rl_conf.dstss,
sizeof(rlay->rl_conf.dstss));
- rlay->rl_conf.dstport = h->port;
+ rlay->rl_conf.dstport = h->port.val[0];
rlay->rl_conf.dstretry = $3;
}
| NAT LOOKUP retry {
@@ -1268,7 +1306,7 @@ host : STRING retry parent {
fatal("out of memory");
TAILQ_INIT(&al);
- if (host($1, &al, 1, 0, NULL) <= 0) {
+ if (host($1, &al, 1, NULL, NULL) <= 0) {
yyerror("invalid host %s", $2);
free($1);
free($$);
@@ -2041,7 +2079,7 @@ host_v6(const char *s)
int
host_dns(const char *s, struct addresslist *al, int max,
- in_port_t port, const char *ifname)
+ struct portrange *port, const char *ifname)
{
struct addrinfo hints, *res0, *res;
int error, cnt = 0;
@@ -2068,7 +2106,8 @@ host_dns(const char *s, struct addresslist *al, int max,
if ((h = calloc(1, sizeof(*h))) == NULL)
fatal(NULL);
- h->port = port;
+ if (port != NULL)
+ bcopy(port, &h->port, sizeof(h->port));
if (ifname != NULL) {
if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
sizeof(h->ifname))
@@ -2102,7 +2141,7 @@ host_dns(const char *s, struct addresslist *al, int max,
int
host(const char *s, struct addresslist *al, int max,
- in_port_t port, const char *ifname)
+ struct portrange *port, const char *ifname)
{
struct address *h;
@@ -2113,7 +2152,8 @@ host(const char *s, struct addresslist *al, int max,
h = host_v6(s);
if (h != NULL) {
- h->port = port;
+ if (port != NULL)
+ bcopy(port, &h->port, sizeof(h->port));
if (ifname != NULL) {
if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
sizeof(h->ifname)) {
@@ -2200,3 +2240,25 @@ table_inherit(struct table *tb)
return (tb);
}
+
+int
+getservice(char *n)
+{
+ struct servent *s;
+ const char *errstr;
+ long long llval;
+
+ llval = strtonum(n, 0, UINT16_MAX, &errstr);
+ if (errstr) {
+ s = getservbyname(n, "tcp");
+ if (s == NULL)
+ s = getservbyname(n, "udp");
+ if (s == NULL) {
+ yyerror("unknown port %s", n);
+ return (-1);
+ }
+ return (s->s_port);
+ }
+
+ return (htons((u_short)llval));
+}