xref: /aosp_15_r20/external/iptables/iptables/nft-cmd.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
1 /*
2  * (C) 2012 by Pablo Neira Ayuso <[email protected]>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published
6  * by the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This code has been sponsored by Sophos Astaro <http://www.sophos.com>
10  */
11 
12 #include <stdlib.h>
13 #include <string.h>
14 #include <xtables.h>
15 #include "nft.h"
16 #include "nft-cmd.h"
17 #include <libnftnl/set.h>
18 
nft_cmd_new(struct nft_handle * h,int command,const char * table,const char * chain,struct iptables_command_state * state,int rulenum,bool verbose)19 struct nft_cmd *nft_cmd_new(struct nft_handle *h, int command,
20 			    const char *table, const char *chain,
21 			    struct iptables_command_state *state,
22 			    int rulenum, bool verbose)
23 {
24 	struct nft_rule_ctx ctx = {
25 		.command = command,
26 	};
27 	struct nftnl_rule *rule;
28 	struct nft_cmd *cmd;
29 
30 	cmd = xtables_calloc(1, sizeof(struct nft_cmd));
31 	cmd->error.lineno = h->error.lineno;
32 	cmd->command = command;
33 	cmd->table = xtables_strdup(table);
34 	if (chain)
35 		cmd->chain = xtables_strdup(chain);
36 	cmd->rulenum = rulenum;
37 	cmd->verbose = verbose;
38 
39 	if (state) {
40 		rule = nft_rule_new(h, &ctx, chain, table, state);
41 		if (!rule) {
42 			nft_cmd_free(cmd);
43 			return NULL;
44 		}
45 
46 		cmd->obj.rule = rule;
47 
48 		if (!state->target && strlen(state->jumpto) > 0)
49 			cmd->jumpto = xtables_strdup(state->jumpto);
50 	}
51 
52 	list_add_tail(&cmd->head, &h->cmd_list);
53 
54 	return cmd;
55 }
56 
nft_cmd_free(struct nft_cmd * cmd)57 void nft_cmd_free(struct nft_cmd *cmd)
58 {
59 	free((void *)cmd->table);
60 	free((void *)cmd->chain);
61 	free((void *)cmd->policy);
62 	free((void *)cmd->rename);
63 	free((void *)cmd->jumpto);
64 
65 	switch (cmd->command) {
66 	case NFT_COMPAT_RULE_CHECK:
67 	case NFT_COMPAT_RULE_DELETE:
68 		if (cmd->obj.rule)
69 			nftnl_rule_free(cmd->obj.rule);
70 		break;
71 	default:
72 		break;
73 	}
74 
75 	list_del(&cmd->head);
76 	free(cmd);
77 }
78 
nft_cmd_rule_bridge(struct nft_handle * h,const struct nft_cmd * cmd)79 static void nft_cmd_rule_bridge(struct nft_handle *h, const struct nft_cmd *cmd)
80 {
81 	const struct builtin_table *t;
82 
83 	t = nft_table_builtin_find(h, cmd->table);
84 	if (!t)
85 		return;
86 
87 	/* Since ebtables user-defined chain policies are implemented as last
88 	 * rule in nftables, rule cache is required here to treat them right.
89 	 */
90 	if (h->family == NFPROTO_BRIDGE &&
91 	    !nft_chain_builtin_find(t, cmd->chain))
92 		nft_cache_level_set(h, NFT_CL_RULES, cmd);
93 	else
94 		nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
95 }
96 
nft_cmd_rule_append(struct nft_handle * h,const char * chain,const char * table,struct iptables_command_state * state,bool verbose)97 int nft_cmd_rule_append(struct nft_handle *h, const char *chain,
98 			const char *table, struct iptables_command_state *state,
99 			bool verbose)
100 {
101 	struct nft_cmd *cmd;
102 
103 	cmd = nft_cmd_new(h, NFT_COMPAT_RULE_APPEND, table, chain, state, -1,
104 			  verbose);
105 	if (!cmd)
106 		return 0;
107 
108 	nft_cmd_rule_bridge(h, cmd);
109 
110 	return 1;
111 }
112 
nft_cmd_rule_insert(struct nft_handle * h,const char * chain,const char * table,struct iptables_command_state * state,int rulenum,bool verbose)113 int nft_cmd_rule_insert(struct nft_handle *h, const char *chain,
114 			const char *table, struct iptables_command_state *state,
115 			int rulenum, bool verbose)
116 {
117 	struct nft_cmd *cmd;
118 
119 	cmd = nft_cmd_new(h, NFT_COMPAT_RULE_INSERT, table, chain, state,
120 			  rulenum, verbose);
121 	if (!cmd)
122 		return 0;
123 
124 	nft_cmd_rule_bridge(h, cmd);
125 
126 	if (cmd->rulenum > 0)
127 		nft_cache_level_set(h, NFT_CL_RULES, cmd);
128 	else
129 		nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
130 
131 	return 1;
132 }
133 
nft_cmd_rule_delete(struct nft_handle * h,const char * chain,const char * table,struct iptables_command_state * state,bool verbose)134 int nft_cmd_rule_delete(struct nft_handle *h, const char *chain,
135 			const char *table, struct iptables_command_state *state,
136 			bool verbose)
137 {
138 	struct nft_cmd *cmd;
139 
140 	cmd = nft_cmd_new(h, NFT_COMPAT_RULE_DELETE, table, chain, state,
141 			  -1, verbose);
142 	if (!cmd)
143 		return 0;
144 
145 	nft_cache_level_set(h, NFT_CL_RULES, cmd);
146 
147 	return 1;
148 }
149 
nft_cmd_rule_delete_num(struct nft_handle * h,const char * chain,const char * table,int rulenum,bool verbose)150 int nft_cmd_rule_delete_num(struct nft_handle *h, const char *chain,
151 			    const char *table, int rulenum, bool verbose)
152 {
153 	struct nft_cmd *cmd;
154 
155 	cmd = nft_cmd_new(h, NFT_COMPAT_RULE_DELETE, table, chain, NULL,
156 			  rulenum, verbose);
157 	if (!cmd)
158 		return 0;
159 
160 	nft_cache_level_set(h, NFT_CL_RULES, cmd);
161 
162 	return 1;
163 }
164 
nft_cmd_rule_flush(struct nft_handle * h,const char * chain,const char * table,bool verbose)165 int nft_cmd_rule_flush(struct nft_handle *h, const char *chain,
166 		       const char *table, bool verbose)
167 {
168 	struct nft_cmd *cmd;
169 
170 	cmd = nft_cmd_new(h, NFT_COMPAT_RULE_FLUSH, table, chain, NULL, -1,
171 			  verbose);
172 	if (!cmd)
173 		return 0;
174 
175 	if (h->family == NFPROTO_BRIDGE)
176 		nft_cache_level_set(h, NFT_CL_RULES, cmd);
177 	else if (chain || verbose)
178 		nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
179 	else
180 		nft_cache_level_set(h, NFT_CL_TABLES, cmd);
181 
182 	return 1;
183 }
184 
nft_cmd_chain_zero_counters(struct nft_handle * h,const char * chain,const char * table,bool verbose)185 int nft_cmd_chain_zero_counters(struct nft_handle *h, const char *chain,
186 				const char *table, bool verbose)
187 {
188 	struct nft_cmd *cmd;
189 
190 	cmd = nft_cmd_new(h, NFT_COMPAT_CHAIN_ZERO, table, chain, NULL, -1,
191 			  verbose);
192 	if (!cmd)
193 		return 0;
194 
195 	nft_cache_level_set(h, NFT_CL_RULES, cmd);
196 
197 	return 1;
198 }
199 
nft_cmd_chain_user_add(struct nft_handle * h,const char * chain,const char * table)200 int nft_cmd_chain_user_add(struct nft_handle *h, const char *chain,
201 			   const char *table)
202 {
203 	struct nft_cmd *cmd;
204 
205 	cmd = nft_cmd_new(h, NFT_COMPAT_CHAIN_USER_ADD, table, chain, NULL, -1,
206 			  false);
207 	if (!cmd)
208 		return 0;
209 
210 	nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
211 
212 	return 1;
213 }
214 
nft_cmd_chain_del(struct nft_handle * h,const char * chain,const char * table,bool verbose)215 int nft_cmd_chain_del(struct nft_handle *h, const char *chain,
216 		      const char *table, bool verbose)
217 {
218 	struct nft_cmd *cmd;
219 
220 	cmd = nft_cmd_new(h, NFT_COMPAT_CHAIN_DEL, table, chain, NULL, -1,
221 			  verbose);
222 	if (!cmd)
223 		return 0;
224 
225 	/* This triggers nft_bridge_chain_postprocess() when fetching the
226 	 * rule cache.
227 	 */
228 	if (h->family == NFPROTO_BRIDGE || !chain)
229 		nft_cache_level_set(h, NFT_CL_RULES, cmd);
230 	else
231 		nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
232 
233 	return 1;
234 }
235 
nft_cmd_chain_user_rename(struct nft_handle * h,const char * chain,const char * table,const char * newname)236 int nft_cmd_chain_user_rename(struct nft_handle *h,const char *chain,
237 			      const char *table, const char *newname)
238 {
239 	struct nft_cmd *cmd;
240 
241 	cmd = nft_cmd_new(h, NFT_COMPAT_CHAIN_RENAME, table, chain, NULL, -1,
242 			  false);
243 	if (!cmd)
244 		return 0;
245 
246 	cmd->rename = xtables_strdup(newname);
247 
248 	nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
249 
250 	return 1;
251 }
252 
nft_cmd_rule_list(struct nft_handle * h,const char * chain,const char * table,int rulenum,unsigned int format)253 int nft_cmd_rule_list(struct nft_handle *h, const char *chain,
254 		      const char *table, int rulenum, unsigned int format)
255 {
256 	struct nft_cmd *cmd;
257 
258 	cmd = nft_cmd_new(h, NFT_COMPAT_RULE_LIST, table, chain, NULL, rulenum,
259 			  false);
260 	if (!cmd)
261 		return 0;
262 
263 	cmd->format = format;
264 
265 	nft_cache_level_set(h, NFT_CL_RULES, cmd);
266 
267 	return 1;
268 }
269 
nft_cmd_rule_replace(struct nft_handle * h,const char * chain,const char * table,void * data,int rulenum,bool verbose)270 int nft_cmd_rule_replace(struct nft_handle *h, const char *chain,
271 			 const char *table, void *data, int rulenum,
272 			 bool verbose)
273 {
274 	struct nft_cmd *cmd;
275 
276 	cmd = nft_cmd_new(h, NFT_COMPAT_RULE_REPLACE, table, chain, data,
277 			  rulenum, verbose);
278 	if (!cmd)
279 		return 0;
280 
281 	nft_cache_level_set(h, NFT_CL_RULES, cmd);
282 
283 	return 1;
284 }
285 
nft_cmd_rule_check(struct nft_handle * h,const char * chain,const char * table,void * data,bool verbose)286 int nft_cmd_rule_check(struct nft_handle *h, const char *chain,
287 		       const char *table, void *data, bool verbose)
288 {
289 	struct nft_cmd *cmd;
290 
291 	cmd = nft_cmd_new(h, NFT_COMPAT_RULE_CHECK, table, chain, data, -1,
292 			  verbose);
293 	if (!cmd)
294 		return 0;
295 
296 	nft_cache_level_set(h, NFT_CL_RULES, cmd);
297 
298 	return 1;
299 }
300 
nft_cmd_chain_set(struct nft_handle * h,const char * table,const char * chain,const char * policy,const struct xt_counters * counters)301 int nft_cmd_chain_set(struct nft_handle *h, const char *table,
302 		      const char *chain, const char *policy,
303 		      const struct xt_counters *counters)
304 {
305 	struct nft_cmd *cmd;
306 
307 	cmd = nft_cmd_new(h, NFT_COMPAT_CHAIN_UPDATE, table, chain, NULL, -1,
308 			  false);
309 	if (!cmd)
310 		return 0;
311 
312 	cmd->policy = xtables_strdup(policy);
313 	if (counters)
314 		cmd->counters = *counters;
315 
316 	nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
317 
318 	return 1;
319 }
320 
nft_cmd_table_flush(struct nft_handle * h,const char * table,bool verbose)321 int nft_cmd_table_flush(struct nft_handle *h, const char *table, bool verbose)
322 {
323 	struct nft_cmd *cmd;
324 
325 	if (verbose) {
326 		return nft_cmd_rule_flush(h, NULL, table, verbose) &&
327 		       nft_cmd_chain_del(h, NULL, table, verbose);
328 	}
329 
330 	cmd = nft_cmd_new(h, NFT_COMPAT_TABLE_FLUSH, table, NULL, NULL, -1,
331 			  false);
332 	if (!cmd)
333 		return 0;
334 
335 	nft_cache_level_set(h, NFT_CL_TABLES, cmd);
336 
337 	return 1;
338 }
339 
nft_cmd_chain_restore(struct nft_handle * h,const char * chain,const char * table)340 int nft_cmd_chain_restore(struct nft_handle *h, const char *chain,
341 			  const char *table)
342 {
343 	struct nft_cmd *cmd;
344 
345 	cmd = nft_cmd_new(h, NFT_COMPAT_CHAIN_RESTORE, table, chain, NULL, -1,
346 			  false);
347 	if (!cmd)
348 		return 0;
349 
350 	nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
351 
352 	return 1;
353 }
354 
nft_cmd_rule_zero_counters(struct nft_handle * h,const char * chain,const char * table,int rulenum)355 int nft_cmd_rule_zero_counters(struct nft_handle *h, const char *chain,
356 			       const char *table, int rulenum)
357 {
358 	struct nft_cmd *cmd;
359 
360 	cmd = nft_cmd_new(h, NFT_COMPAT_RULE_ZERO, table, chain, NULL, rulenum,
361 			  false);
362 	if (!cmd)
363 		return 0;
364 
365 	nft_cache_level_set(h, NFT_CL_RULES, cmd);
366 
367 	return 1;
368 }
369 
nft_cmd_rule_list_save(struct nft_handle * h,const char * chain,const char * table,int rulenum,int counters)370 int nft_cmd_rule_list_save(struct nft_handle *h, const char *chain,
371 			   const char *table, int rulenum, int counters)
372 {
373 	struct nft_cmd *cmd;
374 
375 	cmd = nft_cmd_new(h, NFT_COMPAT_RULE_SAVE, table, chain, NULL, rulenum,
376 			  false);
377 	if (!cmd)
378 		return 0;
379 
380 	cmd->counters_save = counters;
381 
382 	nft_cache_level_set(h, NFT_CL_RULES, cmd);
383 
384 	return 1;
385 }
386 
ebt_cmd_user_chain_policy(struct nft_handle * h,const char * table,const char * chain,const char * policy)387 int ebt_cmd_user_chain_policy(struct nft_handle *h, const char *table,
388                               const char *chain, const char *policy)
389 {
390 	struct nft_cmd *cmd;
391 
392 	cmd = nft_cmd_new(h, NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE, table, chain,
393 			  NULL, -1, false);
394 	if (!cmd)
395 		return 0;
396 
397 	cmd->policy = xtables_strdup(policy);
398 
399 	nft_cache_level_set(h, NFT_CL_RULES, cmd);
400 
401 	return 1;
402 }
403