Home | History | Annotate | Download | only in ematch
      1 /*
      2  * lib/route/cls/ematch/text.c		Text Search
      3  *
      4  *	This library is free software; you can redistribute it and/or
      5  *	modify it under the terms of the GNU Lesser General Public
      6  *	License as published by the Free Software Foundation version 2.1
      7  *	of the License.
      8  *
      9  * Copyright (c) 2010-2013 Thomas Graf <tgraf (at) suug.ch>
     10  */
     11 
     12 /**
     13  * @ingroup ematch
     14  * @defgroup em_text Text Search
     15  *
     16  * @{
     17  */
     18 
     19 #include <netlink-private/netlink.h>
     20 #include <netlink-private/tc.h>
     21 #include <netlink/netlink.h>
     22 #include <netlink/route/cls/ematch.h>
     23 #include <netlink/route/cls/ematch/text.h>
     24 
     25 struct text_data
     26 {
     27 	struct tcf_em_text	cfg;
     28 	char *			pattern;
     29 };
     30 
     31 void rtnl_ematch_text_set_from(struct rtnl_ematch *e, uint8_t layer,
     32 			       uint16_t offset)
     33 {
     34 	struct text_data *t = rtnl_ematch_data(e);
     35 	t->cfg.from_offset = offset;
     36 	t->cfg.from_layer = layer;
     37 }
     38 
     39 uint16_t rtnl_ematch_text_get_from_offset(struct rtnl_ematch *e)
     40 {
     41 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_offset;
     42 }
     43 
     44 uint8_t rtnl_ematch_text_get_from_layer(struct rtnl_ematch *e)
     45 {
     46 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_layer;
     47 }
     48 
     49 void rtnl_ematch_text_set_to(struct rtnl_ematch *e, uint8_t layer,
     50 			       uint16_t offset)
     51 {
     52 	struct text_data *t = rtnl_ematch_data(e);
     53 	t->cfg.to_offset = offset;
     54 	t->cfg.to_layer = layer;
     55 }
     56 
     57 uint16_t rtnl_ematch_text_get_to_offset(struct rtnl_ematch *e)
     58 {
     59 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_offset;
     60 }
     61 
     62 uint8_t rtnl_ematch_text_get_to_layer(struct rtnl_ematch *e)
     63 {
     64 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_layer;
     65 }
     66 
     67 void rtnl_ematch_text_set_pattern(struct rtnl_ematch *e,
     68 				  char *pattern, size_t len)
     69 {
     70 	struct text_data *t = rtnl_ematch_data(e);
     71 
     72 	if (t->pattern)
     73 		free(t->pattern);
     74 
     75 	t->pattern = pattern;
     76 	t->cfg.pattern_len = len;
     77 }
     78 
     79 char *rtnl_ematch_text_get_pattern(struct rtnl_ematch *e)
     80 {
     81 	return ((struct text_data *) rtnl_ematch_data(e))->pattern;
     82 }
     83 
     84 size_t rtnl_ematch_text_get_len(struct rtnl_ematch *e)
     85 {
     86 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.pattern_len;
     87 }
     88 
     89 void rtnl_ematch_text_set_algo(struct rtnl_ematch *e, const char *algo)
     90 {
     91 	struct text_data *t = rtnl_ematch_data(e);
     92 
     93 	strncpy(t->cfg.algo, algo, sizeof(t->cfg.algo));
     94 }
     95 
     96 char *rtnl_ematch_text_get_algo(struct rtnl_ematch *e)
     97 {
     98 	struct text_data *t = rtnl_ematch_data(e);
     99 
    100 	return t->cfg.algo[0] ? t->cfg.algo : NULL;
    101 }
    102 
    103 static int text_parse(struct rtnl_ematch *e, void *data, size_t len)
    104 {
    105 	struct text_data *t = rtnl_ematch_data(e);
    106 	size_t hdrlen = sizeof(struct tcf_em_text);
    107 	size_t plen = len - hdrlen;
    108 
    109 	memcpy(&t->cfg, data, hdrlen);
    110 
    111 	if (t->cfg.pattern_len > plen)
    112 		return -NLE_INVAL;
    113 
    114 	if (t->cfg.pattern_len > 0) {
    115 		if (!(t->pattern = calloc(1, t->cfg.pattern_len)))
    116 			return -NLE_NOMEM;
    117 
    118 		memcpy(t->pattern, data + hdrlen, t->cfg.pattern_len);
    119 	}
    120 
    121 	return 0;
    122 }
    123 
    124 static void text_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
    125 {
    126 	struct text_data *t = rtnl_ematch_data(e);
    127 	char buf[64];
    128 
    129 	nl_dump(p, "text(%s \"%s\"",
    130 		t->cfg.algo[0] ? t->cfg.algo : "no-algo",
    131 		t->pattern ? : "no-pattern");
    132 
    133 	if (t->cfg.from_layer || t->cfg.from_offset) {
    134 		nl_dump(p, " from %s",
    135 			rtnl_ematch_offset2txt(t->cfg.from_layer,
    136 					       t->cfg.from_offset,
    137 					       buf, sizeof(buf)));
    138 	}
    139 
    140 	if (t->cfg.to_layer || t->cfg.to_offset) {
    141 		nl_dump(p, " to %s",
    142 			rtnl_ematch_offset2txt(t->cfg.to_layer,
    143 					       t->cfg.to_offset,
    144 					       buf, sizeof(buf)));
    145 	}
    146 
    147 	nl_dump(p, ")");
    148 }
    149 
    150 static int text_fill(struct rtnl_ematch *e, struct nl_msg *msg)
    151 {
    152 	struct text_data *t = rtnl_ematch_data(e);
    153 	int err;
    154 
    155 	if ((err = nlmsg_append(msg, &t->cfg, sizeof(t->cfg), 0)) < 0)
    156 		return err;
    157 
    158 	return nlmsg_append(msg, t->pattern, t->cfg.pattern_len, 0);
    159 }
    160 
    161 static void text_free(struct rtnl_ematch *e)
    162 {
    163 	struct text_data *t = rtnl_ematch_data(e);
    164 	free(t->pattern);
    165 }
    166 
    167 static struct rtnl_ematch_ops text_ops = {
    168 	.eo_kind	= TCF_EM_TEXT,
    169 	.eo_name	= "text",
    170 	.eo_minlen	= sizeof(struct tcf_em_text),
    171 	.eo_datalen	= sizeof(struct text_data),
    172 	.eo_parse	= text_parse,
    173 	.eo_dump	= text_dump,
    174 	.eo_fill	= text_fill,
    175 	.eo_free	= text_free,
    176 };
    177 
    178 static void __init text_init(void)
    179 {
    180 	rtnl_ematch_register(&text_ops);
    181 }
    182 
    183 /** @} */
    184