1 #include <stdio.h>
2 #include <xtables.h>
3 #include <linux/netfilter/xt_cgroup.h>
4
5 enum {
6 O_CLASSID = 0,
7 O_PATH = 1,
8 };
9
cgroup_help_v0(void)10 static void cgroup_help_v0(void)
11 {
12 printf(
13 "cgroup match options:\n"
14 "[!] --cgroup classid Match cgroup classid\n");
15 }
16
cgroup_help_v1(void)17 static void cgroup_help_v1(void)
18 {
19 printf(
20 "cgroup match options:\n"
21 "[!] --path path Recursively match path relative to cgroup2 root\n"
22 "[!] --cgroup classid Match cgroup classid, can't be used with --path\n");
23 }
24
25 static const struct xt_option_entry cgroup_opts_v0[] = {
26 {
27 .name = "cgroup",
28 .id = O_CLASSID,
29 .type = XTTYPE_UINT32,
30 .flags = XTOPT_INVERT | XTOPT_MAND | XTOPT_PUT,
31 XTOPT_POINTER(struct xt_cgroup_info_v0, id)
32 },
33 XTOPT_TABLEEND,
34 };
35
36 static const struct xt_option_entry cgroup_opts_v1[] = {
37 {
38 .name = "path",
39 .id = O_PATH,
40 .type = XTTYPE_STRING,
41 .flags = XTOPT_INVERT | XTOPT_PUT,
42 XTOPT_POINTER(struct xt_cgroup_info_v1, path)
43 },
44 {
45 .name = "cgroup",
46 .id = O_CLASSID,
47 .type = XTTYPE_UINT32,
48 .flags = XTOPT_INVERT | XTOPT_PUT,
49 XTOPT_POINTER(struct xt_cgroup_info_v1, classid)
50 },
51 XTOPT_TABLEEND,
52 };
53
54 static const struct xt_option_entry cgroup_opts_v2[] = {
55 {
56 .name = "path",
57 .id = O_PATH,
58 .type = XTTYPE_STRING,
59 .flags = XTOPT_INVERT | XTOPT_PUT,
60 XTOPT_POINTER(struct xt_cgroup_info_v2, path)
61 },
62 {
63 .name = "cgroup",
64 .id = O_CLASSID,
65 .type = XTTYPE_UINT32,
66 .flags = XTOPT_INVERT | XTOPT_PUT,
67 XTOPT_POINTER(struct xt_cgroup_info_v2, classid)
68 },
69 XTOPT_TABLEEND,
70 };
71
cgroup_parse_v0(struct xt_option_call * cb)72 static void cgroup_parse_v0(struct xt_option_call *cb)
73 {
74 struct xt_cgroup_info_v0 *cgroupinfo = cb->data;
75
76 xtables_option_parse(cb);
77 if (cb->invert)
78 cgroupinfo->invert = true;
79 }
80
cgroup_parse_v1(struct xt_option_call * cb)81 static void cgroup_parse_v1(struct xt_option_call *cb)
82 {
83 struct xt_cgroup_info_v1 *info = cb->data;
84
85 xtables_option_parse(cb);
86
87 switch (cb->entry->id) {
88 case O_PATH:
89 info->has_path = true;
90 if (cb->invert)
91 info->invert_path = true;
92 break;
93 case O_CLASSID:
94 info->has_classid = true;
95 if (cb->invert)
96 info->invert_classid = true;
97 break;
98 }
99 }
100
cgroup_parse_v2(struct xt_option_call * cb)101 static void cgroup_parse_v2(struct xt_option_call *cb)
102 {
103 struct xt_cgroup_info_v2 *info = cb->data;
104
105 xtables_option_parse(cb);
106
107 switch (cb->entry->id) {
108 case O_PATH:
109 info->has_path = true;
110 if (cb->invert)
111 info->invert_path = true;
112 break;
113 case O_CLASSID:
114 info->has_classid = true;
115 if (cb->invert)
116 info->invert_classid = true;
117 break;
118 }
119 }
120
121 static void
cgroup_print_v0(const void * ip,const struct xt_entry_match * match,int numeric)122 cgroup_print_v0(const void *ip, const struct xt_entry_match *match, int numeric)
123 {
124 const struct xt_cgroup_info_v0 *info = (void *) match->data;
125
126 printf(" cgroup %s%u", info->invert ? "! ":"", info->id);
127 }
128
cgroup_save_v0(const void * ip,const struct xt_entry_match * match)129 static void cgroup_save_v0(const void *ip, const struct xt_entry_match *match)
130 {
131 const struct xt_cgroup_info_v0 *info = (void *) match->data;
132
133 printf("%s --cgroup %u", info->invert ? " !" : "", info->id);
134 }
135
136 static void
cgroup_print_v1(const void * ip,const struct xt_entry_match * match,int numeric)137 cgroup_print_v1(const void *ip, const struct xt_entry_match *match, int numeric)
138 {
139 const struct xt_cgroup_info_v1 *info = (void *)match->data;
140
141 printf(" cgroup");
142 if (info->has_path)
143 printf(" %s%s", info->invert_path ? "! ":"", info->path);
144 if (info->has_classid)
145 printf(" %s%u", info->invert_classid ? "! ":"", info->classid);
146 }
147
cgroup_save_v1(const void * ip,const struct xt_entry_match * match)148 static void cgroup_save_v1(const void *ip, const struct xt_entry_match *match)
149 {
150 const struct xt_cgroup_info_v1 *info = (void *)match->data;
151
152 if (info->has_path) {
153 printf("%s --path", info->invert_path ? " !" : "");
154 xtables_save_string(info->path);
155 }
156
157 if (info->has_classid)
158 printf("%s --cgroup %u", info->invert_classid ? " !" : "",
159 info->classid);
160 }
161
162 static void
cgroup_print_v2(const void * ip,const struct xt_entry_match * match,int numeric)163 cgroup_print_v2(const void *ip, const struct xt_entry_match *match, int numeric)
164 {
165 const struct xt_cgroup_info_v2 *info = (void *)match->data;
166
167 printf(" cgroup");
168 if (info->has_path)
169 printf(" %s%s", info->invert_path ? "! ":"", info->path);
170 if (info->has_classid)
171 printf(" %s%u", info->invert_classid ? "! ":"", info->classid);
172 }
173
cgroup_save_v2(const void * ip,const struct xt_entry_match * match)174 static void cgroup_save_v2(const void *ip, const struct xt_entry_match *match)
175 {
176 const struct xt_cgroup_info_v2 *info = (void *)match->data;
177
178 if (info->has_path) {
179 printf("%s --path", info->invert_path ? " !" : "");
180 xtables_save_string(info->path);
181 }
182
183 if (info->has_classid)
184 printf("%s --cgroup %u", info->invert_classid ? " !" : "",
185 info->classid);
186 }
187
cgroup_xlate_v0(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)188 static int cgroup_xlate_v0(struct xt_xlate *xl,
189 const struct xt_xlate_mt_params *params)
190 {
191 const struct xt_cgroup_info_v0 *info = (void *)params->match->data;
192
193 xt_xlate_add(xl, "meta cgroup %s%u", info->invert ? "!= " : "",
194 info->id);
195 return 1;
196 }
197
cgroup_xlate_v1(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)198 static int cgroup_xlate_v1(struct xt_xlate *xl,
199 const struct xt_xlate_mt_params *params)
200 {
201 const struct xt_cgroup_info_v1 *info = (void *)params->match->data;
202
203 if (info->has_path)
204 return 0;
205
206 if (info->has_classid)
207 xt_xlate_add(xl, "meta cgroup %s%u",
208 info->invert_classid ? "!= " : "",
209 info->classid);
210
211 return 1;
212 }
213
cgroup_xlate_v2(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)214 static int cgroup_xlate_v2(struct xt_xlate *xl,
215 const struct xt_xlate_mt_params *params)
216 {
217 const struct xt_cgroup_info_v2 *info = (void *)params->match->data;
218
219 if (info->has_path)
220 return 0;
221
222 if (info->has_classid)
223 xt_xlate_add(xl, "meta cgroup %s%u",
224 info->invert_classid ? "!= " : "",
225 info->classid);
226
227 return 1;
228 }
229
230 static struct xtables_match cgroup_match[] = {
231 {
232 .family = NFPROTO_UNSPEC,
233 .revision = 0,
234 .name = "cgroup",
235 .version = XTABLES_VERSION,
236 .size = XT_ALIGN(sizeof(struct xt_cgroup_info_v0)),
237 .userspacesize = XT_ALIGN(sizeof(struct xt_cgroup_info_v0)),
238 .help = cgroup_help_v0,
239 .print = cgroup_print_v0,
240 .save = cgroup_save_v0,
241 .x6_parse = cgroup_parse_v0,
242 .x6_options = cgroup_opts_v0,
243 .xlate = cgroup_xlate_v0,
244 },
245 {
246 .family = NFPROTO_UNSPEC,
247 .revision = 1,
248 .name = "cgroup",
249 .version = XTABLES_VERSION,
250 .size = XT_ALIGN(sizeof(struct xt_cgroup_info_v1)),
251 .userspacesize = offsetof(struct xt_cgroup_info_v1, priv),
252 .help = cgroup_help_v1,
253 .print = cgroup_print_v1,
254 .save = cgroup_save_v1,
255 .x6_parse = cgroup_parse_v1,
256 .x6_options = cgroup_opts_v1,
257 .xlate = cgroup_xlate_v1,
258 },
259 {
260 .family = NFPROTO_UNSPEC,
261 .revision = 2,
262 .name = "cgroup",
263 .version = XTABLES_VERSION,
264 .size = XT_ALIGN(sizeof(struct xt_cgroup_info_v2)),
265 .userspacesize = offsetof(struct xt_cgroup_info_v2, priv),
266 .help = cgroup_help_v1,
267 .print = cgroup_print_v2,
268 .save = cgroup_save_v2,
269 .x6_parse = cgroup_parse_v2,
270 .x6_options = cgroup_opts_v2,
271 .xlate = cgroup_xlate_v2,
272 },
273 };
274
_init(void)275 void _init(void)
276 {
277 xtables_register_matches(cgroup_match, ARRAY_SIZE(cgroup_match));
278 }
279