xref: /aosp_15_r20/external/libnl/lib/route/cls/ematch/text.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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_text Text Search
9  *
10  * @{
11  */
12 
13 #include "nl-default.h"
14 
15 #include <linux/tc_ematch/tc_em_text.h>
16 
17 #include <netlink/netlink.h>
18 #include <netlink/route/cls/ematch.h>
19 #include <netlink/route/cls/ematch/text.h>
20 
21 struct text_data
22 {
23 	struct tcf_em_text	cfg;
24 	char *			pattern;
25 };
26 
rtnl_ematch_text_set_from(struct rtnl_ematch * e,uint8_t layer,uint16_t offset)27 void rtnl_ematch_text_set_from(struct rtnl_ematch *e, uint8_t layer,
28 			       uint16_t offset)
29 {
30 	struct text_data *t = rtnl_ematch_data(e);
31 	t->cfg.from_offset = offset;
32 	t->cfg.from_layer = layer;
33 }
34 
rtnl_ematch_text_get_from_offset(struct rtnl_ematch * e)35 uint16_t rtnl_ematch_text_get_from_offset(struct rtnl_ematch *e)
36 {
37 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_offset;
38 }
39 
rtnl_ematch_text_get_from_layer(struct rtnl_ematch * e)40 uint8_t rtnl_ematch_text_get_from_layer(struct rtnl_ematch *e)
41 {
42 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.from_layer;
43 }
44 
rtnl_ematch_text_set_to(struct rtnl_ematch * e,uint8_t layer,uint16_t offset)45 void rtnl_ematch_text_set_to(struct rtnl_ematch *e, uint8_t layer,
46 			       uint16_t offset)
47 {
48 	struct text_data *t = rtnl_ematch_data(e);
49 	t->cfg.to_offset = offset;
50 	t->cfg.to_layer = layer;
51 }
52 
rtnl_ematch_text_get_to_offset(struct rtnl_ematch * e)53 uint16_t rtnl_ematch_text_get_to_offset(struct rtnl_ematch *e)
54 {
55 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_offset;
56 }
57 
rtnl_ematch_text_get_to_layer(struct rtnl_ematch * e)58 uint8_t rtnl_ematch_text_get_to_layer(struct rtnl_ematch *e)
59 {
60 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.to_layer;
61 }
62 
rtnl_ematch_text_set_pattern(struct rtnl_ematch * e,char * pattern,size_t len)63 void rtnl_ematch_text_set_pattern(struct rtnl_ematch *e,
64 				  char *pattern, size_t len)
65 {
66 	struct text_data *t = rtnl_ematch_data(e);
67 
68 	if (t->pattern)
69 		free(t->pattern);
70 
71 	t->pattern = pattern;
72 	t->cfg.pattern_len = len;
73 }
74 
rtnl_ematch_text_get_pattern(struct rtnl_ematch * e)75 char *rtnl_ematch_text_get_pattern(struct rtnl_ematch *e)
76 {
77 	return ((struct text_data *) rtnl_ematch_data(e))->pattern;
78 }
79 
rtnl_ematch_text_get_len(struct rtnl_ematch * e)80 size_t rtnl_ematch_text_get_len(struct rtnl_ematch *e)
81 {
82 	return ((struct text_data *) rtnl_ematch_data(e))->cfg.pattern_len;
83 }
84 
rtnl_ematch_text_set_algo(struct rtnl_ematch * e,const char * algo)85 void rtnl_ematch_text_set_algo(struct rtnl_ematch *e, const char *algo)
86 {
87 	struct text_data *t = rtnl_ematch_data(e);
88 
89 	_nl_strncpy_trunc(t->cfg.algo, algo, sizeof(t->cfg.algo));
90 }
91 
rtnl_ematch_text_get_algo(struct rtnl_ematch * e)92 char *rtnl_ematch_text_get_algo(struct rtnl_ematch *e)
93 {
94 	struct text_data *t = rtnl_ematch_data(e);
95 
96 	return t->cfg.algo[0] ? t->cfg.algo : NULL;
97 }
98 
text_parse(struct rtnl_ematch * e,void * data,size_t len)99 static int text_parse(struct rtnl_ematch *e, void *data, size_t len)
100 {
101 	struct text_data *t = rtnl_ematch_data(e);
102 	size_t hdrlen = sizeof(struct tcf_em_text);
103 	size_t plen = len - hdrlen;
104 
105 	memcpy(&t->cfg, data, hdrlen);
106 
107 	if (t->cfg.pattern_len > plen)
108 		return -NLE_INVAL;
109 
110 	if (t->cfg.pattern_len > 0) {
111 		if (!(t->pattern = calloc(1, t->cfg.pattern_len)))
112 			return -NLE_NOMEM;
113 
114 		memcpy(t->pattern, (char *) data + hdrlen, t->cfg.pattern_len);
115 	}
116 
117 	return 0;
118 }
119 
text_dump(struct rtnl_ematch * e,struct nl_dump_params * p)120 static void text_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
121 {
122 	struct text_data *t = rtnl_ematch_data(e);
123 	char buf[64];
124 
125 	nl_dump(p, "text(%s \"%s\"",
126 		t->cfg.algo[0] ? t->cfg.algo : "no-algo",
127 		t->pattern ? t->pattern : "no-pattern");
128 
129 	if (t->cfg.from_layer || t->cfg.from_offset) {
130 		nl_dump(p, " from %s",
131 			rtnl_ematch_offset2txt(t->cfg.from_layer,
132 					       t->cfg.from_offset,
133 					       buf, sizeof(buf)));
134 	}
135 
136 	if (t->cfg.to_layer || t->cfg.to_offset) {
137 		nl_dump(p, " to %s",
138 			rtnl_ematch_offset2txt(t->cfg.to_layer,
139 					       t->cfg.to_offset,
140 					       buf, sizeof(buf)));
141 	}
142 
143 	nl_dump(p, ")");
144 }
145 
text_fill(struct rtnl_ematch * e,struct nl_msg * msg)146 static int text_fill(struct rtnl_ematch *e, struct nl_msg *msg)
147 {
148 	struct text_data *t = rtnl_ematch_data(e);
149 	int err;
150 
151 	if ((err = nlmsg_append(msg, &t->cfg, sizeof(t->cfg), 0)) < 0)
152 		return err;
153 
154 	return nlmsg_append(msg, t->pattern, t->cfg.pattern_len, 0);
155 }
156 
text_free(struct rtnl_ematch * e)157 static void text_free(struct rtnl_ematch *e)
158 {
159 	struct text_data *t = rtnl_ematch_data(e);
160 	free(t->pattern);
161 }
162 
163 static struct rtnl_ematch_ops text_ops = {
164 	.eo_kind	= TCF_EM_TEXT,
165 	.eo_name	= "text",
166 	.eo_minlen	= sizeof(struct tcf_em_text),
167 	.eo_datalen	= sizeof(struct text_data),
168 	.eo_parse	= text_parse,
169 	.eo_dump	= text_dump,
170 	.eo_fill	= text_fill,
171 	.eo_free	= text_free,
172 };
173 
text_init(void)174 static void _nl_init text_init(void)
175 {
176 	rtnl_ematch_register(&text_ops);
177 }
178 
179 /** @} */
180