1 /*
2 * lib/route/cls/ematch/nbyte.c Nbyte comparison
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@suug.ch>
10 */
11
12 /**
13 * @ingroup ematch
14 * @defgroup em_nbyte N-Byte Comparison
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/nbyte.h>
24
25 struct nbyte_data
26 {
27 struct tcf_em_nbyte cfg;
28 uint8_t * pattern;
29 };
30
rtnl_ematch_nbyte_set_offset(struct rtnl_ematch * e,uint8_t layer,uint16_t offset)31 void rtnl_ematch_nbyte_set_offset(struct rtnl_ematch *e, uint8_t layer,
32 uint16_t offset)
33 {
34 struct nbyte_data *n = rtnl_ematch_data(e);
35 n->cfg.off = offset;
36 n->cfg.layer = layer;
37 }
38
rtnl_ematch_nbyte_get_offset(struct rtnl_ematch * e)39 uint16_t rtnl_ematch_nbyte_get_offset(struct rtnl_ematch *e)
40 {
41 return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.off;
42 }
43
rtnl_ematch_nbyte_get_layer(struct rtnl_ematch * e)44 uint8_t rtnl_ematch_nbyte_get_layer(struct rtnl_ematch *e)
45 {
46 return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.layer;
47 }
48
rtnl_ematch_nbyte_set_pattern(struct rtnl_ematch * e,uint8_t * pattern,size_t len)49 void rtnl_ematch_nbyte_set_pattern(struct rtnl_ematch *e,
50 uint8_t *pattern, size_t len)
51 {
52 struct nbyte_data *n = rtnl_ematch_data(e);
53
54 if (n->pattern)
55 free(n->pattern);
56
57 n->pattern = pattern;
58 n->cfg.len = len;
59 }
60
rtnl_ematch_nbyte_get_pattern(struct rtnl_ematch * e)61 uint8_t *rtnl_ematch_nbyte_get_pattern(struct rtnl_ematch *e)
62 {
63 return ((struct nbyte_data *) rtnl_ematch_data(e))->pattern;
64 }
65
rtnl_ematch_nbyte_get_len(struct rtnl_ematch * e)66 size_t rtnl_ematch_nbyte_get_len(struct rtnl_ematch *e)
67 {
68 return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.len;
69 }
70
layer_txt(struct tcf_em_nbyte * nbyte)71 static const char *layer_txt(struct tcf_em_nbyte *nbyte)
72 {
73 switch (nbyte->layer) {
74 case TCF_LAYER_LINK:
75 return "link";
76 case TCF_LAYER_NETWORK:
77 return "net";
78 case TCF_LAYER_TRANSPORT:
79 return "trans";
80 default:
81 return "?";
82 }
83 }
84
nbyte_parse(struct rtnl_ematch * e,void * data,size_t len)85 static int nbyte_parse(struct rtnl_ematch *e, void *data, size_t len)
86 {
87 struct nbyte_data *n = rtnl_ematch_data(e);
88 size_t hdrlen = sizeof(struct tcf_em_nbyte);
89 size_t plen = len - hdrlen;
90
91 memcpy(&n->cfg, data, hdrlen);
92 if (plen > 0) {
93 if (!(n->pattern = calloc(1, plen)))
94 return -NLE_NOMEM;
95
96 memcpy(n->pattern, data + hdrlen, plen);
97 }
98
99 return 0;
100 }
101
nbyte_dump(struct rtnl_ematch * e,struct nl_dump_params * p)102 static void nbyte_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
103 {
104 struct nbyte_data *n = rtnl_ematch_data(e);
105 int i;
106
107 nl_dump(p, "pattern(%u:[", n->cfg.len);
108
109 for (i = 0; i < n->cfg.len; i++) {
110 nl_dump(p, "%02x", n->pattern[i]);
111 if (i+1 < n->cfg.len)
112 nl_dump(p, " ");
113 }
114
115 nl_dump(p, "] at %s+%u)", layer_txt(&n->cfg), n->cfg.off);
116 }
117
nbyte_free(struct rtnl_ematch * e)118 static void nbyte_free(struct rtnl_ematch *e)
119 {
120 struct nbyte_data *n = rtnl_ematch_data(e);
121 free(n->pattern);
122 }
123
124 static struct rtnl_ematch_ops nbyte_ops = {
125 .eo_kind = TCF_EM_NBYTE,
126 .eo_name = "nbyte",
127 .eo_minlen = sizeof(struct tcf_em_nbyte),
128 .eo_datalen = sizeof(struct nbyte_data),
129 .eo_parse = nbyte_parse,
130 .eo_dump = nbyte_dump,
131 .eo_free = nbyte_free,
132 };
133
nbyte_init(void)134 static void __init nbyte_init(void)
135 {
136 rtnl_ematch_register(&nbyte_ops);
137 }
138
139 /** @} */
140