xref: /aosp_15_r20/external/iproute2/tc/m_ipt.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * m_ipt.c	iptables based targets
3*de1e4e89SAndroid Build Coastguard Worker  *		utilities mostly ripped from iptables <duh, its the linux way>
4*de1e4e89SAndroid Build Coastguard Worker  *
5*de1e4e89SAndroid Build Coastguard Worker  *		This program is free software; you can distribute it and/or
6*de1e4e89SAndroid Build Coastguard Worker  *		modify it under the terms of the GNU General Public License
7*de1e4e89SAndroid Build Coastguard Worker  *		as published by the Free Software Foundation; either version
8*de1e4e89SAndroid Build Coastguard Worker  *		2 of the License, or (at your option) any later version.
9*de1e4e89SAndroid Build Coastguard Worker  *
10*de1e4e89SAndroid Build Coastguard Worker  * Authors:  J Hadi Salim ([email protected])
11*de1e4e89SAndroid Build Coastguard Worker  */
12*de1e4e89SAndroid Build Coastguard Worker 
13*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <iptables.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <linux/netfilter.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <linux/netfilter_ipv4/ip_tables.h>
20*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
21*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
22*de1e4e89SAndroid Build Coastguard Worker #include <linux/tc_act/tc_ipt.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <dlfcn.h>
25*de1e4e89SAndroid Build Coastguard Worker #include <getopt.h>
26*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
27*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
28*de1e4e89SAndroid Build Coastguard Worker #include <netdb.h>
29*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
30*de1e4e89SAndroid Build Coastguard Worker #include <ctype.h>
31*de1e4e89SAndroid Build Coastguard Worker #include <stdarg.h>
32*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
33*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
34*de1e4e89SAndroid Build Coastguard Worker #include <sys/wait.h>
35*de1e4e89SAndroid Build Coastguard Worker 
36*de1e4e89SAndroid Build Coastguard Worker static const char *pname = "tc-ipt";
37*de1e4e89SAndroid Build Coastguard Worker static const char *tname = "mangle";
38*de1e4e89SAndroid Build Coastguard Worker static const char *pversion = "0.1";
39*de1e4e89SAndroid Build Coastguard Worker 
40*de1e4e89SAndroid Build Coastguard Worker static const char *ipthooks[] = {
41*de1e4e89SAndroid Build Coastguard Worker 	"NF_IP_PRE_ROUTING",
42*de1e4e89SAndroid Build Coastguard Worker 	"NF_IP_LOCAL_IN",
43*de1e4e89SAndroid Build Coastguard Worker 	"NF_IP_FORWARD",
44*de1e4e89SAndroid Build Coastguard Worker 	"NF_IP_LOCAL_OUT",
45*de1e4e89SAndroid Build Coastguard Worker 	"NF_IP_POST_ROUTING",
46*de1e4e89SAndroid Build Coastguard Worker };
47*de1e4e89SAndroid Build Coastguard Worker 
48*de1e4e89SAndroid Build Coastguard Worker static struct option original_opts[] = {
49*de1e4e89SAndroid Build Coastguard Worker 	{"jump", 1, 0, 'j'},
50*de1e4e89SAndroid Build Coastguard Worker 	{0, 0, 0, 0}
51*de1e4e89SAndroid Build Coastguard Worker };
52*de1e4e89SAndroid Build Coastguard Worker 
53*de1e4e89SAndroid Build Coastguard Worker static struct xtables_target *t_list;
54*de1e4e89SAndroid Build Coastguard Worker static struct option *opts = original_opts;
55*de1e4e89SAndroid Build Coastguard Worker static unsigned int global_option_offset;
56*de1e4e89SAndroid Build Coastguard Worker #define OPTION_OFFSET 256
57*de1e4e89SAndroid Build Coastguard Worker 
58*de1e4e89SAndroid Build Coastguard Worker char *lib_dir;
59*de1e4e89SAndroid Build Coastguard Worker 
60*de1e4e89SAndroid Build Coastguard Worker void
xtables_register_target(struct xtables_target * me)61*de1e4e89SAndroid Build Coastguard Worker xtables_register_target(struct xtables_target *me)
62*de1e4e89SAndroid Build Coastguard Worker {
63*de1e4e89SAndroid Build Coastguard Worker 	me->next = t_list;
64*de1e4e89SAndroid Build Coastguard Worker 	t_list = me;
65*de1e4e89SAndroid Build Coastguard Worker 
66*de1e4e89SAndroid Build Coastguard Worker }
67*de1e4e89SAndroid Build Coastguard Worker 
exit_tryhelp(int status)68*de1e4e89SAndroid Build Coastguard Worker static void exit_tryhelp(int status)
69*de1e4e89SAndroid Build Coastguard Worker {
70*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
71*de1e4e89SAndroid Build Coastguard Worker 		pname, pname);
72*de1e4e89SAndroid Build Coastguard Worker 	exit(status);
73*de1e4e89SAndroid Build Coastguard Worker }
74*de1e4e89SAndroid Build Coastguard Worker 
exit_error(enum xtables_exittype status,char * msg,...)75*de1e4e89SAndroid Build Coastguard Worker static void exit_error(enum xtables_exittype status, char *msg, ...)
76*de1e4e89SAndroid Build Coastguard Worker {
77*de1e4e89SAndroid Build Coastguard Worker 	va_list args;
78*de1e4e89SAndroid Build Coastguard Worker 
79*de1e4e89SAndroid Build Coastguard Worker 	va_start(args, msg);
80*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "%s v%s: ", pname, pversion);
81*de1e4e89SAndroid Build Coastguard Worker 	vfprintf(stderr, msg, args);
82*de1e4e89SAndroid Build Coastguard Worker 	va_end(args);
83*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\n");
84*de1e4e89SAndroid Build Coastguard Worker 	if (status == PARAMETER_PROBLEM)
85*de1e4e89SAndroid Build Coastguard Worker 		exit_tryhelp(status);
86*de1e4e89SAndroid Build Coastguard Worker 	if (status == VERSION_PROBLEM)
87*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr,
88*de1e4e89SAndroid Build Coastguard Worker 			"Perhaps iptables or your kernel needs to be upgraded.\n");
89*de1e4e89SAndroid Build Coastguard Worker 	exit(status);
90*de1e4e89SAndroid Build Coastguard Worker }
91*de1e4e89SAndroid Build Coastguard Worker 
92*de1e4e89SAndroid Build Coastguard Worker /* stolen from iptables 1.2.11
93*de1e4e89SAndroid Build Coastguard Worker They should really have them as a library so i can link to them
94*de1e4e89SAndroid Build Coastguard Worker Email them next time i remember
95*de1e4e89SAndroid Build Coastguard Worker */
96*de1e4e89SAndroid Build Coastguard Worker 
free_opts(struct option * local_opts)97*de1e4e89SAndroid Build Coastguard Worker static void free_opts(struct option *local_opts)
98*de1e4e89SAndroid Build Coastguard Worker {
99*de1e4e89SAndroid Build Coastguard Worker 	if (local_opts != original_opts) {
100*de1e4e89SAndroid Build Coastguard Worker 		free(local_opts);
101*de1e4e89SAndroid Build Coastguard Worker 		opts = original_opts;
102*de1e4e89SAndroid Build Coastguard Worker 		global_option_offset = 0;
103*de1e4e89SAndroid Build Coastguard Worker 	}
104*de1e4e89SAndroid Build Coastguard Worker }
105*de1e4e89SAndroid Build Coastguard Worker 
106*de1e4e89SAndroid Build Coastguard Worker static struct option *
merge_options(struct option * oldopts,const struct option * newopts,unsigned int * option_offset)107*de1e4e89SAndroid Build Coastguard Worker merge_options(struct option *oldopts, const struct option *newopts,
108*de1e4e89SAndroid Build Coastguard Worker 	      unsigned int *option_offset)
109*de1e4e89SAndroid Build Coastguard Worker {
110*de1e4e89SAndroid Build Coastguard Worker 	struct option *merge;
111*de1e4e89SAndroid Build Coastguard Worker 	unsigned int num_old, num_new, i;
112*de1e4e89SAndroid Build Coastguard Worker 
113*de1e4e89SAndroid Build Coastguard Worker 	for (num_old = 0; oldopts[num_old].name; num_old++);
114*de1e4e89SAndroid Build Coastguard Worker 	for (num_new = 0; newopts[num_new].name; num_new++);
115*de1e4e89SAndroid Build Coastguard Worker 
116*de1e4e89SAndroid Build Coastguard Worker 	*option_offset = global_option_offset + OPTION_OFFSET;
117*de1e4e89SAndroid Build Coastguard Worker 
118*de1e4e89SAndroid Build Coastguard Worker 	merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
119*de1e4e89SAndroid Build Coastguard Worker 	memcpy(merge, oldopts, num_old * sizeof(struct option));
120*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < num_new; i++) {
121*de1e4e89SAndroid Build Coastguard Worker 		merge[num_old + i] = newopts[i];
122*de1e4e89SAndroid Build Coastguard Worker 		merge[num_old + i].val += *option_offset;
123*de1e4e89SAndroid Build Coastguard Worker 	}
124*de1e4e89SAndroid Build Coastguard Worker 	memset(merge + num_old + num_new, 0, sizeof(struct option));
125*de1e4e89SAndroid Build Coastguard Worker 
126*de1e4e89SAndroid Build Coastguard Worker 	return merge;
127*de1e4e89SAndroid Build Coastguard Worker }
128*de1e4e89SAndroid Build Coastguard Worker 
129*de1e4e89SAndroid Build Coastguard Worker static void *
fw_calloc(size_t count,size_t size)130*de1e4e89SAndroid Build Coastguard Worker fw_calloc(size_t count, size_t size)
131*de1e4e89SAndroid Build Coastguard Worker {
132*de1e4e89SAndroid Build Coastguard Worker 	void *p;
133*de1e4e89SAndroid Build Coastguard Worker 
134*de1e4e89SAndroid Build Coastguard Worker 	if ((p = (void *) calloc(count, size)) == NULL) {
135*de1e4e89SAndroid Build Coastguard Worker 		perror("iptables: calloc failed");
136*de1e4e89SAndroid Build Coastguard Worker 		exit(1);
137*de1e4e89SAndroid Build Coastguard Worker 	}
138*de1e4e89SAndroid Build Coastguard Worker 	return p;
139*de1e4e89SAndroid Build Coastguard Worker }
140*de1e4e89SAndroid Build Coastguard Worker 
141*de1e4e89SAndroid Build Coastguard Worker static struct xtables_target *
find_t(char * name)142*de1e4e89SAndroid Build Coastguard Worker find_t(char *name)
143*de1e4e89SAndroid Build Coastguard Worker {
144*de1e4e89SAndroid Build Coastguard Worker 	struct xtables_target *m;
145*de1e4e89SAndroid Build Coastguard Worker 
146*de1e4e89SAndroid Build Coastguard Worker 	for (m = t_list; m; m = m->next) {
147*de1e4e89SAndroid Build Coastguard Worker 		if (strcmp(m->name, name) == 0)
148*de1e4e89SAndroid Build Coastguard Worker 			return m;
149*de1e4e89SAndroid Build Coastguard Worker 	}
150*de1e4e89SAndroid Build Coastguard Worker 
151*de1e4e89SAndroid Build Coastguard Worker 	return NULL;
152*de1e4e89SAndroid Build Coastguard Worker }
153*de1e4e89SAndroid Build Coastguard Worker 
154*de1e4e89SAndroid Build Coastguard Worker static struct xtables_target *
get_target_name(const char * name)155*de1e4e89SAndroid Build Coastguard Worker get_target_name(const char *name)
156*de1e4e89SAndroid Build Coastguard Worker {
157*de1e4e89SAndroid Build Coastguard Worker 	void *handle;
158*de1e4e89SAndroid Build Coastguard Worker 	char *error;
159*de1e4e89SAndroid Build Coastguard Worker 	char *new_name, *lname;
160*de1e4e89SAndroid Build Coastguard Worker 	struct xtables_target *m;
161*de1e4e89SAndroid Build Coastguard Worker 	char path[strlen(lib_dir) + sizeof("/libipt_.so") + strlen(name)];
162*de1e4e89SAndroid Build Coastguard Worker 
163*de1e4e89SAndroid Build Coastguard Worker #ifdef NO_SHARED_LIBS
164*de1e4e89SAndroid Build Coastguard Worker 	return NULL;
165*de1e4e89SAndroid Build Coastguard Worker #endif
166*de1e4e89SAndroid Build Coastguard Worker 
167*de1e4e89SAndroid Build Coastguard Worker 	new_name = calloc(1, strlen(name) + 1);
168*de1e4e89SAndroid Build Coastguard Worker 	lname = calloc(1, strlen(name) + 1);
169*de1e4e89SAndroid Build Coastguard Worker 	if (!new_name)
170*de1e4e89SAndroid Build Coastguard Worker 		exit_error(PARAMETER_PROBLEM, "get_target_name");
171*de1e4e89SAndroid Build Coastguard Worker 	if (!lname)
172*de1e4e89SAndroid Build Coastguard Worker 		exit_error(PARAMETER_PROBLEM, "get_target_name");
173*de1e4e89SAndroid Build Coastguard Worker 
174*de1e4e89SAndroid Build Coastguard Worker 	strcpy(new_name, name);
175*de1e4e89SAndroid Build Coastguard Worker 	strcpy(lname, name);
176*de1e4e89SAndroid Build Coastguard Worker 
177*de1e4e89SAndroid Build Coastguard Worker 	if (isupper(lname[0])) {
178*de1e4e89SAndroid Build Coastguard Worker 		int i;
179*de1e4e89SAndroid Build Coastguard Worker 
180*de1e4e89SAndroid Build Coastguard Worker 		for (i = 0; i < strlen(name); i++) {
181*de1e4e89SAndroid Build Coastguard Worker 			lname[i] = tolower(lname[i]);
182*de1e4e89SAndroid Build Coastguard Worker 		}
183*de1e4e89SAndroid Build Coastguard Worker 	}
184*de1e4e89SAndroid Build Coastguard Worker 
185*de1e4e89SAndroid Build Coastguard Worker 	if (islower(new_name[0])) {
186*de1e4e89SAndroid Build Coastguard Worker 		int i;
187*de1e4e89SAndroid Build Coastguard Worker 
188*de1e4e89SAndroid Build Coastguard Worker 		for (i = 0; i < strlen(new_name); i++) {
189*de1e4e89SAndroid Build Coastguard Worker 			new_name[i] = toupper(new_name[i]);
190*de1e4e89SAndroid Build Coastguard Worker 		}
191*de1e4e89SAndroid Build Coastguard Worker 	}
192*de1e4e89SAndroid Build Coastguard Worker 
193*de1e4e89SAndroid Build Coastguard Worker 	/* try libxt_xx first */
194*de1e4e89SAndroid Build Coastguard Worker 	sprintf(path, "%s/libxt_%s.so", lib_dir, new_name);
195*de1e4e89SAndroid Build Coastguard Worker 	handle = dlopen(path, RTLD_LAZY);
196*de1e4e89SAndroid Build Coastguard Worker 	if (!handle) {
197*de1e4e89SAndroid Build Coastguard Worker 		/* try libipt_xx next */
198*de1e4e89SAndroid Build Coastguard Worker 		sprintf(path, "%s/libipt_%s.so", lib_dir, new_name);
199*de1e4e89SAndroid Build Coastguard Worker 		handle = dlopen(path, RTLD_LAZY);
200*de1e4e89SAndroid Build Coastguard Worker 
201*de1e4e89SAndroid Build Coastguard Worker 		if (!handle) {
202*de1e4e89SAndroid Build Coastguard Worker 			sprintf(path, "%s/libxt_%s.so", lib_dir, lname);
203*de1e4e89SAndroid Build Coastguard Worker 			handle = dlopen(path, RTLD_LAZY);
204*de1e4e89SAndroid Build Coastguard Worker 		}
205*de1e4e89SAndroid Build Coastguard Worker 
206*de1e4e89SAndroid Build Coastguard Worker 		if (!handle) {
207*de1e4e89SAndroid Build Coastguard Worker 			sprintf(path, "%s/libipt_%s.so", lib_dir, lname);
208*de1e4e89SAndroid Build Coastguard Worker 			handle = dlopen(path, RTLD_LAZY);
209*de1e4e89SAndroid Build Coastguard Worker 		}
210*de1e4e89SAndroid Build Coastguard Worker 		/* ok, lets give up .. */
211*de1e4e89SAndroid Build Coastguard Worker 		if (!handle) {
212*de1e4e89SAndroid Build Coastguard Worker 			fputs(dlerror(), stderr);
213*de1e4e89SAndroid Build Coastguard Worker 			printf("\n");
214*de1e4e89SAndroid Build Coastguard Worker 			free(new_name);
215*de1e4e89SAndroid Build Coastguard Worker 			free(lname);
216*de1e4e89SAndroid Build Coastguard Worker 			return NULL;
217*de1e4e89SAndroid Build Coastguard Worker 		}
218*de1e4e89SAndroid Build Coastguard Worker 	}
219*de1e4e89SAndroid Build Coastguard Worker 
220*de1e4e89SAndroid Build Coastguard Worker 	m = dlsym(handle, new_name);
221*de1e4e89SAndroid Build Coastguard Worker 	if ((error = dlerror()) != NULL) {
222*de1e4e89SAndroid Build Coastguard Worker 		m = (struct xtables_target *) dlsym(handle, lname);
223*de1e4e89SAndroid Build Coastguard Worker 		if ((error = dlerror()) != NULL) {
224*de1e4e89SAndroid Build Coastguard Worker 			m = find_t(new_name);
225*de1e4e89SAndroid Build Coastguard Worker 			if (m == NULL) {
226*de1e4e89SAndroid Build Coastguard Worker 				m = find_t(lname);
227*de1e4e89SAndroid Build Coastguard Worker 				if (m == NULL) {
228*de1e4e89SAndroid Build Coastguard Worker 					fputs(error, stderr);
229*de1e4e89SAndroid Build Coastguard Worker 					fprintf(stderr, "\n");
230*de1e4e89SAndroid Build Coastguard Worker 					dlclose(handle);
231*de1e4e89SAndroid Build Coastguard Worker 					free(new_name);
232*de1e4e89SAndroid Build Coastguard Worker 					free(lname);
233*de1e4e89SAndroid Build Coastguard Worker 					return NULL;
234*de1e4e89SAndroid Build Coastguard Worker 				}
235*de1e4e89SAndroid Build Coastguard Worker 			}
236*de1e4e89SAndroid Build Coastguard Worker 		}
237*de1e4e89SAndroid Build Coastguard Worker 	}
238*de1e4e89SAndroid Build Coastguard Worker 
239*de1e4e89SAndroid Build Coastguard Worker 	free(new_name);
240*de1e4e89SAndroid Build Coastguard Worker 	free(lname);
241*de1e4e89SAndroid Build Coastguard Worker 	return m;
242*de1e4e89SAndroid Build Coastguard Worker }
243*de1e4e89SAndroid Build Coastguard Worker 
set_revision(char * name,u_int8_t revision)244*de1e4e89SAndroid Build Coastguard Worker static void set_revision(char *name, u_int8_t revision)
245*de1e4e89SAndroid Build Coastguard Worker {
246*de1e4e89SAndroid Build Coastguard Worker 	/* Old kernel sources don't have ".revision" field,
247*de1e4e89SAndroid Build Coastguard Worker 	*  but we stole a byte from name. */
248*de1e4e89SAndroid Build Coastguard Worker 	name[IPT_FUNCTION_MAXNAMELEN - 2] = '\0';
249*de1e4e89SAndroid Build Coastguard Worker 	name[IPT_FUNCTION_MAXNAMELEN - 1] = revision;
250*de1e4e89SAndroid Build Coastguard Worker }
251*de1e4e89SAndroid Build Coastguard Worker 
252*de1e4e89SAndroid Build Coastguard Worker /*
253*de1e4e89SAndroid Build Coastguard Worker  * we may need to check for version mismatch
254*de1e4e89SAndroid Build Coastguard Worker */
build_st(struct xtables_target * target,struct ipt_entry_target * t)255*de1e4e89SAndroid Build Coastguard Worker static int build_st(struct xtables_target *target, struct ipt_entry_target *t)
256*de1e4e89SAndroid Build Coastguard Worker {
257*de1e4e89SAndroid Build Coastguard Worker 	if (target) {
258*de1e4e89SAndroid Build Coastguard Worker 		size_t size;
259*de1e4e89SAndroid Build Coastguard Worker 
260*de1e4e89SAndroid Build Coastguard Worker 		size =
261*de1e4e89SAndroid Build Coastguard Worker 		    XT_ALIGN(sizeof(struct ipt_entry_target)) + target->size;
262*de1e4e89SAndroid Build Coastguard Worker 
263*de1e4e89SAndroid Build Coastguard Worker 		if (t == NULL) {
264*de1e4e89SAndroid Build Coastguard Worker 			target->t = fw_calloc(1, size);
265*de1e4e89SAndroid Build Coastguard Worker 			target->t->u.target_size = size;
266*de1e4e89SAndroid Build Coastguard Worker 
267*de1e4e89SAndroid Build Coastguard Worker 			if (target->init != NULL)
268*de1e4e89SAndroid Build Coastguard Worker 				target->init(target->t);
269*de1e4e89SAndroid Build Coastguard Worker 			set_revision(target->t->u.user.name, target->revision);
270*de1e4e89SAndroid Build Coastguard Worker 		} else {
271*de1e4e89SAndroid Build Coastguard Worker 			target->t = t;
272*de1e4e89SAndroid Build Coastguard Worker 		}
273*de1e4e89SAndroid Build Coastguard Worker 		strcpy(target->t->u.user.name, target->name);
274*de1e4e89SAndroid Build Coastguard Worker 		return 0;
275*de1e4e89SAndroid Build Coastguard Worker 	}
276*de1e4e89SAndroid Build Coastguard Worker 
277*de1e4e89SAndroid Build Coastguard Worker 	return -1;
278*de1e4e89SAndroid Build Coastguard Worker }
279*de1e4e89SAndroid Build Coastguard Worker 
parse_ipt(struct action_util * a,int * argc_p,char *** argv_p,int tca_id,struct nlmsghdr * n)280*de1e4e89SAndroid Build Coastguard Worker static int parse_ipt(struct action_util *a, int *argc_p,
281*de1e4e89SAndroid Build Coastguard Worker 		     char ***argv_p, int tca_id, struct nlmsghdr *n)
282*de1e4e89SAndroid Build Coastguard Worker {
283*de1e4e89SAndroid Build Coastguard Worker 	struct xtables_target *m = NULL;
284*de1e4e89SAndroid Build Coastguard Worker 	struct ipt_entry fw;
285*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tail;
286*de1e4e89SAndroid Build Coastguard Worker 	int c;
287*de1e4e89SAndroid Build Coastguard Worker 	int rargc = *argc_p;
288*de1e4e89SAndroid Build Coastguard Worker 	char **argv = *argv_p;
289*de1e4e89SAndroid Build Coastguard Worker 	int argc = 0, iargc = 0;
290*de1e4e89SAndroid Build Coastguard Worker 	char k[16];
291*de1e4e89SAndroid Build Coastguard Worker 	int size = 0;
292*de1e4e89SAndroid Build Coastguard Worker 	int iok = 0, ok = 0;
293*de1e4e89SAndroid Build Coastguard Worker 	__u32 hook = 0, index = 0;
294*de1e4e89SAndroid Build Coastguard Worker 
295*de1e4e89SAndroid Build Coastguard Worker 	lib_dir = getenv("IPTABLES_LIB_DIR");
296*de1e4e89SAndroid Build Coastguard Worker 	if (!lib_dir)
297*de1e4e89SAndroid Build Coastguard Worker 		lib_dir = IPT_LIB_DIR;
298*de1e4e89SAndroid Build Coastguard Worker 
299*de1e4e89SAndroid Build Coastguard Worker 	{
300*de1e4e89SAndroid Build Coastguard Worker 		int i;
301*de1e4e89SAndroid Build Coastguard Worker 
302*de1e4e89SAndroid Build Coastguard Worker 		for (i = 0; i < rargc; i++) {
303*de1e4e89SAndroid Build Coastguard Worker 			if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) {
304*de1e4e89SAndroid Build Coastguard Worker 				break;
305*de1e4e89SAndroid Build Coastguard Worker 			}
306*de1e4e89SAndroid Build Coastguard Worker 		}
307*de1e4e89SAndroid Build Coastguard Worker 		iargc = argc = i;
308*de1e4e89SAndroid Build Coastguard Worker 	}
309*de1e4e89SAndroid Build Coastguard Worker 
310*de1e4e89SAndroid Build Coastguard Worker 	if (argc <= 2) {
311*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "bad arguments to ipt %d vs %d\n", argc, rargc);
312*de1e4e89SAndroid Build Coastguard Worker 		return -1;
313*de1e4e89SAndroid Build Coastguard Worker 	}
314*de1e4e89SAndroid Build Coastguard Worker 
315*de1e4e89SAndroid Build Coastguard Worker 	while (1) {
316*de1e4e89SAndroid Build Coastguard Worker 		c = getopt_long(argc, argv, "j:", opts, NULL);
317*de1e4e89SAndroid Build Coastguard Worker 		if (c == -1)
318*de1e4e89SAndroid Build Coastguard Worker 			break;
319*de1e4e89SAndroid Build Coastguard Worker 		switch (c) {
320*de1e4e89SAndroid Build Coastguard Worker 		case 'j':
321*de1e4e89SAndroid Build Coastguard Worker 			m = get_target_name(optarg);
322*de1e4e89SAndroid Build Coastguard Worker 			if (m != NULL) {
323*de1e4e89SAndroid Build Coastguard Worker 
324*de1e4e89SAndroid Build Coastguard Worker 				if (build_st(m, NULL) < 0) {
325*de1e4e89SAndroid Build Coastguard Worker 					printf(" %s error\n", m->name);
326*de1e4e89SAndroid Build Coastguard Worker 					return -1;
327*de1e4e89SAndroid Build Coastguard Worker 				}
328*de1e4e89SAndroid Build Coastguard Worker 				opts =
329*de1e4e89SAndroid Build Coastguard Worker 				    merge_options(opts, m->extra_opts,
330*de1e4e89SAndroid Build Coastguard Worker 						  &m->option_offset);
331*de1e4e89SAndroid Build Coastguard Worker 			} else {
332*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, " failed to find target %s\n\n", optarg);
333*de1e4e89SAndroid Build Coastguard Worker 				return -1;
334*de1e4e89SAndroid Build Coastguard Worker 			}
335*de1e4e89SAndroid Build Coastguard Worker 			ok++;
336*de1e4e89SAndroid Build Coastguard Worker 			break;
337*de1e4e89SAndroid Build Coastguard Worker 
338*de1e4e89SAndroid Build Coastguard Worker 		default:
339*de1e4e89SAndroid Build Coastguard Worker 			memset(&fw, 0, sizeof(fw));
340*de1e4e89SAndroid Build Coastguard Worker 			if (m) {
341*de1e4e89SAndroid Build Coastguard Worker 				m->parse(c - m->option_offset, argv, 0,
342*de1e4e89SAndroid Build Coastguard Worker 					 &m->tflags, NULL, &m->t);
343*de1e4e89SAndroid Build Coastguard Worker 			} else {
344*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, " failed to find target %s\n\n", optarg);
345*de1e4e89SAndroid Build Coastguard Worker 				return -1;
346*de1e4e89SAndroid Build Coastguard Worker 
347*de1e4e89SAndroid Build Coastguard Worker 			}
348*de1e4e89SAndroid Build Coastguard Worker 			ok++;
349*de1e4e89SAndroid Build Coastguard Worker 			break;
350*de1e4e89SAndroid Build Coastguard Worker 
351*de1e4e89SAndroid Build Coastguard Worker 		}
352*de1e4e89SAndroid Build Coastguard Worker 	}
353*de1e4e89SAndroid Build Coastguard Worker 
354*de1e4e89SAndroid Build Coastguard Worker 	if (iargc > optind) {
355*de1e4e89SAndroid Build Coastguard Worker 		if (matches(argv[optind], "index") == 0) {
356*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&index, argv[optind + 1], 10)) {
357*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Illegal \"index\"\n");
358*de1e4e89SAndroid Build Coastguard Worker 				free_opts(opts);
359*de1e4e89SAndroid Build Coastguard Worker 				return -1;
360*de1e4e89SAndroid Build Coastguard Worker 			}
361*de1e4e89SAndroid Build Coastguard Worker 			iok++;
362*de1e4e89SAndroid Build Coastguard Worker 
363*de1e4e89SAndroid Build Coastguard Worker 			optind += 2;
364*de1e4e89SAndroid Build Coastguard Worker 		}
365*de1e4e89SAndroid Build Coastguard Worker 	}
366*de1e4e89SAndroid Build Coastguard Worker 
367*de1e4e89SAndroid Build Coastguard Worker 	if (!ok && !iok) {
368*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, " ipt Parser BAD!! (%s)\n", *argv);
369*de1e4e89SAndroid Build Coastguard Worker 		return -1;
370*de1e4e89SAndroid Build Coastguard Worker 	}
371*de1e4e89SAndroid Build Coastguard Worker 
372*de1e4e89SAndroid Build Coastguard Worker 	/* check that we passed the correct parameters to the target */
373*de1e4e89SAndroid Build Coastguard Worker 	if (m)
374*de1e4e89SAndroid Build Coastguard Worker 		m->final_check(m->tflags);
375*de1e4e89SAndroid Build Coastguard Worker 
376*de1e4e89SAndroid Build Coastguard Worker 	{
377*de1e4e89SAndroid Build Coastguard Worker 		struct tcmsg *t = NLMSG_DATA(n);
378*de1e4e89SAndroid Build Coastguard Worker 
379*de1e4e89SAndroid Build Coastguard Worker 		if (t->tcm_parent != TC_H_ROOT
380*de1e4e89SAndroid Build Coastguard Worker 		    && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) {
381*de1e4e89SAndroid Build Coastguard Worker 			hook = NF_IP_PRE_ROUTING;
382*de1e4e89SAndroid Build Coastguard Worker 		} else {
383*de1e4e89SAndroid Build Coastguard Worker 			hook = NF_IP_POST_ROUTING;
384*de1e4e89SAndroid Build Coastguard Worker 		}
385*de1e4e89SAndroid Build Coastguard Worker 	}
386*de1e4e89SAndroid Build Coastguard Worker 
387*de1e4e89SAndroid Build Coastguard Worker 	tail = NLMSG_TAIL(n);
388*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
389*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]);
390*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stdout, "\ttarget: ");
391*de1e4e89SAndroid Build Coastguard Worker 
392*de1e4e89SAndroid Build Coastguard Worker 	if (m)
393*de1e4e89SAndroid Build Coastguard Worker 		m->print(NULL, m->t, 0);
394*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stdout, " index %d\n", index);
395*de1e4e89SAndroid Build Coastguard Worker 
396*de1e4e89SAndroid Build Coastguard Worker 	if (strlen(tname) > 16) {
397*de1e4e89SAndroid Build Coastguard Worker 		size = 16;
398*de1e4e89SAndroid Build Coastguard Worker 		k[15] = 0;
399*de1e4e89SAndroid Build Coastguard Worker 	} else {
400*de1e4e89SAndroid Build Coastguard Worker 		size = 1 + strlen(tname);
401*de1e4e89SAndroid Build Coastguard Worker 	}
402*de1e4e89SAndroid Build Coastguard Worker 	strncpy(k, tname, size);
403*de1e4e89SAndroid Build Coastguard Worker 
404*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, TCA_IPT_TABLE, k, size);
405*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, TCA_IPT_HOOK, &hook, 4);
406*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4);
407*de1e4e89SAndroid Build Coastguard Worker 	if (m)
408*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size);
409*de1e4e89SAndroid Build Coastguard Worker 	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
410*de1e4e89SAndroid Build Coastguard Worker 
411*de1e4e89SAndroid Build Coastguard Worker 	argc -= optind;
412*de1e4e89SAndroid Build Coastguard Worker 	argv += optind;
413*de1e4e89SAndroid Build Coastguard Worker 	*argc_p = rargc - iargc;
414*de1e4e89SAndroid Build Coastguard Worker 	*argv_p = argv;
415*de1e4e89SAndroid Build Coastguard Worker 
416*de1e4e89SAndroid Build Coastguard Worker 	optind = 0;
417*de1e4e89SAndroid Build Coastguard Worker 	free_opts(opts);
418*de1e4e89SAndroid Build Coastguard Worker 	/* Clear flags if target will be used again */
419*de1e4e89SAndroid Build Coastguard Worker         m->tflags = 0;
420*de1e4e89SAndroid Build Coastguard Worker         m->used = 0;
421*de1e4e89SAndroid Build Coastguard Worker 	/* Free allocated memory */
422*de1e4e89SAndroid Build Coastguard Worker 	if (m->t)
423*de1e4e89SAndroid Build Coastguard Worker 	    free(m->t);
424*de1e4e89SAndroid Build Coastguard Worker 
425*de1e4e89SAndroid Build Coastguard Worker 
426*de1e4e89SAndroid Build Coastguard Worker 	return 0;
427*de1e4e89SAndroid Build Coastguard Worker 
428*de1e4e89SAndroid Build Coastguard Worker }
429*de1e4e89SAndroid Build Coastguard Worker 
430*de1e4e89SAndroid Build Coastguard Worker static int
print_ipt(struct action_util * au,FILE * f,struct rtattr * arg)431*de1e4e89SAndroid Build Coastguard Worker print_ipt(struct action_util *au, FILE * f, struct rtattr *arg)
432*de1e4e89SAndroid Build Coastguard Worker {
433*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[TCA_IPT_MAX + 1];
434*de1e4e89SAndroid Build Coastguard Worker 	struct ipt_entry_target *t = NULL;
435*de1e4e89SAndroid Build Coastguard Worker 
436*de1e4e89SAndroid Build Coastguard Worker 	if (arg == NULL)
437*de1e4e89SAndroid Build Coastguard Worker 		return -1;
438*de1e4e89SAndroid Build Coastguard Worker 
439*de1e4e89SAndroid Build Coastguard Worker 	lib_dir = getenv("IPTABLES_LIB_DIR");
440*de1e4e89SAndroid Build Coastguard Worker 	if (!lib_dir)
441*de1e4e89SAndroid Build Coastguard Worker 		lib_dir = IPT_LIB_DIR;
442*de1e4e89SAndroid Build Coastguard Worker 
443*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr_nested(tb, TCA_IPT_MAX, arg);
444*de1e4e89SAndroid Build Coastguard Worker 
445*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_IPT_TABLE] == NULL) {
446*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "[NULL ipt table name ] assuming mangle ");
447*de1e4e89SAndroid Build Coastguard Worker 	} else {
448*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "tablename: %s ",
449*de1e4e89SAndroid Build Coastguard Worker 			rta_getattr_str(tb[TCA_IPT_TABLE]));
450*de1e4e89SAndroid Build Coastguard Worker 	}
451*de1e4e89SAndroid Build Coastguard Worker 
452*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_IPT_HOOK] == NULL) {
453*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "[NULL ipt hook name ]\n ");
454*de1e4e89SAndroid Build Coastguard Worker 		return -1;
455*de1e4e89SAndroid Build Coastguard Worker 	} else {
456*de1e4e89SAndroid Build Coastguard Worker 		__u32 hook;
457*de1e4e89SAndroid Build Coastguard Worker 
458*de1e4e89SAndroid Build Coastguard Worker 		hook = rta_getattr_u32(tb[TCA_IPT_HOOK]);
459*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, " hook: %s\n", ipthooks[hook]);
460*de1e4e89SAndroid Build Coastguard Worker 	}
461*de1e4e89SAndroid Build Coastguard Worker 
462*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_IPT_TARG] == NULL) {
463*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "\t[NULL ipt target parameters ]\n");
464*de1e4e89SAndroid Build Coastguard Worker 		return -1;
465*de1e4e89SAndroid Build Coastguard Worker 	} else {
466*de1e4e89SAndroid Build Coastguard Worker 		struct xtables_target *m = NULL;
467*de1e4e89SAndroid Build Coastguard Worker 
468*de1e4e89SAndroid Build Coastguard Worker 		t = RTA_DATA(tb[TCA_IPT_TARG]);
469*de1e4e89SAndroid Build Coastguard Worker 		m = get_target_name(t->u.user.name);
470*de1e4e89SAndroid Build Coastguard Worker 		if (m != NULL) {
471*de1e4e89SAndroid Build Coastguard Worker 			if (build_st(m, t) < 0) {
472*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, " %s error\n", m->name);
473*de1e4e89SAndroid Build Coastguard Worker 				return -1;
474*de1e4e89SAndroid Build Coastguard Worker 			}
475*de1e4e89SAndroid Build Coastguard Worker 
476*de1e4e89SAndroid Build Coastguard Worker 			opts =
477*de1e4e89SAndroid Build Coastguard Worker 			    merge_options(opts, m->extra_opts,
478*de1e4e89SAndroid Build Coastguard Worker 					  &m->option_offset);
479*de1e4e89SAndroid Build Coastguard Worker 		} else {
480*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, " failed to find target %s\n\n",
481*de1e4e89SAndroid Build Coastguard Worker 				t->u.user.name);
482*de1e4e89SAndroid Build Coastguard Worker 			return -1;
483*de1e4e89SAndroid Build Coastguard Worker 		}
484*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "\ttarget ");
485*de1e4e89SAndroid Build Coastguard Worker 		m->print(NULL, m->t, 0);
486*de1e4e89SAndroid Build Coastguard Worker 		if (tb[TCA_IPT_INDEX] == NULL) {
487*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, " [NULL ipt target index ]\n");
488*de1e4e89SAndroid Build Coastguard Worker 		} else {
489*de1e4e89SAndroid Build Coastguard Worker 			__u32 index;
490*de1e4e89SAndroid Build Coastguard Worker 
491*de1e4e89SAndroid Build Coastguard Worker 			index = rta_getattr_u32(tb[TCA_IPT_INDEX]);
492*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n\tindex %u", index);
493*de1e4e89SAndroid Build Coastguard Worker 		}
494*de1e4e89SAndroid Build Coastguard Worker 
495*de1e4e89SAndroid Build Coastguard Worker 		if (tb[TCA_IPT_CNT]) {
496*de1e4e89SAndroid Build Coastguard Worker 			struct tc_cnt *c  = RTA_DATA(tb[TCA_IPT_CNT]);
497*de1e4e89SAndroid Build Coastguard Worker 
498*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt);
499*de1e4e89SAndroid Build Coastguard Worker 		}
500*de1e4e89SAndroid Build Coastguard Worker 		if (show_stats) {
501*de1e4e89SAndroid Build Coastguard Worker 			if (tb[TCA_IPT_TM]) {
502*de1e4e89SAndroid Build Coastguard Worker 				struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]);
503*de1e4e89SAndroid Build Coastguard Worker 
504*de1e4e89SAndroid Build Coastguard Worker 				print_tm(f, tm);
505*de1e4e89SAndroid Build Coastguard Worker 			}
506*de1e4e89SAndroid Build Coastguard Worker 		}
507*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "\n");
508*de1e4e89SAndroid Build Coastguard Worker 
509*de1e4e89SAndroid Build Coastguard Worker 	}
510*de1e4e89SAndroid Build Coastguard Worker 	free_opts(opts);
511*de1e4e89SAndroid Build Coastguard Worker 
512*de1e4e89SAndroid Build Coastguard Worker 	return 0;
513*de1e4e89SAndroid Build Coastguard Worker }
514*de1e4e89SAndroid Build Coastguard Worker 
515*de1e4e89SAndroid Build Coastguard Worker struct action_util ipt_action_util = {
516*de1e4e89SAndroid Build Coastguard Worker 	.id = "ipt",
517*de1e4e89SAndroid Build Coastguard Worker 	.parse_aopt = parse_ipt,
518*de1e4e89SAndroid Build Coastguard Worker 	.print_aopt = print_ipt,
519*de1e4e89SAndroid Build Coastguard Worker };
520