1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/*
2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * m_xt.c	xtables based targets
3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 		utilities mostly ripped from iptables <duh, its the linux way>
4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		This program is free software; you can distribute it and/or
6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		modify it under the terms of the GNU General Public License
7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		as published by the Free Software Foundation; either version
8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		2 of the License, or (at your option) any later version.
9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Authors:  J Hadi Salim (hadi@cyberus.ca)
11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */
12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <syslog.h>
14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h>
15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netinet/in.h>
16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <arpa/inet.h>
17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <net/if.h>
18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <limits.h>
19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/netfilter.h>
20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/netfilter_ipv4/ip_tables.h>
21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <xtables.h>
22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "utils.h"
23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "tc_util.h"
24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/tc_act/tc_ipt.h>
25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h>
26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <dlfcn.h>
27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <getopt.h>
28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <errno.h>
29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h>
30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netdb.h>
31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h>
32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <ctype.h>
33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdarg.h>
34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <limits.h>
35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h>
36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h>
37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/wait.h>
38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#ifndef XT_LIB_DIR
39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#       define XT_LIB_DIR "/lib/xtables"
40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#endif
41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
421a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#ifndef ALIGN
431a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#define ALIGN(x,a)		__ALIGN_MASK(x,(typeof(x))(a)-1)
441a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#define __ALIGN_MASK(x,mask)	(((x)+(mask))&~(mask))
451a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#endif
461a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const char *tname = "mangle";
48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar *lib_dir;
50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const char *ipthooks[] = {
52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	"NF_IP_PRE_ROUTING",
53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	"NF_IP_LOCAL_IN",
54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	"NF_IP_FORWARD",
55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	"NF_IP_LOCAL_OUT",
56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	"NF_IP_POST_ROUTING",
57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct option original_opts[] = {
60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{
61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		.name = "jump",
62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		.has_arg = 1,
63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		.val = 'j'
64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	},
65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{0, 0, 0, 0}
66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct xtables_globals tcipt_globals = {
69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.option_offset = 0,
70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.program_name = "tc-ipt",
71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.program_version = "0.2",
72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.orig_opts = original_opts,
73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.opts = original_opts,
74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.exit_err = NULL,
75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/*
78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * we may need to check for version mismatch
79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat*/
80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint
81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatbuild_st(struct xtables_target *target, struct xt_entry_target *t)
82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	size_t size =
85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		    XT_ALIGN(sizeof (struct xt_entry_target)) + target->size;
86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (NULL == t) {
88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		target->t = xtables_calloc(1, size);
89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		target->t->u.target_size = size;
90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		strcpy(target->t->u.user.name, target->name);
91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		xtables_set_revision(target->t->u.user.name, target->revision);
92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (target->init != NULL)
94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			target->init(target->t);
95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		target->t = t;
97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatinline void set_lib_dir(void)
103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	lib_dir = getenv("XTABLES_LIBDIR");
106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!lib_dir) {
107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		lib_dir = getenv("IPTABLES_LIB_DIR");
108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (lib_dir)
109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr, "using deprecated IPTABLES_LIB_DIR \n");
110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (lib_dir == NULL)
112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		lib_dir = XT_LIB_DIR;
113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int parse_ipt(struct action_util *a,int *argc_p,
117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		     char ***argv_p, int tca_id, struct nlmsghdr *n)
118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct xtables_target *m = NULL;
120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ipt_entry fw;
121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct rtattr *tail;
122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int c;
123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int rargc = *argc_p;
124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char **argv = *argv_p;
125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int argc = 0, iargc = 0;
126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char k[16];
127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int res = -1;
128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int size = 0;
129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int iok = 0, ok = 0;
130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	__u32 hook = 0, index = 0;
131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	res = 0;
132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	xtables_init_all(&tcipt_globals, NFPROTO_IPV4);
134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	set_lib_dir();
135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{
137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int i;
138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		for (i = 0; i < rargc; i++) {
139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) {
140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				break;
141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		iargc = argc = i;
144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (argc <= 2) {
147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(stderr,"bad arguements to ipt %d vs %d \n", argc, rargc);
148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (1) {
152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		c = getopt_long(argc, argv, "j:", tcipt_globals.opts, NULL);
153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (c == -1)
154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		switch (c) {
156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'j':
157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			m = xtables_find_target(optarg, XTF_TRY_LOAD);
158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (NULL != m) {
159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (0 > build_st(m, NULL)) {
161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					printf(" %s error \n", m->name);
162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					return -1;
163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				}
164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				tcipt_globals.opts =
165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				    xtables_merge_options(tcipt_globals.opts,
166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				                          m->extra_opts,
167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				                          &m->option_offset);
168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			} else {
169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr," failed to find target %s\n\n", optarg);
170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			ok++;
173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		default:
176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			memset(&fw, 0, sizeof (fw));
177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (m) {
178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				m->parse(c - m->option_offset, argv, 0,
179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					 &m->tflags, NULL, &m->t);
180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			} else {
181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr," failed to find target %s\n\n", optarg);
182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			ok++;
186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (iargc > optind) {
192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (matches(argv[optind], "index") == 0) {
193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (get_u32(&index, argv[optind + 1], 10)) {
194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr, "Illegal \"index\"\n");
195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				xtables_free_opts(1);
196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			iok++;
199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			optind += 2;
201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!ok && !iok) {
205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(stderr," ipt Parser BAD!! (%s)\n", *argv);
206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
207dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
208dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
209dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* check that we passed the correct parameters to the target */
210dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (m && m->final_check)
211dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		m->final_check(m->tflags);
212dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
213dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{
214dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct tcmsg *t = NLMSG_DATA(n);
215dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (t->tcm_parent != TC_H_ROOT
216dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		    && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) {
217dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			hook = NF_IP_PRE_ROUTING;
218dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else {
219dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			hook = NF_IP_POST_ROUTING;
220dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
221dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
222dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
223dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	tail = NLMSG_TAIL(n);
224dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
225dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]);
226dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stdout, "\ttarget: ");
227dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
228dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (m)
229dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		m->print(NULL, m->t, 0);
230dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stdout, " index %d\n", index);
231dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
232dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (strlen(tname) > 16) {
233dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		size = 16;
234dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		k[15] = 0;
235dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
236dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		size = 1 + strlen(tname);
237dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
238dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	strncpy(k, tname, size);
239dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
240dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n, MAX_MSG, TCA_IPT_TABLE, k, size);
241dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n, MAX_MSG, TCA_IPT_HOOK, &hook, 4);
242dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4);
243dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (m)
244dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size);
245dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
246dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
247dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	argc -= optind;
248dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	argv += optind;
249dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*argc_p = rargc - iargc;
250dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*argv_p = argv;
251dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
252dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	optind = 0;
253dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	xtables_free_opts(1);
254dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* Clear flags if target will be used again */
255dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        m->tflags=0;
256dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        m->used=0;
257dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* Free allocated memory */
258dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        if (m->t)
259dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat            free(m->t);
260dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
261dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
262dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
263dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
264dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
265dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
266dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int
267dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatprint_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
268dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
269dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct rtattr *tb[TCA_IPT_MAX + 1];
270dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct xt_entry_target *t = NULL;
271dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
272dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (arg == NULL)
273dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
274dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
275dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	xtables_init_all(&tcipt_globals, NFPROTO_IPV4);
276dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	set_lib_dir();
277dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
278dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	parse_rtattr_nested(tb, TCA_IPT_MAX, arg);
279dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
280dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_IPT_TABLE] == NULL) {
281dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "[NULL ipt table name ] assuming mangle ");
282dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
283dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "tablename: %s ",
284dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			(char *) RTA_DATA(tb[TCA_IPT_TABLE]));
285dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
286dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
287dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_IPT_HOOK] == NULL) {
288dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "[NULL ipt hook name ]\n ");
289dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
290dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
291dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		__u32 hook;
292dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		hook = *(__u32 *) RTA_DATA(tb[TCA_IPT_HOOK]);
293dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, " hook: %s \n", ipthooks[hook]);
294dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
295dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
296dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_IPT_TARG] == NULL) {
297dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "\t[NULL ipt target parameters ] \n");
298dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
299dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
300dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct xtables_target *m = NULL;
301dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		t = RTA_DATA(tb[TCA_IPT_TARG]);
302dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		m = xtables_find_target(t->u.user.name, XTF_TRY_LOAD);
303dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (NULL != m) {
304dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (0 > build_st(m, t)) {
305dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr, " %s error \n", m->name);
306dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
307dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
308dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
309dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			tcipt_globals.opts =
310dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			    xtables_merge_options(tcipt_globals.opts,
311dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			                          m->extra_opts,
312dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			                          &m->option_offset);
313dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else {
314dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr, " failed to find target %s\n\n",
315dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				t->u.user.name);
316dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
317dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
318dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "\ttarget ");
319dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		m->print(NULL, m->t, 0);
320dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (tb[TCA_IPT_INDEX] == NULL) {
321dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(f, " [NULL ipt target index ]\n");
322dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else {
323dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			__u32 index;
324dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			index = *(__u32 *) RTA_DATA(tb[TCA_IPT_INDEX]);
325dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(f, " \n\tindex %d", index);
326dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
327dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
328dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (tb[TCA_IPT_CNT]) {
329dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			struct tc_cnt *c  = RTA_DATA(tb[TCA_IPT_CNT]);;
330dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt);
331dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
332dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (show_stats) {
333dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (tb[TCA_IPT_TM]) {
334dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]);
335dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				print_tm(f,tm);
336dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
337dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
338dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, " \n");
339dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
340dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
341dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	xtables_free_opts(1);
342dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
343dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
344dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
345dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
346dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct action_util ipt_action_util = {
347dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        .id = "ipt",
348dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        .parse_aopt = parse_ipt,
349dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        .print_aopt = print_ipt,
350dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
351dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
352