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