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