--- /dev/null
+/*
+ * netlink/route/cls/ematch/text.h Text Search
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_CLS_EMATCH_TEXT_H_
+#define NETLINK_CLS_EMATCH_TEXT_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/cls/ematch.h>
+#include <linux/tc_ematch/tc_em_text.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void rtnl_ematch_text_set_from(struct rtnl_ematch *,
+ uint8_t, uint16_t);
+extern uint16_t rtnl_ematch_text_get_from_offset(struct rtnl_ematch *);
+extern uint8_t rtnl_ematch_text_get_from_layer(struct rtnl_ematch *);
+extern void rtnl_ematch_text_set_to(struct rtnl_ematch *,
+ uint8_t, uint16_t);
+extern uint16_t rtnl_ematch_text_get_to_offset(struct rtnl_ematch *);
+extern uint8_t rtnl_ematch_text_get_to_layer(struct rtnl_ematch *);
+extern void rtnl_ematch_text_set_pattern(struct rtnl_ematch *,
+ char *, size_t);
+extern char * rtnl_ematch_text_get_pattern(struct rtnl_ematch *);
+extern size_t rtnl_ematch_text_get_len(struct rtnl_ematch *);
+extern void rtnl_ematch_text_set_algo(struct rtnl_ematch *, const char *);
+extern char * rtnl_ematch_text_get_algo(struct rtnl_ematch *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * lib/route/cls/ematch/text.c Text Search
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ */
+
+/**
+ * @ingroup ematch
+ * @defgroup em_text Text Search
+ *
+ * @{
+ */
+
+#include <netlink-local.h>
+#include <netlink-tc.h>
+#include <netlink/netlink.h>
+#include <netlink/route/cls/ematch.h>
+#include <netlink/route/cls/ematch/text.h>
+
+struct text_data
+{
+ struct tcf_em_text cfg;
+ char * pattern;
+};
+
+void rtnl_ematch_text_set_from(struct rtnl_ematch *e, uint8_t layer,
+ uint16_t offset)
+{
+ struct text_data *t = rtnl_ematch_data(e);
+ t->cfg.from_offset = offset;
+ t->cfg.from_layer = layer;
+}
+
+uint16_t rtnl_ematch_text_get_from_offset(struct rtnl_ematch *e)
+{
+ return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_offset;
+}
+
+uint8_t rtnl_ematch_text_get_from_layer(struct rtnl_ematch *e)
+{
+ return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_layer;
+}
+
+void rtnl_ematch_text_set_to(struct rtnl_ematch *e, uint8_t layer,
+ uint16_t offset)
+{
+ struct text_data *t = rtnl_ematch_data(e);
+ t->cfg.to_offset = offset;
+ t->cfg.to_layer = layer;
+}
+
+uint16_t rtnl_ematch_text_get_to_offset(struct rtnl_ematch *e)
+{
+ return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_offset;
+}
+
+uint8_t rtnl_ematch_text_get_to_layer(struct rtnl_ematch *e)
+{
+ return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_layer;
+}
+
+void rtnl_ematch_text_set_pattern(struct rtnl_ematch *e,
+ char *pattern, size_t len)
+{
+ struct text_data *t = rtnl_ematch_data(e);
+
+ if (t->pattern)
+ free(t->pattern);
+
+ t->pattern = pattern;
+ t->cfg.pattern_len = len;
+}
+
+char *rtnl_ematch_text_get_pattern(struct rtnl_ematch *e)
+{
+ return ((struct text_data *) rtnl_ematch_data(e))->pattern;
+}
+
+size_t rtnl_ematch_text_get_len(struct rtnl_ematch *e)
+{
+ return ((struct text_data *) rtnl_ematch_data(e))->cfg.pattern_len;
+}
+
+void rtnl_ematch_text_set_algo(struct rtnl_ematch *e, const char *algo)
+{
+ struct text_data *t = rtnl_ematch_data(e);
+
+ strncpy(t->cfg.algo, algo, sizeof(t->cfg.algo));
+}
+
+char *rtnl_ematch_text_get_algo(struct rtnl_ematch *e)
+{
+ struct text_data *t = rtnl_ematch_data(e);
+
+ return t->cfg.algo[0] ? t->cfg.algo : NULL;
+}
+
+static int text_parse(struct rtnl_ematch *e, void *data, size_t len)
+{
+ struct text_data *t = rtnl_ematch_data(e);
+ size_t hdrlen = sizeof(struct tcf_em_text);
+ size_t plen = len - hdrlen;
+
+ memcpy(&t->cfg, data, hdrlen);
+
+ if (t->cfg.pattern_len > plen)
+ return -NLE_INVAL;
+
+ if (t->cfg.pattern_len > 0) {
+ if (!(t->pattern = calloc(1, t->cfg.pattern_len)))
+ return -NLE_NOMEM;
+
+ memcpy(t->pattern, data + hdrlen, t->cfg.pattern_len);
+ }
+
+ return 0;
+}
+
+static void text_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
+{
+ struct text_data *t = rtnl_ematch_data(e);
+ char buf[64];
+
+ nl_dump(p, "text(%s \"%s\"",
+ t->cfg.algo[0] ? t->cfg.algo : "no-algo",
+ t->pattern ? : "no-pattern");
+
+ if (t->cfg.from_layer || t->cfg.from_offset) {
+ nl_dump(p, " from %s",
+ rtnl_ematch_offset2txt(t->cfg.from_layer,
+ t->cfg.from_offset,
+ buf, sizeof(buf)));
+ }
+
+ if (t->cfg.to_layer || t->cfg.to_offset) {
+ nl_dump(p, " to %s",
+ rtnl_ematch_offset2txt(t->cfg.to_layer,
+ t->cfg.to_offset,
+ buf, sizeof(buf)));
+ }
+
+ nl_dump(p, ")");
+}
+
+static int text_fill(struct rtnl_ematch *e, struct nl_msg *msg)
+{
+ struct text_data *t = rtnl_ematch_data(e);
+ int err;
+
+ if ((err = nlmsg_append(msg, &t->cfg, sizeof(t->cfg), 0)) < 0)
+ return err;
+
+ return nlmsg_append(msg, t->pattern, t->cfg.pattern_len, 0);
+}
+
+static void text_free(struct rtnl_ematch *e)
+{
+ struct text_data *t = rtnl_ematch_data(e);
+ free(t->pattern);
+}
+
+static struct rtnl_ematch_ops text_ops = {
+ .eo_kind = TCF_EM_TEXT,
+ .eo_name = "text",
+ .eo_minlen = sizeof(struct tcf_em_text),
+ .eo_datalen = sizeof(struct text_data),
+ .eo_parse = text_parse,
+ .eo_dump = text_dump,
+ .eo_fill = text_fill,
+ .eo_free = text_free,
+};
+
+static void __init text_init(void)
+{
+ rtnl_ematch_register(&text_ops);
+}
+
+/** @} */
#include <netlink/route/cls/ematch.h>
#include <netlink/route/cls/ematch/cmp.h>
#include <netlink/route/cls/ematch/nbyte.h>
+#include <netlink/route/cls/ematch/text.h>
%}
%error-verbose
%token <i> KW_AT "at"
%token <i> EMATCH_CMP "cmp"
%token <i> EMATCH_NBYTE "pattern"
+%token <i> EMATCH_TEXT "text"
%token <i> KW_EQ "="
%token <i> KW_GT ">"
%token <i> KW_LT "<"
+%token <i> KW_FROM "from"
+%token <i> KW_TO "to"
%token <s> STR
%type <i> mask align operand
%type <e> expr match ematch
%type <cmp> cmp_expr cmp_match
-%type <loc> pktloc
+%type <loc> pktloc text_from text_to
%type <q> pattern
%destructor { free($$); NL_DBG(2, "string destructor\n"); } <s>
BUG();
rtnl_ematch_nbyte_set_offset(e, $3->layer, $3->offset);
+ rtnl_pktloc_put($3);
rtnl_ematch_nbyte_set_pattern(e, (uint8_t *) $5.data, $5.index);
+ $$ = e;
+ }
+ | EMATCH_TEXT "(" STR QUOTED text_from text_to ")"
+ {
+ struct rtnl_ematch *e;
+
+ if (!(e = rtnl_ematch_alloc())) {
+ asprintf(errp, "Unable to allocate ematch object");
+ YYABORT;
+ }
+
+ if (rtnl_ematch_set_kind(e, TCF_EM_TEXT) < 0)
+ BUG();
+
+ rtnl_ematch_text_set_algo(e, $3);
+ rtnl_ematch_text_set_pattern(e, $4.data, $4.index);
+
+ if ($5) {
+ rtnl_ematch_text_set_from(e, $5->layer, $5->offset);
+ rtnl_pktloc_put($5);
+ }
+
+ if ($6) {
+ rtnl_ematch_text_set_to(e, $6->layer, $6->offset);
+ rtnl_pktloc_put($6);
+ }
+
$$ = e;
}
/* CONTAINER */
$$.layer = $1->layer;
$$.opnd = $2;
$$.val = $3;
+
+ rtnl_pktloc_put($1);
}
;
+text_from:
+ /* empty */
+ { $$ = NULL; }
+ | "from" pktloc
+ { $$ = $2; }
+ ;
+
+text_to:
+ /* empty */
+ { $$ = NULL; }
+ | "to" pktloc
+ { $$ = $2; }
+ ;
+
/*
* pattern
*/
$$ = loc;
}
- | align "at" LAYER "+" NUMBER mask
+ /* [u8|u16|u32|NUM at] LAYER + OFFSET [mask MASK] */
+ | align LAYER "+" NUMBER mask
{
struct rtnl_pktloc *loc;
+ if ($5 && (!$1 || $1 > TCF_EM_ALIGN_U32)) {
+ asprintf(errp, "mask only allowed for alignments u8|u16|u32");
+ YYABORT;
+ }
+
if (!(loc = rtnl_pktloc_alloc())) {
asprintf(errp, "Unable to allocate packet location object");
YYABORT;
loc->name = strdup("<USER-DEFINED>");
loc->align = $1;
- loc->layer = $3;
- loc->offset = $5;
- loc->mask = $6;
+ loc->layer = $2;
+ loc->offset = $4;
+ loc->mask = $5;
$$ = loc;
}
;
align:
- ALIGN
+ /* empty */
+ { $$ = 0; }
+ | ALIGN "at"
{ $$ = $1; }
- | NUMBER
+ | NUMBER "at"
{ $$ = $1; }
;