text ematch support
This commit is contained in:
parent
93f992eac5
commit
c7a673787b
7 changed files with 310 additions and 8 deletions
|
@ -84,6 +84,9 @@ extern void rtnl_ematch_tree_dump(struct rtnl_ematch_tree *,
|
|||
extern int rtnl_ematch_parse_expr(const char *, char **,
|
||||
struct rtnl_ematch_tree **);
|
||||
|
||||
extern char * rtnl_ematch_offset2txt(uint8_t, uint16_t,
|
||||
char *, size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
42
include/netlink/route/cls/ematch/text.h
Normal file
42
include/netlink/route/cls/ematch/text.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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
|
|
@ -55,7 +55,7 @@ libnl_route_la_SOURCES = \
|
|||
route/cls/ematch_syntax.c route/cls/ematch_grammar.c \
|
||||
route/cls/ematch.c \
|
||||
route/cls/ematch/container.c route/cls/ematch/cmp.c \
|
||||
route/cls/ematch/nbyte.c \
|
||||
route/cls/ematch/nbyte.c route/cls/ematch/text.c \
|
||||
\
|
||||
route/link/api.c route/link/vlan.c \
|
||||
\
|
||||
|
|
|
@ -667,4 +667,19 @@ errout:
|
|||
return err;
|
||||
}
|
||||
|
||||
static const char *layer_txt[] = {
|
||||
[TCF_LAYER_LINK] = "eth",
|
||||
[TCF_LAYER_NETWORK] = "ip",
|
||||
[TCF_LAYER_TRANSPORT] = "tcp",
|
||||
};
|
||||
|
||||
char *rtnl_ematch_offset2txt(uint8_t layer, uint16_t offset, char *buf, size_t len)
|
||||
{
|
||||
snprintf(buf, len, "%s+%u",
|
||||
(layer <= TCF_LAYER_MAX) ? layer_txt[layer] : "?",
|
||||
offset);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
183
lib/route/cls/ematch/text.c
Normal file
183
lib/route/cls/ematch/text.c
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -77,12 +77,15 @@ lt |
|
|||
|
||||
[cC][mM][pP] { yylval->i = TCF_EM_CMP; return EMATCH_CMP; }
|
||||
[pP][aA][tT][tT][eE][rR][nN] { yylval->i = TCF_EM_NBYTE; return EMATCH_NBYTE; }
|
||||
[tT][eE][xX][tT] { yylval->i = TCF_EM_TEXT; return EMATCH_TEXT; }
|
||||
|
||||
"(" return KW_OPEN;
|
||||
")" return KW_CLOSE;
|
||||
[mM][aA][sS][kK] return KW_MASK;
|
||||
[aA][tT] return KW_AT;
|
||||
"+" return KW_PLUS;
|
||||
[fF][rR][oO][mM] return KW_FROM;
|
||||
[tT][oO] return KW_TO;
|
||||
|
||||
[uU]8 { yylval->i = TCF_EM_ALIGN_U8; return ALIGN; }
|
||||
[uU]16 { yylval->i = TCF_EM_ALIGN_U16; return ALIGN; }
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#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
|
||||
|
@ -56,9 +57,12 @@ static void yyerror(void *scanner, char **errp, struct nl_list_head *root, const
|
|||
%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
|
||||
|
||||
|
@ -67,7 +71,7 @@ static void yyerror(void *scanner, char **errp, struct nl_list_head *root, const
|
|||
%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>
|
||||
|
@ -144,8 +148,36 @@ ematch:
|
|||
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 */
|
||||
|
@ -198,9 +230,25 @@ cmp_expr:
|
|||
$$.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
|
||||
*/
|
||||
|
@ -248,10 +296,16 @@ pktloc:
|
|||
|
||||
$$ = 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;
|
||||
|
@ -259,18 +313,20 @@ pktloc:
|
|||
|
||||
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; }
|
||||
;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue