summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd/parse.y
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2007-12-08 17:07:10 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2007-12-08 17:07:10 +0000
commit67f014d739e406309e7192d88049bf4590b0b84e (patch)
treedb090ce82f941a06ca8af38a2cc7553a18265fde /usr.sbin/relayd/parse.y
parentd6e596645f91520c4d84ae7559efde1ba27dea9d (diff)
some changes to the relayd.conf configuration language and grammar.
the tables will look more like pf tables, it is easier to re-use tables with different options, "services" will become "redirections" (they refer to rdr pf rules), sync configuration directives of redirect (l3, ex-service) relay (l7) sections (for example "virtual host" will become "listen on"), all target definitions will start with "forward to", etc. pp. (see relay.conf(5) and etc/relayd.conf) discussed with pyr and deraadt ok pyr@
Diffstat (limited to 'usr.sbin/relayd/parse.y')
-rw-r--r--usr.sbin/relayd/parse.y514
1 files changed, 253 insertions, 261 deletions
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y
index f729fb4d1eb..1865e787e99 100644
--- a/usr.sbin/relayd/parse.y
+++ b/usr.sbin/relayd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.97 2007/12/07 17:17:00 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.98 2007/12/08 17:07:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -94,6 +94,7 @@ static struct relay *rlay = NULL;
static struct protocol *proto = NULL;
static struct protonode node;
static u_int16_t label = 0;
+static in_port_t tableport = 0;
struct address *host_v4(const char *);
struct address *host_v6(const char *);
@@ -102,7 +103,7 @@ int host_dns(const char *, struct addresslist *,
int host(const char *, struct addresslist *,
int, in_port_t, const char *);
-struct table *table_inherit(const char *, in_port_t);
+struct table *table_inherit(struct table *);
typedef struct {
union {
@@ -110,6 +111,7 @@ typedef struct {
char *string;
struct host *host;
struct timeval tv;
+ struct table *table;
struct {
enum digest_type type;
char *digest;
@@ -120,23 +122,23 @@ typedef struct {
%}
-%token SERVICE TABLE BACKUP HOST REAL INCLUDE
-%token CHECK TCP ICMP EXTERNAL REQUEST RESPONSE
-%token TIMEOUT CODE DIGEST PORT TAG INTERFACE STYLE RETURN LABEL
-%token VIRTUAL INTERVAL DISABLE STICKYADDR BACKLOG PATH SCRIPT WITH
-%token SEND EXPECT NOTHING SSL LOADBALANCE ROUNDROBIN CIPHERS COOKIE
-%token RELAY LISTEN ON FORWARD TO NAT LOOKUP PREFORK NO MARK MARKED URL
-%token PROTO SESSION CACHE APPEND CHANGE REMOVE FROM FILTER HASH HEADER
-%token LOG UPDATES ALL DEMOTE NODELAY SACK SOCKET BUFFER QUERYSTR RETRY IP
-%token ERROR
+%token ALL APPEND BACKLOG BACKUP BUFFER CACHE CHANGE CHECK CIPHERS
+%token CODE COOKIE DEMOTE DIGEST DISABLE EXPECT EXTERNAL FILTER FORWARD
+%token FROM HASH HEADER HOST ICMP INCLUDE INTERFACE INTERVAL IP LABEL
+%token LISTEN LOADBALANCE LOG LOOKUP MARK MARKED MODE NAT NO NODELAY NOTHING
+%token ON PATH PORT PREFORK PROTO QUERYSTR REAL REDIRECT RELAY REMOVE
+%token REQUEST RESPONSE RETRY RETURN ROUNDROBIN SACK SCRIPT SEND SESSION
+%token SOCKET SSL STICKYADDR STYLE TABLE TAG TCP TIMEOUT TO UPDATES URL
+%token VIRTUAL WITH ERROR
%token <v.string> STRING
%token <v.number> NUMBER
-%type <v.string> interface hostname
-%type <v.number> port http_type loglevel sslcache optssl dstport mark
-%type <v.number> proto_type dstmode docheck retry log flag direction
+%type <v.string> interface hostname table
+%type <v.number> port http_type loglevel sslcache optssl mark
+%type <v.number> proto_type dstmode retry log flag direction
%type <v.host> host
%type <v.tv> timeout
%type <v.digest> digest
+%type <v.table> tablespec
%%
@@ -146,7 +148,7 @@ grammar : /* empty */
| grammar varset '\n'
| grammar main '\n'
| grammar service '\n'
- | grammar table '\n'
+ | grammar tabledef '\n'
| grammar relay '\n'
| grammar proto '\n'
| grammar error '\n' { file->errors++; }
@@ -308,14 +310,14 @@ loglevel : UPDATES { $$ = RELAYD_OPT_LOGUPDATE; }
| ALL { $$ = RELAYD_OPT_LOGALL; }
;
-service : SERVICE STRING {
+service : REDIRECT STRING {
struct service *srv;
TAILQ_FOREACH(srv, conf->services, entry)
if (!strcmp(srv->conf.name, $2))
break;
if (srv != NULL) {
- yyerror("service %s defined twice", $2);
+ yyerror("redirection %s defined twice", $2);
free($2);
YYERROR;
}
@@ -325,24 +327,24 @@ service : SERVICE STRING {
if (strlcpy(srv->conf.name, $2,
sizeof(srv->conf.name)) >=
sizeof(srv->conf.name)) {
- yyerror("service name truncated");
+ yyerror("redirection name truncated");
YYERROR;
}
free($2);
srv->conf.id = last_service_id++;
if (last_service_id == INT_MAX) {
- yyerror("too many services defined");
+ yyerror("too many redirections defined");
YYERROR;
}
service = srv;
} '{' optnl serviceopts_l '}' {
if (service->table == NULL) {
- yyerror("service %s has no table",
+ yyerror("redirection %s has no table",
service->conf.name);
YYERROR;
}
if (TAILQ_EMPTY(&service->virts)) {
- yyerror("service %s has no virtual ip",
+ yyerror("redirection %s has no virtual ip",
service->conf.name);
YYERROR;
}
@@ -353,15 +355,16 @@ service : SERVICE STRING {
service->backup = &conf->empty_table;
} else if (service->backup->conf.port !=
service->table->conf.port) {
- yyerror("service %s uses two different ports "
- "for its table and backup table",
+ yyerror("redirection %s uses two different "
+ "ports for its table and backup table",
service->conf.name);
YYERROR;
}
-
if (!(service->conf.flags & F_DISABLE))
service->conf.flags |= F_ADD;
TAILQ_INSERT_HEAD(conf->services, service, entry);
+ tableport = 0;
+ service = NULL;
}
;
@@ -369,49 +372,28 @@ serviceopts_l : serviceopts_l serviceoptsl nl
| serviceoptsl optnl
;
-serviceoptsl : TABLE STRING dstport {
- struct table *tb;
- in_port_t port;
-
- port = $3;
- if (port == 0)
- port = service->conf.port;
- if ((tb = table_inherit($2, port)) == NULL) {
- free($2);
+serviceoptsl : FORWARD TO tablespec {
+ if ($3->conf.check == CHECK_NOCHECK) {
+ yyerror("table %s has no check", $3->conf.name);
+ purge_table(conf->tables, $3);
YYERROR;
}
- free($2);
-
- service->table = tb;
- service->conf.table_id = tb->conf.id;
- service->table->conf.serviceid = service->conf.id;
- service->table->conf.flags |= F_USED;
- }
- | BACKUP TABLE STRING dstport {
- struct table *tb;
- in_port_t port;
-
if (service->backup) {
- yyerror("backup already specified");
- free($3);
+ yyerror("only one backup table is allowed");
+ purge_table(conf->tables, $3);
YYERROR;
}
-
- port = $4;
- if (port == 0)
- port = service->conf.port;
- if ((tb = table_inherit($3, port)) == NULL) {
- free($3);
- YYERROR;
+ if (service->table) {
+ service->backup = $3;
+ service->conf.backup_id = $3->conf.id;
+ } else {
+ service->table = $3;
+ service->conf.table_id = $3->conf.id;
}
- free($3);
-
- service->backup = tb;
- service->conf.backup_id = tb->conf.id;
- service->backup->conf.serviceid = service->conf.id;
- service->backup->conf.flags |= (F_USED|F_BACKUP);
+ $3->conf.serviceid = service->conf.id;
+ $3->conf.flags |= F_USED;
}
- | VIRTUAL HOST STRING port interface {
+ | LISTEN ON STRING port interface {
if (host($3, &service->virts,
SRV_MAX_VIRTS, $4, $5) <= 0) {
yyerror("invalid virtual ip: %s", $3);
@@ -423,6 +405,7 @@ serviceoptsl : TABLE STRING dstport {
free($5);
if (service->conf.port == 0)
service->conf.port = $4;
+ tableport = service->conf.port;
}
| DISABLE { service->conf.flags |= F_DISABLE; }
| STICKYADDR { service->conf.flags |= F_STICKY; }
@@ -430,7 +413,7 @@ serviceoptsl : TABLE STRING dstport {
if (strlcpy(service->conf.tag, $2,
sizeof(service->conf.tag)) >=
sizeof(service->conf.tag)) {
- yyerror("service tag name truncated");
+ yyerror("redirection tag name truncated");
free($2);
YYERROR;
}
@@ -439,7 +422,17 @@ serviceoptsl : TABLE STRING dstport {
| include
;
-table : TABLE STRING {
+table : '<' STRING '>' {
+ if (strlen($2) >= TABLE_NAME_SIZE) {
+ yyerror("invalid table name");
+ free($2);
+ YYERROR;
+ }
+ $$ = $2;
+ }
+ ;
+
+tabledef : TABLE table {
struct table *tb;
TAILQ_FOREACH(tb, conf->tables, entry)
@@ -454,11 +447,9 @@ table : TABLE STRING {
if ((tb = calloc(1, sizeof (*tb))) == NULL)
fatal("out of memory");
- if (strlcpy(tb->conf.name, $2, sizeof(tb->conf.name)) >=
- sizeof(tb->conf.name)) {
- yyerror("table name truncated");
- YYERROR;
- }
+ (void)strlcpy(tb->conf.name, $2, sizeof(tb->conf.name));
+ free($2);
+
tb->conf.id = last_table_id++;
bcopy(&conf->timeout, &tb->conf.timeout,
sizeof(struct timeval));
@@ -466,148 +457,183 @@ table : TABLE STRING {
yyerror("too many tables defined");
YYERROR;
}
- free($2);
table = tb;
- } '{' optnl tableopts_l '}' {
+ } tabledefopts_l {
if (TAILQ_EMPTY(&table->hosts)) {
yyerror("table %s has no hosts",
table->conf.name);
YYERROR;
}
- if (table->conf.check == CHECK_NOCHECK) {
- yyerror("table %s has no check",
- table->conf.name);
- YYERROR;
- }
conf->tablecount++;
TAILQ_INSERT_HEAD(conf->tables, table, entry);
}
;
-tableopts_l : tableopts_l tableoptsl nl
- | tableoptsl optnl
+tabledefopts_l : tabledefopts_l tabledefopts
+ | tabledefopts
+ ;
+
+tabledefopts : DISABLE { table->conf.flags |= F_DISABLE; }
+ | '{' optnl tablelist_l '}'
+ ;
+
+tablelist_l : tablelist comma tablelist_l
+ | tablelist optnl
;
-tableoptsl : host {
+tablelist : host {
$1->conf.tableid = table->conf.id;
$1->tablename = table->conf.name;
TAILQ_INSERT_HEAD(&table->hosts, $1, entry);
}
+ | include
+ ;
+
+tablespec : table {
+ struct table *tb;
+ if ((tb = calloc(1, sizeof (*tb))) == NULL)
+ fatal("out of memory");
+ (void)strlcpy(tb->conf.name, $1, sizeof(tb->conf.name));
+ free($1);
+ table = tb;
+ } tableopts_l {
+ struct table *tb;
+ if (table->conf.port == 0)
+ table->conf.port = tableport;
+ if ((tb = table_inherit(table)) == NULL)
+ YYERROR;
+ $$ = tb;
+ }
+ ;
+
+tableopts_l : tableopts tableopts_l
+ | tableopts
+ ;
+
+tableopts : CHECK tablecheck
+ | port { table->conf.port = $1; }
| TIMEOUT timeout {
bcopy(&$2, &table->conf.timeout,
sizeof(struct timeval));
}
- | CHECK ICMP {
- table->conf.check = CHECK_ICMP;
+ | DEMOTE STRING {
+ table->conf.flags |= F_DEMOTE;
+ if (strlcpy(table->conf.demote_group, $2,
+ sizeof(table->conf.demote_group))
+ >= sizeof(table->conf.demote_group)) {
+ yyerror("yyparse: demote group name too long");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ if (carp_demote_init(table->conf.demote_group, 1)
+ == -1) {
+ yyerror("yyparse: error initializing group "
+ "'%s'", table->conf.demote_group);
+ YYERROR;
+ }
+ }
+ | INTERVAL NUMBER {
+ if ($2 < conf->interval.tv_sec ||
+ $2 % conf->interval.tv_sec) {
+ yyerror("table interval must be "
+ "divisible by global interval");
+ YYERROR;
+ }
+ table->conf.skip_cnt = ($2 / conf->interval.tv_sec) - 1;
}
- | CHECK TCP {
- table->conf.check = CHECK_TCP;
+ | MODE dstmode {
+ switch ($2) {
+ case RELAY_DSTMODE_LOADBALANCE:
+ case RELAY_DSTMODE_HASH:
+ if (service != NULL) {
+ yyerror("mode not supported "
+ "for redirections");
+ YYERROR;
+ }
+ /* FALLTHROUGH */
+ case RELAY_DSTMODE_ROUNDROBIN:
+ if (rlay != NULL)
+ rlay->conf.dstmode = $2;
+ break;
+ }
}
- | CHECK SSL {
+ ;
+
+tablecheck : ICMP { table->conf.check = CHECK_ICMP; }
+ | TCP { table->conf.check = CHECK_TCP; }
+ | SSL {
table->conf.check = CHECK_TCP;
conf->flags |= F_SSL;
table->conf.flags |= F_SSL;
}
- | CHECK http_type STRING hostname CODE NUMBER {
- if ($2) {
+ | http_type STRING hostname CODE NUMBER {
+ if ($1) {
conf->flags |= F_SSL;
table->conf.flags |= F_SSL;
}
table->conf.check = CHECK_HTTP_CODE;
- if ((table->conf.retcode = $6) <= 0) {
- yyerror("invalid HTTP code: %d", $6);
+ if ((table->conf.retcode = $5) <= 0) {
+ yyerror("invalid HTTP code: %d", $5);
+ free($2);
free($3);
- free($4);
YYERROR;
}
if (asprintf(&table->sendbuf,
- "HEAD %s HTTP/1.0\r\n%s\r\n", $3, $4) == -1)
+ "HEAD %s HTTP/1.0\r\n%s\r\n", $2, $3) == -1)
fatal("asprintf");
+ free($2);
free($3);
- free($4);
if (table->sendbuf == NULL)
fatal("out of memory");
table->sendbuf_len = strlen(table->sendbuf);
}
- | CHECK http_type STRING hostname digest {
- if ($2) {
+ | http_type STRING hostname digest {
+ if ($1) {
conf->flags |= F_SSL;
table->conf.flags |= F_SSL;
}
table->conf.check = CHECK_HTTP_DIGEST;
if (asprintf(&table->sendbuf,
- "GET %s HTTP/1.0\r\n%s\r\n", $3, $4) == -1)
+ "GET %s HTTP/1.0\r\n%s\r\n", $2, $3) == -1)
fatal("asprintf");
+ free($2);
free($3);
- free($4);
if (table->sendbuf == NULL)
fatal("out of memory");
table->sendbuf_len = strlen(table->sendbuf);
- (void)strlcpy(table->conf.digest, $5.digest,
+ (void)strlcpy(table->conf.digest, $4.digest,
sizeof(table->conf.digest));
- table->conf.digest_type = $5.type;
- free($5.digest);
+ table->conf.digest_type = $4.type;
+ free($4.digest);
}
- | CHECK SEND sendbuf EXPECT STRING optssl {
+ | SEND sendbuf EXPECT STRING optssl {
table->conf.check = CHECK_SEND_EXPECT;
- if ($6) {
+ if ($5) {
conf->flags |= F_SSL;
table->conf.flags |= F_SSL;
}
- if (strlcpy(table->conf.exbuf, $5,
+ if (strlcpy(table->conf.exbuf, $4,
sizeof(table->conf.exbuf))
>= sizeof(table->conf.exbuf)) {
yyerror("yyparse: expect buffer truncated");
- free($5);
+ free($4);
YYERROR;
}
translate_string(table->conf.exbuf);
- free($5);
+ free($4);
}
- | CHECK SCRIPT STRING {
+ | SCRIPT STRING {
table->conf.check = CHECK_SCRIPT;
- if (strlcpy(table->conf.path, $3,
+ if (strlcpy(table->conf.path, $2,
sizeof(table->conf.path)) >=
sizeof(table->conf.path)) {
yyerror("script path truncated");
- free($3);
- YYERROR;
- }
- free($3);
- }
- | REAL port {
- table->conf.port = $2;
- }
- | DEMOTE STRING {
- table->conf.flags |= F_DEMOTE;
- if (strlcpy(table->conf.demote_group, $2,
- sizeof(table->conf.demote_group))
- >= sizeof(table->conf.demote_group)) {
- yyerror("yyparse: demote group name too long");
free($2);
YYERROR;
}
free($2);
- if (carp_demote_init(table->conf.demote_group, 1)
- == -1) {
- yyerror("yyparse: error initializing group "
- "'%s'", table->conf.demote_group);
- YYERROR;
- }
- }
- | DISABLE {
- table->conf.flags |= F_DISABLE;
- }
- | INTERVAL NUMBER {
- if ($2 < conf->interval.tv_sec ||
- $2 % conf->interval.tv_sec) {
- yyerror("table interval must be "
- "divisible by global interval");
- YYERROR;
- }
- table->conf.skip_cnt = ($2 / conf->interval.tv_sec) - 1;
}
- | include
;
digest : DIGEST STRING
@@ -628,31 +654,32 @@ digest : DIGEST STRING
}
;
-proto : PROTO STRING {
+proto : proto_type PROTO STRING {
struct protocol *p;
- if (strcmp($2, "default") == 0) {
+ if (strcmp($3, "default") == 0) {
p = &conf->proto_default;
} else {
TAILQ_FOREACH(p, conf->protos, entry)
- if (!strcmp(p->name, $2))
+ if (!strcmp(p->name, $3))
break;
}
if (p != NULL) {
- yyerror("protocol %s defined twice", $2);
- free($2);
+ yyerror("protocol %s defined twice", $3);
+ free($3);
YYERROR;
}
if ((p = calloc(1, sizeof (*p))) == NULL)
fatal("out of memory");
- if (strlcpy(p->name, $2, sizeof(p->name)) >=
+ if (strlcpy(p->name, $3, sizeof(p->name)) >=
sizeof(p->name)) {
yyerror("protocol name truncated");
YYERROR;
}
- free($2);
+ free($3);
p->id = last_proto_id++;
+ p->type = $1;
p->cache = RELAY_CACHESIZE;
p->type = RELAY_PROTO_TCP;
p->tcpflags = TCPFLAG_DEFAULT;
@@ -667,7 +694,7 @@ proto : PROTO STRING {
RB_INIT(&p->request_tree);
RB_INIT(&p->response_tree);
proto = p;
- } '{' optnl protopts_l '}' {
+ } protopts_n {
conf->protocount++;
if ((proto->sslflags & SSLFLAG_VERSION) == 0) {
@@ -679,6 +706,11 @@ proto : PROTO STRING {
}
;
+protopts_n : /* empty */
+ | '{' '}'
+ | '{' optnl protopts_l '}'
+ ;
+
protopts_l : protopts_l protoptsl nl
| protoptsl optnl
;
@@ -687,7 +719,6 @@ protoptsl : SSL sslflags
| SSL '{' sslflags_l '}'
| TCP tcpflags
| TCP '{' tcpflags_l '}'
- | PROTO proto_type { proto->type = $2; }
| RETURN ERROR opteflags { proto->flags |= F_RETURN; }
| RETURN ERROR '{' eflags_l '}' { proto->flags |= F_RETURN; }
| LABEL STRING {
@@ -1111,6 +1142,8 @@ relay : RELAY STRING {
conf->relaycount++;
SPLAY_INIT(&rlay->sessions);
TAILQ_INSERT_HEAD(conf->relays, rlay, entry);
+ tableport = 0;
+ rlay = NULL;
}
;
@@ -1142,103 +1175,75 @@ relayoptsl : LISTEN ON STRING port optssl {
rlay->conf.flags |= F_SSL;
conf->flags |= F_SSL;
}
+ tableport = h->port;
}
- | FORWARD TO STRING port retry {
- struct addresslist al;
- struct address *h;
+ | FORWARD TO forwardspec
+ | FORWARD TIMEOUT NUMBER {
+ if ((rlay->conf.timeout.tv_sec = $3) < 0) {
+ yyerror("invalid timeout: %d", $3);
+ YYERROR;
+ }
+ }
+ | PROTO STRING {
+ struct protocol *p;
- if (rlay->conf.dstss.ss_family != AF_UNSPEC) {
- yyerror("relay %s target or service already "
- "specified", rlay->conf.name);
- free($3);
+ TAILQ_FOREACH(p, conf->protos, entry)
+ if (!strcmp(p->name, $2))
+ break;
+ if (p == NULL) {
+ yyerror("no such protocol: %s", $2);
+ free($2);
YYERROR;
}
+ p->flags |= F_USED;
+ rlay->conf.proto = p->id;
+ rlay->proto = p;
+ free($2);
+ }
+ | DISABLE { rlay->conf.flags |= F_DISABLE; }
+ | include
+ ;
- TAILQ_INIT(&al);
- if (host($3, &al, 1, $4, NULL) <= 0) {
- yyerror("invalid listen ip: %s", $3);
- free($3);
+forwardspec : tablespec {
+ if (rlay->dsttable) {
+ yyerror("table already specified");
+ purge_table(conf->tables, $1);
YYERROR;
}
- free($3);
- h = TAILQ_FIRST(&al);
- bcopy(&h->ss, &rlay->conf.dstss,
- sizeof(rlay->conf.dstss));
- rlay->conf.dstport = h->port;
- rlay->conf.dstretry = $5;
+
+ rlay->dsttable = $1;
+ rlay->dsttable->conf.flags |= F_USED;
+ rlay->conf.dsttable = $1->conf.id;
+ rlay->conf.dstport = $1->conf.port;
}
- | SERVICE STRING retry {
- struct service *svc;
- struct address *h;
+ | STRING port retry {
+ struct addresslist al;
+ struct address *h;
if (rlay->conf.dstss.ss_family != AF_UNSPEC) {
- yyerror("relay %s target or service already "
+ yyerror("relay %s target or redirection already "
"specified", rlay->conf.name);
- free($2);
+ free($1);
YYERROR;
}
- if ((svc = service_findbyname(conf, $2)) == NULL) {
- yyerror("relay %s for unknown service %s",
- rlay->conf.name, $2);
- free($2);
+ TAILQ_INIT(&al);
+ if (host($1, &al, 1, $2, NULL) <= 0) {
+ yyerror("invalid listen ip: %s", $1);
+ free($1);
YYERROR;
}
- free($2);
- h = TAILQ_FIRST(&svc->virts);
+ free($1);
+ h = TAILQ_FIRST(&al);
bcopy(&h->ss, &rlay->conf.dstss,
sizeof(rlay->conf.dstss));
rlay->conf.dstport = h->port;
rlay->conf.dstretry = $3;
}
- | TABLE STRING dstport dstmode docheck {
- struct table *tb;
-
- rlay->conf.dstport = $3;
- if (rlay->conf.dstport == 0)
- rlay->conf.dstport = rlay->conf.port;
-
- if ((tb = table_inherit($2, rlay->conf.dstport)) ==
- NULL) {
- free($2);
- YYERROR;
- }
- free($2);
- rlay->conf.dsttable = tb->conf.id;
- rlay->dsttable = tb;
- rlay->conf.dstport = tb->conf.port;
- rlay->conf.dstmode = $4;
- rlay->conf.dstcheck = $5;
- rlay->dsttable->conf.flags |= F_USED;
- }
- | PROTO STRING {
- struct protocol *p;
-
- TAILQ_FOREACH(p, conf->protos, entry)
- if (!strcmp(p->name, $2))
- break;
- if (p == NULL) {
- yyerror("no such protocol: %s", $2);
- free($2);
- YYERROR;
- }
- p->flags |= F_USED;
- rlay->conf.proto = p->id;
- rlay->proto = p;
- free($2);
- }
- | NAT LOOKUP retry {
+ | NAT LOOKUP retry {
rlay->conf.flags |= F_NATLOOK;
rlay->conf.dstretry = $3;
}
- | TIMEOUT NUMBER {
- if ((rlay->conf.timeout.tv_sec = $2) < 0) {
- yyerror("invalid timeout: %d", $2);
- YYERROR;
- }
- }
- | DISABLE { rlay->conf.flags |= F_DISABLE; }
- | include
;
dstmode : /* empty */ { $$ = RELAY_DSTMODE_DEFAULT; }
@@ -1247,19 +1252,11 @@ dstmode : /* empty */ { $$ = RELAY_DSTMODE_DEFAULT; }
| HASH { $$ = RELAY_DSTMODE_HASH; }
;
-docheck : /* empty */ { $$ = 1; }
- | NO CHECK { $$ = 0; }
- ;
-
interface : /*empty*/ { $$ = NULL; }
| INTERFACE STRING { $$ = $2; }
;
-dstport : /* empty */ { $$ = 0; }
- | port { $$ = $1; }
- ;
-
-host : HOST STRING retry {
+host : STRING retry {
struct address *a;
struct addresslist al;
@@ -1267,9 +1264,9 @@ host : HOST STRING retry {
fatal("out of memory");
TAILQ_INIT(&al);
- if (host($2, &al, 1, 0, NULL) <= 0) {
+ if (host($1, &al, 1, 0, NULL) <= 0) {
yyerror("invalid host %s", $2);
- free($2);
+ free($1);
free($$);
YYERROR;
}
@@ -1277,16 +1274,16 @@ host : HOST STRING retry {
memcpy(&$$->conf.ss, &a->ss, sizeof($$->conf.ss));
free(a);
- if (strlcpy($$->conf.name, $2, sizeof($$->conf.name)) >=
+ if (strlcpy($$->conf.name, $1, sizeof($$->conf.name)) >=
sizeof($$->conf.name)) {
yyerror("host name truncated");
- free($2);
+ free($1);
free($$);
YYERROR;
}
- free($2);
+ free($1);
$$->conf.id = last_host_id++;
- $$->conf.retry = $3;
+ $$->conf.retry = $2;
if (last_host_id == INT_MAX) {
yyerror("too many hosts defined");
free($$);
@@ -1320,6 +1317,7 @@ log : /* empty */ { $$ = 0; }
;
comma : ','
+ | nl
| /* empty */
;
@@ -1397,6 +1395,7 @@ lookup(char *s)
{ "lookup", LOOKUP },
{ "mark", MARK },
{ "marked", MARKED },
+ { "mode", MODE },
{ "nat", NAT },
{ "no", NO },
{ "nodelay", NODELAY },
@@ -1408,6 +1407,7 @@ lookup(char *s)
{ "protocol", PROTO },
{ "query", QUERYSTR },
{ "real", REAL },
+ { "redirect", REDIRECT },
{ "relay", RELAY },
{ "remove", REMOVE },
{ "request", REQUEST },
@@ -1418,7 +1418,6 @@ lookup(char *s)
{ "sack", SACK },
{ "script", SCRIPT },
{ "send", SEND },
- { "service", SERVICE },
{ "session", SESSION },
{ "socket", SOCKET },
{ "ssl", SSL },
@@ -1654,7 +1653,7 @@ nodigits:
#define allowed_in_string(x) \
(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
- x != '{' && x != '}' && \
+ x != '{' && x != '}' && x != '<' && x != '>' && \
x != '!' && x != '=' && x != '#' && \
x != ','))
@@ -1827,7 +1826,7 @@ parse_config(const char *filename, int opts)
}
if (TAILQ_EMPTY(conf->services) && TAILQ_EMPTY(conf->relays)) {
- log_warnx("no services, nothing to do");
+ log_warnx("no redirections, nothing to do");
errors++;
}
@@ -2086,53 +2085,45 @@ host(const char *s, struct addresslist *al, int max,
}
struct table *
-table_inherit(const char *name, in_port_t port)
+table_inherit(struct table *tb)
{
char pname[TABLE_NAME_SIZE + 6];
struct host *h, *dsth;
- struct table *dsttb, *tb;
+ struct table *dsttb, *oldtb;
/* Get the table or table template */
- if ((dsttb = table_findbyname(conf, name)) == NULL) {
- yyerror("unknown table or template %s", name);
+ if ((dsttb = table_findbyname(conf, tb->conf.name)) == NULL) {
+ yyerror("unknown table %s", tb->conf.name);
+ purge_table(NULL, tb);
return (NULL);
}
if (dsttb->conf.port != 0)
- return (dsttb);
+ fatal("invalid table"); /* should not happen */
- if (port == 0) {
+ if (tb->conf.port == 0) {
yyerror("invalid port");
+ purge_table(NULL, tb);
return (NULL);
}
/* Check if a matching table already exists */
- snprintf(pname, sizeof(pname), "%s:%u", name, ntohs(port));
- if ((tb = table_findbyname(conf, pname)) != NULL) {
- if (tb->conf.port == 0) {
- yyerror("invalid table");
- return (NULL);
- }
- return (tb);
+ if (snprintf(pname, sizeof(pname), "%s:%u",
+ tb->conf.name, ntohs(tb->conf.port)) >= (int)sizeof(pname)) {
+ yyerror("invalid table name");
+ return (NULL);
}
+ (void)strlcpy(tb->conf.name, pname, sizeof(tb->conf.name));
+ if ((oldtb = table_findbyconf(conf, tb)) != NULL)
+ return (oldtb);
/* Create a new table */
- if ((tb = calloc(1, sizeof (*tb))) == NULL)
- fatal("out of memory");
- bcopy(dsttb, tb, sizeof(*tb));
- if (strlcpy(tb->conf.name, pname, sizeof(tb->conf.name))
- >= sizeof(tb->conf.name)) {
- yyerror("table name truncated");
- return (NULL);
- }
- if (dsttb->sendbuf != NULL &&
- (tb->sendbuf = strdup(dsttb->sendbuf)) == NULL)
- fatal("out of memory");
- tb->conf.port = port;
tb->conf.id = last_table_id++;
if (last_table_id == INT_MAX) {
yyerror("too many tables defined");
+ purge_table(NULL, tb);
return (NULL);
}
+ tb->conf.flags |= dsttb->conf.flags;
/* Copy the associated hosts */
bzero(&tb->hosts, sizeof(tb->hosts));
@@ -2144,6 +2135,7 @@ table_inherit(const char *name, in_port_t port)
h->conf.id = last_host_id++;
if (last_host_id == INT_MAX) {
yyerror("too many hosts defined");
+ purge_table(NULL, tb);
return (NULL);
}
h->conf.tableid = tb->conf.id;