summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2007-11-23 09:39:43 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2007-11-23 09:39:43 +0000
commit8a55c5d3ca663058a2ddc8dc5b0ac47e65d3b5b6 (patch)
treef95e92f40af0ac6bdddff0df6be66cc24d3c8f83 /usr.sbin/relayd
parent53d6b9213667eaffb95e49df42f51cc6006463eb (diff)
re-implement the "mark" action and document it in the manpage:
it is possible to attach a mark to a session based on matching an entity (header, url, cookie, ...) and add conditional action for this mark. it works a bit like the tag/tagged keywords in pf, but i decided to pick a different name to avoid confusion. ok pyr@ gilles@
Diffstat (limited to 'usr.sbin/relayd')
-rw-r--r--usr.sbin/relayd/parse.y53
-rw-r--r--usr.sbin/relayd/relay.c67
-rw-r--r--usr.sbin/relayd/relayd.conf.523
-rw-r--r--usr.sbin/relayd/relayd.h8
4 files changed, 108 insertions, 43 deletions
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y
index 86ebc48c691..55aeef325d2 100644
--- a/usr.sbin/relayd/parse.y
+++ b/usr.sbin/relayd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.93 2007/11/22 10:09:53 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.94 2007/11/23 09:39:42 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -121,7 +121,7 @@ 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
-%token VIRTUAL INTERVAL DISABLE STICKYADDR BACKLOG PATH SCRIPT
+%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
@@ -130,7 +130,7 @@ typedef struct {
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.string> interface hostname
-%type <v.number> port http_type loglevel sslcache optssl dstport
+%type <v.number> port http_type loglevel sslcache optssl dstport mark
%type <v.number> proto_type dstmode docheck retry log flag direction
%type <v.host> host
%type <v.tv> timeout
@@ -897,7 +897,7 @@ protonode : nodetype APPEND STRING TO STRING marked {
fatal("out of memory");
free($3);
}
- | nodetype EXPECT STRING FROM STRING mark {
+ | nodetype EXPECT STRING FROM STRING marked {
node.action = NODE_ACTION_EXPECT;
node.key = strdup($5);
node.value = strdup($3);
@@ -907,7 +907,7 @@ protonode : nodetype APPEND STRING TO STRING marked {
free($3);
proto->lateconnect++;
}
- | nodetype EXPECT STRING mark {
+ | nodetype EXPECT STRING marked {
node.action = NODE_ACTION_EXPECT;
node.key = strdup($3);
node.value = strdup("*");
@@ -916,7 +916,7 @@ protonode : nodetype APPEND STRING TO STRING marked {
free($3);
proto->lateconnect++;
}
- | nodetype EXPECT digest mark {
+ | nodetype EXPECT digest marked {
if (node.type != NODE_TYPE_URL) {
yyerror("digest not supported for this type");
free($3.digest);
@@ -931,7 +931,7 @@ protonode : nodetype APPEND STRING TO STRING marked {
free($3.digest);
proto->lateconnect++;
}
- | nodetype FILTER STRING FROM STRING mark {
+ | nodetype FILTER STRING FROM STRING marked {
node.action = NODE_ACTION_FILTER;
node.key = strdup($5);
node.value = strdup($3);
@@ -941,7 +941,7 @@ protonode : nodetype APPEND STRING TO STRING marked {
free($3);
proto->lateconnect++;
}
- | nodetype FILTER STRING mark {
+ | nodetype FILTER STRING marked {
node.action = NODE_ACTION_FILTER;
node.key = strdup($3);
node.value = strdup("*");
@@ -950,7 +950,7 @@ protonode : nodetype APPEND STRING TO STRING marked {
free($3);
proto->lateconnect++;
}
- | nodetype FILTER digest mark {
+ | nodetype FILTER digest marked {
if (node.type != NODE_TYPE_URL) {
yyerror("digest not supported for this type");
free($3.digest);
@@ -983,14 +983,38 @@ protonode : nodetype APPEND STRING TO STRING marked {
fatal("out of memory");
free($3);
}
+ | nodetype MARK STRING FROM STRING WITH mark {
+ node.action = NODE_ACTION_MARK;
+ node.key = strdup($5);
+ node.value = strdup($3);
+ node.mark = $7;
+ if (node.key == NULL || node.value == NULL)
+ fatal("out of memory");
+ free($3);
+ free($5);
+ }
+ | nodetype MARK STRING WITH mark {
+ node.action = NODE_ACTION_MARK;
+ node.key = strdup($3);
+ node.value = strdup("*");
+ node.mark = $5;
+ if (node.key == NULL || node.value == NULL)
+ fatal("out of memory");
+ free($3);
+ }
;
-mark : /* empty */
- | MARK { node.flags |= PNFLAG_MARK; }
+marked : /* empty */
+ | MARKED mark { node.mark = $2; }
;
-marked : /* empty */
- | MARKED { node.flags |= PNFLAG_MARK; }
+mark : NUMBER {
+ if ($1 <= 0 || $1 >= (int)USHRT_MAX) {
+ yyerror("invalid mark: %d", $1);
+ YYERROR;
+ }
+ $$ = $1;
+ }
;
nodetype : HEADER {
@@ -1392,7 +1416,8 @@ lookup(char *s)
{ "to", TO },
{ "updates", UPDATES },
{ "url", URL },
- { "virtual", VIRTUAL }
+ { "virtual", VIRTUAL },
+ { "with", WITH }
};
const struct keywords *p;
diff --git a/usr.sbin/relayd/relay.c b/usr.sbin/relayd/relay.c
index dd3776b7f26..75e2820038e 100644
--- a/usr.sbin/relayd/relay.c
+++ b/usr.sbin/relayd/relay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay.c,v 1.66 2007/11/22 16:07:03 reyk Exp $ */
+/* $OpenBSD: relay.c,v 1.67 2007/11/23 09:39:42 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org>
@@ -341,6 +341,13 @@ relay_nodedebug(const char *name, struct protonode *pn)
case NODE_ACTION_LOG:
fprintf(stderr, "log \"%s\"", pn->key);
break;
+ case NODE_ACTION_MARK:
+ if (strcmp(pn->value, "*") == 0)
+ fprintf(stderr, "mark \"%s\"", pn->key);
+ else
+ fprintf(stderr, "mark \"%s\" from \"%s\"",
+ pn->value, pn->key);
+ break;
case NODE_ACTION_NONE:
break;
}
@@ -872,6 +879,9 @@ relay_resolve(struct ctl_relay_event *cre,
char buf[READ_BUF_SIZE], *ptr;
int id;
+ if (pn->mark && (pn->mark != con->mark))
+ return (0);
+
switch (pn->action) {
case NODE_ACTION_FILTER:
id = cre->nodes[proot->id];
@@ -898,9 +908,6 @@ relay_resolve(struct ctl_relay_event *cre,
case NODE_ACTION_APPEND:
case NODE_ACTION_CHANGE:
ptr = pn->value;
- if ((pn->flags & PNFLAG_MARK) &&
- cre->marked == 0)
- break;
if ((pn->flags & PNFLAG_MACRO) &&
(ptr = relay_expand_http(cre, pn->value,
buf, sizeof(buf))) == NULL)
@@ -916,15 +923,11 @@ relay_resolve(struct ctl_relay_event *cre,
pn->key, ptr);
break;
case NODE_ACTION_EXPECT:
- if (pn->flags & PNFLAG_MARK)
- break;
DPRINTF("relay_resolve: missing '%s: %s'",
pn->key, pn->value);
relay_close_http(con, 403, "incomplete request");
return (-1);
case NODE_ACTION_FILTER:
- if (pn->flags & PNFLAG_MARK)
- break;
DPRINTF("relay_resolve: filtered '%s: %s'",
pn->key, pn->value);
relay_close_http(con, 403, "rejecting request");
@@ -991,11 +994,27 @@ relay_handle_http(struct ctl_relay_event *cre, struct protonode *proot,
{
struct session *con = (struct session *)cre->con;
char buf[READ_BUF_SIZE], *ptr;
- int ret = PN_DROP;
+ int ret = PN_DROP, mark = 0;
+ struct protonode *next;
+
+ /* Check if this action depends on a marked session */
+ if (pn->mark != 0)
+ mark = pn->mark == con->mark ? 1 : -1;
+
+ switch (pn->action) {
+ case NODE_ACTION_EXPECT:
+ case NODE_ACTION_FILTER:
+ case NODE_ACTION_MARK:
+ break;
+ default:
+ if (mark == -1)
+ return (PN_PASS);
+ break;
+ }
switch (pn->action) {
case NODE_ACTION_APPEND:
- if (!header || ((pn->flags & PNFLAG_MARK) && cre->marked == 0))
+ if (!header)
return (PN_PASS);
ptr = pn->value;
if ((pn->flags & PNFLAG_MACRO) &&
@@ -1015,7 +1034,7 @@ relay_handle_http(struct ctl_relay_event *cre, struct protonode *proot,
break;
case NODE_ACTION_CHANGE:
case NODE_ACTION_REMOVE:
- if (!header || ((pn->flags & PNFLAG_MARK) && cre->marked == 0))
+ if (!header)
return (PN_PASS);
DPRINTF("relay_handle_http: change/remove '%s: %s'",
pk->key, pk->value);
@@ -1038,9 +1057,8 @@ relay_handle_http(struct ctl_relay_event *cre, struct protonode *proot,
/* Do not drop the entity */
ret = PN_PASS;
- if (fnmatch(pn->value, pk->value, FNM_CASEFOLD) == 0) {
- if (pn->flags & PNFLAG_MARK)
- cre->marked++;
+ if (mark != -1 &&
+ fnmatch(pn->value, pk->value, FNM_CASEFOLD) == 0) {
cre->nodes[proot->id] = 1;
/* Fail instantly */
@@ -1049,28 +1067,32 @@ relay_handle_http(struct ctl_relay_event *cre, struct protonode *proot,
return (PN_FAIL);
}
}
- if (SIMPLEQ_NEXT(pn, entry) == NULL)
+ next = SIMPLEQ_NEXT(pn, entry);
+ if (next == NULL || next->action != pn->action)
cre->nodes[proot->id]++;
break;
case NODE_ACTION_HASH:
- if ((pn->flags & PNFLAG_MARK) && cre->marked == 0)
- return (PN_PASS);
DPRINTF("relay_handle_http: hash '%s: %s'",
pn->key, pk->value);
con->outkey = hash32_str(pk->value, con->outkey);
ret = PN_PASS;
break;
case NODE_ACTION_LOG:
- if ((pn->flags & PNFLAG_MARK) && cre->marked == 0)
- return (PN_PASS);
DPRINTF("relay_handle_http: log '%s: %s'",
pn->key, pk->value);
ret = PN_PASS;
break;
+ case NODE_ACTION_MARK:
+ DPRINTF("relay_handle_http: mark '%s: %s'",
+ pn->key, pk->value);
+ if (fnmatch(pn->value, pk->value, FNM_CASEFOLD) == 0)
+ con->mark = pn->mark;
+ ret = PN_PASS;
+ break;
case NODE_ACTION_NONE:
return (PN_PASS);
}
- if (pn->flags & PNFLAG_LOG) {
+ if (mark != -1 && pn->flags & PNFLAG_LOG) {
bzero(buf, sizeof(buf));
if (snprintf(buf, sizeof(buf), " [%s: %s]",
pk->key, pk->value) == -1 ||
@@ -1474,7 +1496,6 @@ relay_read_http(struct bufferevent *bev, void *arg)
goto fail;
cre->line = 0;
cre->method = 0;
- cre->marked = 0;
cre->done = 0;
cre->chunked = 0;
@@ -2069,9 +2090,9 @@ relay_close(struct session *con, const char *msg)
if (EVBUFFER_LENGTH(con->log) &&
evbuffer_add_printf(con->log, "\r\n") != -1)
ptr = evbuffer_readline(con->log);
- log_info("relay %s, session %d (%d active), %s -> %s:%d, "
+ log_info("relay %s, session %d (%d active), %d, %s -> %s:%d, "
"%s%s%s", rlay->conf.name, con->id, relay_sessions,
- ibuf, obuf, ntohs(con->out.port), msg,
+ con->mark, ibuf, obuf, ntohs(con->out.port), msg,
ptr == NULL ? "" : ",", ptr == NULL ? "" : ptr);
if (ptr != NULL)
free(ptr);
diff --git a/usr.sbin/relayd/relayd.conf.5 b/usr.sbin/relayd/relayd.conf.5
index 23cf9c0f026..987d97916aa 100644
--- a/usr.sbin/relayd/relayd.conf.5
+++ b/usr.sbin/relayd/relayd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: relayd.conf.5,v 1.63 2007/11/22 10:09:53 reyk Exp $
+.\" $OpenBSD: relayd.conf.5,v 1.64 2007/11/23 09:39:42 reyk Exp $
.\"
.\" Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org>
.\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: November 22 2007 $
+.Dd $Mdocdate: November 23 2007 $
.Dt HOSTSTATED.CONF 5
.Os
.Sh NAME
@@ -508,12 +508,17 @@ predictable values generated by some hosts.
.Op Ar direction
.Op Ar type
.Ar action
+.Op Ic marked Ar id
.Op Ic log
.Xc
Define an action for the selected entity.
The optional
.Ic log
-keyword will log the entity name and the value.
+keyword will log the entity name and the value and
+the optional
+.Ic marked
+keyword requires that the session has been marked with a given
+identifier in order to execute the action.
The actions are depending on the underlying application
.Ic protocol .
.Pp
@@ -665,6 +670,18 @@ keyword in the
section above.
.It Ic log Ar key
Log the name and the value of the entity.
+.It Xo
+.Ic mark
+.Op Ar value Ic from
+.Ar key Ic with Ar id
+.Xc
+Mark the session with the specified identifier (a positive number
+between 1 and 65535) if the specified condition matches.
+Note that the
+.Ic mark
+action does not accept the
+.Ic marked
+option (see above).
.El
.It Ic return error Op Ar option
Return an error reponse to the client if an internal operation or the
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index 4477687c19e..faba45d4399 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.83 2007/11/22 16:38:25 reyk Exp $ */
+/* $OpenBSD: relayd.h,v 1.84 2007/11/23 09:39:42 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -241,7 +241,6 @@ struct ctl_relay_event {
char *args;
char *version;
- int marked;
int line;
size_t toread;
int chunked;
@@ -415,6 +414,7 @@ struct session {
struct timeval tv_last;
int done;
int retry;
+ u_int16_t mark;
struct evbuffer *log;
void *relay;
struct ctl_natlook *cnl;
@@ -431,7 +431,8 @@ enum nodeaction {
NODE_ACTION_EXPECT = 4,
NODE_ACTION_FILTER = 5,
NODE_ACTION_HASH = 6,
- NODE_ACTION_LOG = 7
+ NODE_ACTION_LOG = 7,
+ NODE_ACTION_MARK = 8
};
enum nodetype {
@@ -464,6 +465,7 @@ struct protonode {
char *value;
u_int8_t flags;
enum nodetype type;
+ u_int16_t mark;
SIMPLEQ_HEAD(, protonode) head;
SIMPLEQ_ENTRY(protonode) entry;