text.c

00001 /*
00002  * lib/route/cls/ematch/text.c          Text Search
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup ematch
00014  * @defgroup em_text Text Search
00015  *
00016  * @{
00017  */
00018 
00019 #include <netlink-local.h>
00020 #include <netlink-tc.h>
00021 #include <netlink/netlink.h>
00022 #include <netlink/route/cls/ematch.h>
00023 #include <netlink/route/cls/ematch/text.h>
00024 
00025 struct text_data
00026 {
00027         struct tcf_em_text      cfg;
00028         char *                  pattern;
00029 };
00030 
00031 void rtnl_ematch_text_set_from(struct rtnl_ematch *e, uint8_t layer,
00032                                uint16_t offset)
00033 {
00034         struct text_data *t = rtnl_ematch_data(e);
00035         t->cfg.from_offset = offset;
00036         t->cfg.from_layer = layer;
00037 }
00038 
00039 uint16_t rtnl_ematch_text_get_from_offset(struct rtnl_ematch *e)
00040 {
00041         return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_offset;
00042 }
00043 
00044 uint8_t rtnl_ematch_text_get_from_layer(struct rtnl_ematch *e)
00045 {
00046         return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_layer;
00047 }
00048 
00049 void rtnl_ematch_text_set_to(struct rtnl_ematch *e, uint8_t layer,
00050                                uint16_t offset)
00051 {
00052         struct text_data *t = rtnl_ematch_data(e);
00053         t->cfg.to_offset = offset;
00054         t->cfg.to_layer = layer;
00055 }
00056 
00057 uint16_t rtnl_ematch_text_get_to_offset(struct rtnl_ematch *e)
00058 {
00059         return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_offset;
00060 }
00061 
00062 uint8_t rtnl_ematch_text_get_to_layer(struct rtnl_ematch *e)
00063 {
00064         return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_layer;
00065 }
00066 
00067 void rtnl_ematch_text_set_pattern(struct rtnl_ematch *e,
00068                                   char *pattern, size_t len)
00069 {
00070         struct text_data *t = rtnl_ematch_data(e);
00071 
00072         if (t->pattern)
00073                 free(t->pattern);
00074 
00075         t->pattern = pattern;
00076         t->cfg.pattern_len = len;
00077 }
00078 
00079 char *rtnl_ematch_text_get_pattern(struct rtnl_ematch *e)
00080 {
00081         return ((struct text_data *) rtnl_ematch_data(e))->pattern;
00082 }
00083 
00084 size_t rtnl_ematch_text_get_len(struct rtnl_ematch *e)
00085 {
00086         return ((struct text_data *) rtnl_ematch_data(e))->cfg.pattern_len;
00087 }
00088 
00089 void rtnl_ematch_text_set_algo(struct rtnl_ematch *e, const char *algo)
00090 {
00091         struct text_data *t = rtnl_ematch_data(e);
00092 
00093         strncpy(t->cfg.algo, algo, sizeof(t->cfg.algo));
00094 }
00095 
00096 char *rtnl_ematch_text_get_algo(struct rtnl_ematch *e)
00097 {
00098         struct text_data *t = rtnl_ematch_data(e);
00099 
00100         return t->cfg.algo[0] ? t->cfg.algo : NULL;
00101 }
00102 
00103 static int text_parse(struct rtnl_ematch *e, void *data, size_t len)
00104 {
00105         struct text_data *t = rtnl_ematch_data(e);
00106         size_t hdrlen = sizeof(struct tcf_em_text);
00107         size_t plen = len - hdrlen;
00108 
00109         memcpy(&t->cfg, data, hdrlen);
00110 
00111         if (t->cfg.pattern_len > plen)
00112                 return -NLE_INVAL;
00113 
00114         if (t->cfg.pattern_len > 0) {
00115                 if (!(t->pattern = calloc(1, t->cfg.pattern_len)))
00116                         return -NLE_NOMEM;
00117 
00118                 memcpy(t->pattern, data + hdrlen, t->cfg.pattern_len);
00119         }
00120 
00121         return 0;
00122 }
00123 
00124 static void text_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
00125 {
00126         struct text_data *t = rtnl_ematch_data(e);
00127         char buf[64];
00128 
00129         nl_dump(p, "text(%s \"%s\"",
00130                 t->cfg.algo[0] ? t->cfg.algo : "no-algo",
00131                 t->pattern ? : "no-pattern");
00132 
00133         if (t->cfg.from_layer || t->cfg.from_offset) {
00134                 nl_dump(p, " from %s",
00135                         rtnl_ematch_offset2txt(t->cfg.from_layer,
00136                                                t->cfg.from_offset,
00137                                                buf, sizeof(buf)));
00138         }
00139 
00140         if (t->cfg.to_layer || t->cfg.to_offset) {
00141                 nl_dump(p, " to %s",
00142                         rtnl_ematch_offset2txt(t->cfg.to_layer,
00143                                                t->cfg.to_offset,
00144                                                buf, sizeof(buf)));
00145         }
00146 
00147         nl_dump(p, ")");
00148 }
00149 
00150 static int text_fill(struct rtnl_ematch *e, struct nl_msg *msg)
00151 {
00152         struct text_data *t = rtnl_ematch_data(e);
00153         int err;
00154 
00155         if ((err = nlmsg_append(msg, &t->cfg, sizeof(t->cfg), 0)) < 0)
00156                 return err;
00157 
00158         return nlmsg_append(msg, t->pattern, t->cfg.pattern_len, 0);
00159 }
00160 
00161 static void text_free(struct rtnl_ematch *e)
00162 {
00163         struct text_data *t = rtnl_ematch_data(e);
00164         free(t->pattern);
00165 }
00166 
00167 static struct rtnl_ematch_ops text_ops = {
00168         .eo_kind        = TCF_EM_TEXT,
00169         .eo_name        = "text",
00170         .eo_minlen      = sizeof(struct tcf_em_text),
00171         .eo_datalen     = sizeof(struct text_data),
00172         .eo_parse       = text_parse,
00173         .eo_dump        = text_dump,
00174         .eo_fill        = text_fill,
00175         .eo_free        = text_free,
00176 };
00177 
00178 static void __init text_init(void)
00179 {
00180         rtnl_ematch_register(&text_ops);
00181 }
00182 
00183 /** @} */