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