diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2007-11-23 09:39:43 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2007-11-23 09:39:43 +0000 |
commit | 8a55c5d3ca663058a2ddc8dc5b0ac47e65d3b5b6 (patch) | |
tree | f95e92f40af0ac6bdddff0df6be66cc24d3c8f83 /usr.sbin/relayd | |
parent | 53d6b9213667eaffb95e49df42f51cc6006463eb (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.y | 53 | ||||
-rw-r--r-- | usr.sbin/relayd/relay.c | 67 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.conf.5 | 23 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.h | 8 |
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; |