1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * m_xt.c xtables 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 /*XXX: in the future (xtables 1.4.3?) get rid of everything tagged
14*de1e4e89SAndroid Build Coastguard Worker * as TC_CONFIG_XT_H */
15*de1e4e89SAndroid Build Coastguard Worker
16*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <net/if.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <linux/netfilter.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <linux/netfilter_ipv4/ip_tables.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <xtables.h>
24*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
25*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
26*de1e4e89SAndroid Build Coastguard Worker #include <linux/tc_act/tc_ipt.h>
27*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
28*de1e4e89SAndroid Build Coastguard Worker #include <getopt.h>
29*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
30*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
31*de1e4e89SAndroid Build Coastguard Worker #include <netdb.h>
32*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
33*de1e4e89SAndroid Build Coastguard Worker #include <ctype.h>
34*de1e4e89SAndroid Build Coastguard Worker #include <stdarg.h>
35*de1e4e89SAndroid Build Coastguard Worker #include <limits.h>
36*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
37*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
38*de1e4e89SAndroid Build Coastguard Worker #include <sys/wait.h>
39*de1e4e89SAndroid Build Coastguard Worker #ifdef TC_CONFIG_XT_H
40*de1e4e89SAndroid Build Coastguard Worker #include "xt-internal.h"
41*de1e4e89SAndroid Build Coastguard Worker #endif
42*de1e4e89SAndroid Build Coastguard Worker
43*de1e4e89SAndroid Build Coastguard Worker #ifndef ALIGN
44*de1e4e89SAndroid Build Coastguard Worker #define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
45*de1e4e89SAndroid Build Coastguard Worker #define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
46*de1e4e89SAndroid Build Coastguard Worker #endif
47*de1e4e89SAndroid Build Coastguard Worker
48*de1e4e89SAndroid Build Coastguard Worker static const char *pname = "tc-ipt";
49*de1e4e89SAndroid Build Coastguard Worker static const char *tname = "mangle";
50*de1e4e89SAndroid Build Coastguard Worker static const char *pversion = "0.2";
51*de1e4e89SAndroid Build Coastguard Worker
52*de1e4e89SAndroid Build Coastguard Worker static const char *ipthooks[] = {
53*de1e4e89SAndroid Build Coastguard Worker "NF_IP_PRE_ROUTING",
54*de1e4e89SAndroid Build Coastguard Worker "NF_IP_LOCAL_IN",
55*de1e4e89SAndroid Build Coastguard Worker "NF_IP_FORWARD",
56*de1e4e89SAndroid Build Coastguard Worker "NF_IP_LOCAL_OUT",
57*de1e4e89SAndroid Build Coastguard Worker "NF_IP_POST_ROUTING",
58*de1e4e89SAndroid Build Coastguard Worker };
59*de1e4e89SAndroid Build Coastguard Worker
60*de1e4e89SAndroid Build Coastguard Worker static struct option original_opts[] = {
61*de1e4e89SAndroid Build Coastguard Worker {"jump", 1, 0, 'j'},
62*de1e4e89SAndroid Build Coastguard Worker {0, 0, 0, 0}
63*de1e4e89SAndroid Build Coastguard Worker };
64*de1e4e89SAndroid Build Coastguard Worker
65*de1e4e89SAndroid Build Coastguard Worker static struct option *opts = original_opts;
66*de1e4e89SAndroid Build Coastguard Worker static unsigned int global_option_offset;
67*de1e4e89SAndroid Build Coastguard Worker char *lib_dir;
68*de1e4e89SAndroid Build Coastguard Worker const char *program_version = XTABLES_VERSION;
69*de1e4e89SAndroid Build Coastguard Worker const char *program_name = "tc-ipt";
70*de1e4e89SAndroid Build Coastguard Worker struct afinfo afinfo = {
71*de1e4e89SAndroid Build Coastguard Worker .family = AF_INET,
72*de1e4e89SAndroid Build Coastguard Worker .libprefix = "libxt_",
73*de1e4e89SAndroid Build Coastguard Worker .ipproto = IPPROTO_IP,
74*de1e4e89SAndroid Build Coastguard Worker .kmod = "ip_tables",
75*de1e4e89SAndroid Build Coastguard Worker .so_rev_target = IPT_SO_GET_REVISION_TARGET,
76*de1e4e89SAndroid Build Coastguard Worker };
77*de1e4e89SAndroid Build Coastguard Worker
78*de1e4e89SAndroid Build Coastguard Worker
79*de1e4e89SAndroid Build Coastguard Worker #define OPTION_OFFSET 256
80*de1e4e89SAndroid Build Coastguard Worker
81*de1e4e89SAndroid Build Coastguard Worker /*XXX: TC_CONFIG_XT_H */
free_opts(struct option * local_opts)82*de1e4e89SAndroid Build Coastguard Worker static void free_opts(struct option *local_opts)
83*de1e4e89SAndroid Build Coastguard Worker {
84*de1e4e89SAndroid Build Coastguard Worker if (local_opts != original_opts) {
85*de1e4e89SAndroid Build Coastguard Worker free(local_opts);
86*de1e4e89SAndroid Build Coastguard Worker opts = original_opts;
87*de1e4e89SAndroid Build Coastguard Worker global_option_offset = 0;
88*de1e4e89SAndroid Build Coastguard Worker }
89*de1e4e89SAndroid Build Coastguard Worker }
90*de1e4e89SAndroid Build Coastguard Worker
91*de1e4e89SAndroid Build Coastguard Worker /*XXX: TC_CONFIG_XT_H */
92*de1e4e89SAndroid Build Coastguard Worker static struct option *
merge_options(struct option * oldopts,const struct option * newopts,unsigned int * option_offset)93*de1e4e89SAndroid Build Coastguard Worker merge_options(struct option *oldopts, const struct option *newopts,
94*de1e4e89SAndroid Build Coastguard Worker unsigned int *option_offset)
95*de1e4e89SAndroid Build Coastguard Worker {
96*de1e4e89SAndroid Build Coastguard Worker struct option *merge;
97*de1e4e89SAndroid Build Coastguard Worker unsigned int num_old, num_new, i;
98*de1e4e89SAndroid Build Coastguard Worker
99*de1e4e89SAndroid Build Coastguard Worker for (num_old = 0; oldopts[num_old].name; num_old++);
100*de1e4e89SAndroid Build Coastguard Worker for (num_new = 0; newopts[num_new].name; num_new++);
101*de1e4e89SAndroid Build Coastguard Worker
102*de1e4e89SAndroid Build Coastguard Worker *option_offset = global_option_offset + OPTION_OFFSET;
103*de1e4e89SAndroid Build Coastguard Worker
104*de1e4e89SAndroid Build Coastguard Worker merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
105*de1e4e89SAndroid Build Coastguard Worker memcpy(merge, oldopts, num_old * sizeof(struct option));
106*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < num_new; i++) {
107*de1e4e89SAndroid Build Coastguard Worker merge[num_old + i] = newopts[i];
108*de1e4e89SAndroid Build Coastguard Worker merge[num_old + i].val += *option_offset;
109*de1e4e89SAndroid Build Coastguard Worker }
110*de1e4e89SAndroid Build Coastguard Worker memset(merge + num_old + num_new, 0, sizeof(struct option));
111*de1e4e89SAndroid Build Coastguard Worker
112*de1e4e89SAndroid Build Coastguard Worker return merge;
113*de1e4e89SAndroid Build Coastguard Worker }
114*de1e4e89SAndroid Build Coastguard Worker
115*de1e4e89SAndroid Build Coastguard Worker
116*de1e4e89SAndroid Build Coastguard Worker /*XXX: TC_CONFIG_XT_H */
117*de1e4e89SAndroid Build Coastguard Worker #ifndef TRUE
118*de1e4e89SAndroid Build Coastguard Worker #define TRUE 1
119*de1e4e89SAndroid Build Coastguard Worker #endif
120*de1e4e89SAndroid Build Coastguard Worker #ifndef FALSE
121*de1e4e89SAndroid Build Coastguard Worker #define FALSE 0
122*de1e4e89SAndroid Build Coastguard Worker #endif
123*de1e4e89SAndroid Build Coastguard Worker
124*de1e4e89SAndroid Build Coastguard Worker /*XXX: TC_CONFIG_XT_H */
125*de1e4e89SAndroid Build Coastguard Worker int
check_inverse(const char option[],int * invert,int * my_optind,int argc)126*de1e4e89SAndroid Build Coastguard Worker check_inverse(const char option[], int *invert, int *my_optind, int argc)
127*de1e4e89SAndroid Build Coastguard Worker {
128*de1e4e89SAndroid Build Coastguard Worker if (option && strcmp(option, "!") == 0) {
129*de1e4e89SAndroid Build Coastguard Worker if (*invert)
130*de1e4e89SAndroid Build Coastguard Worker exit_error(PARAMETER_PROBLEM,
131*de1e4e89SAndroid Build Coastguard Worker "Multiple `!' flags not allowed");
132*de1e4e89SAndroid Build Coastguard Worker *invert = TRUE;
133*de1e4e89SAndroid Build Coastguard Worker if (my_optind != NULL) {
134*de1e4e89SAndroid Build Coastguard Worker ++*my_optind;
135*de1e4e89SAndroid Build Coastguard Worker if (argc && *my_optind > argc)
136*de1e4e89SAndroid Build Coastguard Worker exit_error(PARAMETER_PROBLEM,
137*de1e4e89SAndroid Build Coastguard Worker "no argument following `!'");
138*de1e4e89SAndroid Build Coastguard Worker }
139*de1e4e89SAndroid Build Coastguard Worker
140*de1e4e89SAndroid Build Coastguard Worker return TRUE;
141*de1e4e89SAndroid Build Coastguard Worker }
142*de1e4e89SAndroid Build Coastguard Worker return FALSE;
143*de1e4e89SAndroid Build Coastguard Worker }
144*de1e4e89SAndroid Build Coastguard Worker
145*de1e4e89SAndroid Build Coastguard Worker /*XXX: TC_CONFIG_XT_H */
exit_error(enum exittype status,const char * msg,...)146*de1e4e89SAndroid Build Coastguard Worker void exit_error(enum exittype status, const char *msg, ...)
147*de1e4e89SAndroid Build Coastguard Worker {
148*de1e4e89SAndroid Build Coastguard Worker va_list args;
149*de1e4e89SAndroid Build Coastguard Worker
150*de1e4e89SAndroid Build Coastguard Worker va_start(args, msg);
151*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s v%s: ", pname, pversion);
152*de1e4e89SAndroid Build Coastguard Worker vfprintf(stderr, msg, args);
153*de1e4e89SAndroid Build Coastguard Worker va_end(args);
154*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\n");
155*de1e4e89SAndroid Build Coastguard Worker /* On error paths, make sure that we don't leak memory */
156*de1e4e89SAndroid Build Coastguard Worker exit(status);
157*de1e4e89SAndroid Build Coastguard Worker }
158*de1e4e89SAndroid Build Coastguard Worker
159*de1e4e89SAndroid Build Coastguard Worker /*XXX: TC_CONFIG_XT_H */
set_revision(char * name,u_int8_t revision)160*de1e4e89SAndroid Build Coastguard Worker static void set_revision(char *name, u_int8_t revision)
161*de1e4e89SAndroid Build Coastguard Worker {
162*de1e4e89SAndroid Build Coastguard Worker /* Old kernel sources don't have ".revision" field,
163*de1e4e89SAndroid Build Coastguard Worker * but we stole a byte from name. */
164*de1e4e89SAndroid Build Coastguard Worker name[IPT_FUNCTION_MAXNAMELEN - 2] = '\0';
165*de1e4e89SAndroid Build Coastguard Worker name[IPT_FUNCTION_MAXNAMELEN - 1] = revision;
166*de1e4e89SAndroid Build Coastguard Worker }
167*de1e4e89SAndroid Build Coastguard Worker
168*de1e4e89SAndroid Build Coastguard Worker /*
169*de1e4e89SAndroid Build Coastguard Worker * we may need to check for version mismatch
170*de1e4e89SAndroid Build Coastguard Worker */
171*de1e4e89SAndroid Build Coastguard Worker int
build_st(struct xtables_target * target,struct xt_entry_target * t)172*de1e4e89SAndroid Build Coastguard Worker build_st(struct xtables_target *target, struct xt_entry_target *t)
173*de1e4e89SAndroid Build Coastguard Worker {
174*de1e4e89SAndroid Build Coastguard Worker
175*de1e4e89SAndroid Build Coastguard Worker size_t size =
176*de1e4e89SAndroid Build Coastguard Worker XT_ALIGN(sizeof(struct xt_entry_target)) + target->size;
177*de1e4e89SAndroid Build Coastguard Worker
178*de1e4e89SAndroid Build Coastguard Worker if (t == NULL) {
179*de1e4e89SAndroid Build Coastguard Worker target->t = fw_calloc(1, size);
180*de1e4e89SAndroid Build Coastguard Worker target->t->u.target_size = size;
181*de1e4e89SAndroid Build Coastguard Worker strcpy(target->t->u.user.name, target->name);
182*de1e4e89SAndroid Build Coastguard Worker set_revision(target->t->u.user.name, target->revision);
183*de1e4e89SAndroid Build Coastguard Worker
184*de1e4e89SAndroid Build Coastguard Worker if (target->init != NULL)
185*de1e4e89SAndroid Build Coastguard Worker target->init(target->t);
186*de1e4e89SAndroid Build Coastguard Worker } else {
187*de1e4e89SAndroid Build Coastguard Worker target->t = t;
188*de1e4e89SAndroid Build Coastguard Worker }
189*de1e4e89SAndroid Build Coastguard Worker return 0;
190*de1e4e89SAndroid Build Coastguard Worker
191*de1e4e89SAndroid Build Coastguard Worker }
192*de1e4e89SAndroid Build Coastguard Worker
set_lib_dir(void)193*de1e4e89SAndroid Build Coastguard Worker inline void set_lib_dir(void)
194*de1e4e89SAndroid Build Coastguard Worker {
195*de1e4e89SAndroid Build Coastguard Worker
196*de1e4e89SAndroid Build Coastguard Worker lib_dir = getenv("XTABLES_LIBDIR");
197*de1e4e89SAndroid Build Coastguard Worker if (!lib_dir) {
198*de1e4e89SAndroid Build Coastguard Worker lib_dir = getenv("IPTABLES_LIB_DIR");
199*de1e4e89SAndroid Build Coastguard Worker if (lib_dir)
200*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "using deprecated IPTABLES_LIB_DIR\n");
201*de1e4e89SAndroid Build Coastguard Worker }
202*de1e4e89SAndroid Build Coastguard Worker if (lib_dir == NULL)
203*de1e4e89SAndroid Build Coastguard Worker lib_dir = XT_LIB_DIR;
204*de1e4e89SAndroid Build Coastguard Worker
205*de1e4e89SAndroid Build Coastguard Worker }
206*de1e4e89SAndroid Build Coastguard Worker
parse_ipt(struct action_util * a,int * argc_p,char *** argv_p,int tca_id,struct nlmsghdr * n)207*de1e4e89SAndroid Build Coastguard Worker static int parse_ipt(struct action_util *a, int *argc_p,
208*de1e4e89SAndroid Build Coastguard Worker char ***argv_p, int tca_id, struct nlmsghdr *n)
209*de1e4e89SAndroid Build Coastguard Worker {
210*de1e4e89SAndroid Build Coastguard Worker struct xtables_target *m = NULL;
211*de1e4e89SAndroid Build Coastguard Worker struct ipt_entry fw;
212*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tail;
213*de1e4e89SAndroid Build Coastguard Worker int c;
214*de1e4e89SAndroid Build Coastguard Worker int rargc = *argc_p;
215*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
216*de1e4e89SAndroid Build Coastguard Worker int argc = 0, iargc = 0;
217*de1e4e89SAndroid Build Coastguard Worker char k[16];
218*de1e4e89SAndroid Build Coastguard Worker int size = 0;
219*de1e4e89SAndroid Build Coastguard Worker int iok = 0, ok = 0;
220*de1e4e89SAndroid Build Coastguard Worker __u32 hook = 0, index = 0;
221*de1e4e89SAndroid Build Coastguard Worker
222*de1e4e89SAndroid Build Coastguard Worker set_lib_dir();
223*de1e4e89SAndroid Build Coastguard Worker
224*de1e4e89SAndroid Build Coastguard Worker {
225*de1e4e89SAndroid Build Coastguard Worker int i;
226*de1e4e89SAndroid Build Coastguard Worker
227*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < rargc; i++) {
228*de1e4e89SAndroid Build Coastguard Worker if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) {
229*de1e4e89SAndroid Build Coastguard Worker break;
230*de1e4e89SAndroid Build Coastguard Worker }
231*de1e4e89SAndroid Build Coastguard Worker }
232*de1e4e89SAndroid Build Coastguard Worker iargc = argc = i;
233*de1e4e89SAndroid Build Coastguard Worker }
234*de1e4e89SAndroid Build Coastguard Worker
235*de1e4e89SAndroid Build Coastguard Worker if (argc <= 2) {
236*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "bad arguments to ipt %d vs %d\n", argc, rargc);
237*de1e4e89SAndroid Build Coastguard Worker return -1;
238*de1e4e89SAndroid Build Coastguard Worker }
239*de1e4e89SAndroid Build Coastguard Worker
240*de1e4e89SAndroid Build Coastguard Worker while (1) {
241*de1e4e89SAndroid Build Coastguard Worker c = getopt_long(argc, argv, "j:", opts, NULL);
242*de1e4e89SAndroid Build Coastguard Worker if (c == -1)
243*de1e4e89SAndroid Build Coastguard Worker break;
244*de1e4e89SAndroid Build Coastguard Worker switch (c) {
245*de1e4e89SAndroid Build Coastguard Worker case 'j':
246*de1e4e89SAndroid Build Coastguard Worker m = find_target(optarg, TRY_LOAD);
247*de1e4e89SAndroid Build Coastguard Worker if (m != NULL) {
248*de1e4e89SAndroid Build Coastguard Worker
249*de1e4e89SAndroid Build Coastguard Worker if (build_st(m, NULL) < 0) {
250*de1e4e89SAndroid Build Coastguard Worker printf(" %s error\n", m->name);
251*de1e4e89SAndroid Build Coastguard Worker return -1;
252*de1e4e89SAndroid Build Coastguard Worker }
253*de1e4e89SAndroid Build Coastguard Worker opts =
254*de1e4e89SAndroid Build Coastguard Worker merge_options(opts, m->extra_opts,
255*de1e4e89SAndroid Build Coastguard Worker &m->option_offset);
256*de1e4e89SAndroid Build Coastguard Worker } else {
257*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " failed to find target %s\n\n", optarg);
258*de1e4e89SAndroid Build Coastguard Worker return -1;
259*de1e4e89SAndroid Build Coastguard Worker }
260*de1e4e89SAndroid Build Coastguard Worker ok++;
261*de1e4e89SAndroid Build Coastguard Worker break;
262*de1e4e89SAndroid Build Coastguard Worker
263*de1e4e89SAndroid Build Coastguard Worker default:
264*de1e4e89SAndroid Build Coastguard Worker memset(&fw, 0, sizeof(fw));
265*de1e4e89SAndroid Build Coastguard Worker if (m) {
266*de1e4e89SAndroid Build Coastguard Worker m->parse(c - m->option_offset, argv, 0,
267*de1e4e89SAndroid Build Coastguard Worker &m->tflags, NULL, &m->t);
268*de1e4e89SAndroid Build Coastguard Worker } else {
269*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " failed to find target %s\n\n", optarg);
270*de1e4e89SAndroid Build Coastguard Worker return -1;
271*de1e4e89SAndroid Build Coastguard Worker
272*de1e4e89SAndroid Build Coastguard Worker }
273*de1e4e89SAndroid Build Coastguard Worker ok++;
274*de1e4e89SAndroid Build Coastguard Worker break;
275*de1e4e89SAndroid Build Coastguard Worker
276*de1e4e89SAndroid Build Coastguard Worker }
277*de1e4e89SAndroid Build Coastguard Worker }
278*de1e4e89SAndroid Build Coastguard Worker
279*de1e4e89SAndroid Build Coastguard Worker if (iargc > optind) {
280*de1e4e89SAndroid Build Coastguard Worker if (matches(argv[optind], "index") == 0) {
281*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&index, argv[optind + 1], 10)) {
282*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"index\"\n");
283*de1e4e89SAndroid Build Coastguard Worker free_opts(opts);
284*de1e4e89SAndroid Build Coastguard Worker return -1;
285*de1e4e89SAndroid Build Coastguard Worker }
286*de1e4e89SAndroid Build Coastguard Worker iok++;
287*de1e4e89SAndroid Build Coastguard Worker
288*de1e4e89SAndroid Build Coastguard Worker optind += 2;
289*de1e4e89SAndroid Build Coastguard Worker }
290*de1e4e89SAndroid Build Coastguard Worker }
291*de1e4e89SAndroid Build Coastguard Worker
292*de1e4e89SAndroid Build Coastguard Worker if (!ok && !iok) {
293*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ipt Parser BAD!! (%s)\n", *argv);
294*de1e4e89SAndroid Build Coastguard Worker return -1;
295*de1e4e89SAndroid Build Coastguard Worker }
296*de1e4e89SAndroid Build Coastguard Worker
297*de1e4e89SAndroid Build Coastguard Worker /* check that we passed the correct parameters to the target */
298*de1e4e89SAndroid Build Coastguard Worker if (m)
299*de1e4e89SAndroid Build Coastguard Worker m->final_check(m->tflags);
300*de1e4e89SAndroid Build Coastguard Worker
301*de1e4e89SAndroid Build Coastguard Worker {
302*de1e4e89SAndroid Build Coastguard Worker struct tcmsg *t = NLMSG_DATA(n);
303*de1e4e89SAndroid Build Coastguard Worker
304*de1e4e89SAndroid Build Coastguard Worker if (t->tcm_parent != TC_H_ROOT
305*de1e4e89SAndroid Build Coastguard Worker && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) {
306*de1e4e89SAndroid Build Coastguard Worker hook = NF_IP_PRE_ROUTING;
307*de1e4e89SAndroid Build Coastguard Worker } else {
308*de1e4e89SAndroid Build Coastguard Worker hook = NF_IP_POST_ROUTING;
309*de1e4e89SAndroid Build Coastguard Worker }
310*de1e4e89SAndroid Build Coastguard Worker }
311*de1e4e89SAndroid Build Coastguard Worker
312*de1e4e89SAndroid Build Coastguard Worker tail = NLMSG_TAIL(n);
313*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, tca_id, NULL, 0);
314*de1e4e89SAndroid Build Coastguard Worker fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]);
315*de1e4e89SAndroid Build Coastguard Worker fprintf(stdout, "\ttarget: ");
316*de1e4e89SAndroid Build Coastguard Worker
317*de1e4e89SAndroid Build Coastguard Worker if (m)
318*de1e4e89SAndroid Build Coastguard Worker m->print(NULL, m->t, 0);
319*de1e4e89SAndroid Build Coastguard Worker fprintf(stdout, " index %d\n", index);
320*de1e4e89SAndroid Build Coastguard Worker
321*de1e4e89SAndroid Build Coastguard Worker if (strlen(tname) > 16) {
322*de1e4e89SAndroid Build Coastguard Worker size = 16;
323*de1e4e89SAndroid Build Coastguard Worker k[15] = 0;
324*de1e4e89SAndroid Build Coastguard Worker } else {
325*de1e4e89SAndroid Build Coastguard Worker size = 1 + strlen(tname);
326*de1e4e89SAndroid Build Coastguard Worker }
327*de1e4e89SAndroid Build Coastguard Worker strncpy(k, tname, size);
328*de1e4e89SAndroid Build Coastguard Worker
329*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_IPT_TABLE, k, size);
330*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_IPT_HOOK, &hook, 4);
331*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4);
332*de1e4e89SAndroid Build Coastguard Worker if (m)
333*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size);
334*de1e4e89SAndroid Build Coastguard Worker tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
335*de1e4e89SAndroid Build Coastguard Worker
336*de1e4e89SAndroid Build Coastguard Worker argc -= optind;
337*de1e4e89SAndroid Build Coastguard Worker argv += optind;
338*de1e4e89SAndroid Build Coastguard Worker *argc_p = rargc - iargc;
339*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
340*de1e4e89SAndroid Build Coastguard Worker
341*de1e4e89SAndroid Build Coastguard Worker optind = 0;
342*de1e4e89SAndroid Build Coastguard Worker free_opts(opts);
343*de1e4e89SAndroid Build Coastguard Worker /* Clear flags if target will be used again */
344*de1e4e89SAndroid Build Coastguard Worker m->tflags = 0;
345*de1e4e89SAndroid Build Coastguard Worker m->used = 0;
346*de1e4e89SAndroid Build Coastguard Worker /* Free allocated memory */
347*de1e4e89SAndroid Build Coastguard Worker if (m->t)
348*de1e4e89SAndroid Build Coastguard Worker free(m->t);
349*de1e4e89SAndroid Build Coastguard Worker
350*de1e4e89SAndroid Build Coastguard Worker
351*de1e4e89SAndroid Build Coastguard Worker return 0;
352*de1e4e89SAndroid Build Coastguard Worker
353*de1e4e89SAndroid Build Coastguard Worker }
354*de1e4e89SAndroid Build Coastguard Worker
355*de1e4e89SAndroid Build Coastguard Worker static int
print_ipt(struct action_util * au,FILE * f,struct rtattr * arg)356*de1e4e89SAndroid Build Coastguard Worker print_ipt(struct action_util *au, FILE * f, struct rtattr *arg)
357*de1e4e89SAndroid Build Coastguard Worker {
358*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[TCA_IPT_MAX + 1];
359*de1e4e89SAndroid Build Coastguard Worker struct xt_entry_target *t = NULL;
360*de1e4e89SAndroid Build Coastguard Worker
361*de1e4e89SAndroid Build Coastguard Worker if (arg == NULL)
362*de1e4e89SAndroid Build Coastguard Worker return -1;
363*de1e4e89SAndroid Build Coastguard Worker
364*de1e4e89SAndroid Build Coastguard Worker set_lib_dir();
365*de1e4e89SAndroid Build Coastguard Worker
366*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(tb, TCA_IPT_MAX, arg);
367*de1e4e89SAndroid Build Coastguard Worker
368*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_IPT_TABLE] == NULL) {
369*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "[NULL ipt table name ] assuming mangle ");
370*de1e4e89SAndroid Build Coastguard Worker } else {
371*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "tablename: %s ",
372*de1e4e89SAndroid Build Coastguard Worker rta_getattr_str(tb[TCA_IPT_TABLE]));
373*de1e4e89SAndroid Build Coastguard Worker }
374*de1e4e89SAndroid Build Coastguard Worker
375*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_IPT_HOOK] == NULL) {
376*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "[NULL ipt hook name ]\n ");
377*de1e4e89SAndroid Build Coastguard Worker return -1;
378*de1e4e89SAndroid Build Coastguard Worker } else {
379*de1e4e89SAndroid Build Coastguard Worker __u32 hook;
380*de1e4e89SAndroid Build Coastguard Worker
381*de1e4e89SAndroid Build Coastguard Worker hook = rta_getattr_u32(tb[TCA_IPT_HOOK]);
382*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " hook: %s\n", ipthooks[hook]);
383*de1e4e89SAndroid Build Coastguard Worker }
384*de1e4e89SAndroid Build Coastguard Worker
385*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_IPT_TARG] == NULL) {
386*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\t[NULL ipt target parameters ]\n");
387*de1e4e89SAndroid Build Coastguard Worker return -1;
388*de1e4e89SAndroid Build Coastguard Worker } else {
389*de1e4e89SAndroid Build Coastguard Worker struct xtables_target *m = NULL;
390*de1e4e89SAndroid Build Coastguard Worker
391*de1e4e89SAndroid Build Coastguard Worker t = RTA_DATA(tb[TCA_IPT_TARG]);
392*de1e4e89SAndroid Build Coastguard Worker m = find_target(t->u.user.name, TRY_LOAD);
393*de1e4e89SAndroid Build Coastguard Worker if (m != NULL) {
394*de1e4e89SAndroid Build Coastguard Worker if (build_st(m, t) < 0) {
395*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " %s error\n", m->name);
396*de1e4e89SAndroid Build Coastguard Worker return -1;
397*de1e4e89SAndroid Build Coastguard Worker }
398*de1e4e89SAndroid Build Coastguard Worker
399*de1e4e89SAndroid Build Coastguard Worker opts =
400*de1e4e89SAndroid Build Coastguard Worker merge_options(opts, m->extra_opts,
401*de1e4e89SAndroid Build Coastguard Worker &m->option_offset);
402*de1e4e89SAndroid Build Coastguard Worker } else {
403*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " failed to find target %s\n\n",
404*de1e4e89SAndroid Build Coastguard Worker t->u.user.name);
405*de1e4e89SAndroid Build Coastguard Worker return -1;
406*de1e4e89SAndroid Build Coastguard Worker }
407*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\ttarget ");
408*de1e4e89SAndroid Build Coastguard Worker m->print(NULL, m->t, 0);
409*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_IPT_INDEX] == NULL) {
410*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " [NULL ipt target index ]\n");
411*de1e4e89SAndroid Build Coastguard Worker } else {
412*de1e4e89SAndroid Build Coastguard Worker __u32 index;
413*de1e4e89SAndroid Build Coastguard Worker
414*de1e4e89SAndroid Build Coastguard Worker index = rta_getattr_u32(tb[TCA_IPT_INDEX]);
415*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n\tindex %u", index);
416*de1e4e89SAndroid Build Coastguard Worker }
417*de1e4e89SAndroid Build Coastguard Worker
418*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_IPT_CNT]) {
419*de1e4e89SAndroid Build Coastguard Worker struct tc_cnt *c = RTA_DATA(tb[TCA_IPT_CNT]);
420*de1e4e89SAndroid Build Coastguard Worker
421*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt);
422*de1e4e89SAndroid Build Coastguard Worker }
423*de1e4e89SAndroid Build Coastguard Worker if (show_stats) {
424*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_IPT_TM]) {
425*de1e4e89SAndroid Build Coastguard Worker struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]);
426*de1e4e89SAndroid Build Coastguard Worker
427*de1e4e89SAndroid Build Coastguard Worker print_tm(f, tm);
428*de1e4e89SAndroid Build Coastguard Worker }
429*de1e4e89SAndroid Build Coastguard Worker }
430*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n");
431*de1e4e89SAndroid Build Coastguard Worker
432*de1e4e89SAndroid Build Coastguard Worker }
433*de1e4e89SAndroid Build Coastguard Worker free_opts(opts);
434*de1e4e89SAndroid Build Coastguard Worker
435*de1e4e89SAndroid Build Coastguard Worker return 0;
436*de1e4e89SAndroid Build Coastguard Worker }
437*de1e4e89SAndroid Build Coastguard Worker
438*de1e4e89SAndroid Build Coastguard Worker struct action_util ipt_action_util = {
439*de1e4e89SAndroid Build Coastguard Worker .id = "ipt",
440*de1e4e89SAndroid Build Coastguard Worker .parse_aopt = parse_ipt,
441*de1e4e89SAndroid Build Coastguard Worker .print_aopt = print_ipt,
442*de1e4e89SAndroid Build Coastguard Worker };
443