1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/*
2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * m_ipt.c	iptables 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 <linux/if.h>
18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <iptables.h>
19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/netfilter.h>
20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/netfilter_ipv4/ip_tables.h>
21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "utils.h"
22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "tc_util.h"
23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <linux/tc_act/tc_ipt.h>
24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h>
25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <dlfcn.h>
26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <getopt.h>
27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <errno.h>
28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h>
29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netdb.h>
30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h>
31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <ctype.h>
32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdarg.h>
33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h>
34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h>
35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/wait.h>
36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const char *pname = "tc-ipt";
38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const char *tname = "mangle";
39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const char *pversion = "0.1";
40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const char *ipthooks[] = {
42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	"NF_IP_PRE_ROUTING",
43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	"NF_IP_LOCAL_IN",
44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	"NF_IP_FORWARD",
45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	"NF_IP_LOCAL_OUT",
46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	"NF_IP_POST_ROUTING",
47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct option original_opts[] = {
50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{"jump", 1, 0, 'j'},
51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{0, 0, 0, 0}
52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct iptables_target *t_list = NULL;
55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct option *opts = original_opts;
56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic unsigned int global_option_offset = 0;
57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define OPTION_OFFSET 256
58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar *lib_dir;
60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid
62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatregister_target(struct iptables_target *me)
63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/*      fprintf(stderr, "\nDummy register_target %s \n", me->name);
65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat*/
66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	me->next = t_list;
67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	t_list = me;
68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid
72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatxtables_register_target(struct iptables_target *me)
73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	me->next = t_list;
75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	t_list = me;
76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid
79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatexit_tryhelp(int status)
80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		pname, pname);
83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	exit(status);
84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid
87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatexit_error(enum exittype status, char *msg, ...)
88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	va_list args;
90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	va_start(args, msg);
92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr, "%s v%s: ", pname, pversion);
93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	vfprintf(stderr, msg, args);
94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	va_end(args);
95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr, "\n");
96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (status == PARAMETER_PROBLEM)
97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		exit_tryhelp(status);
98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (status == VERSION_PROBLEM)
99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(stderr,
100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			"Perhaps iptables or your kernel needs to be upgraded.\n");
101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	exit(status);
102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* stolen from iptables 1.2.11
105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San MehatThey should really have them as a library so i can link to them
106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San MehatEmail them next time i remember
107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat*/
108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar *
110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehataddr_to_dotted(const struct in_addr *addrp)
111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	static char buf[20];
113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	const unsigned char *bytep;
114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	bytep = (const unsigned char *) &(addrp->s_addr);
116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return buf;
118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint string_to_number_ll(const char *s, unsigned long long min,
121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			unsigned long long max,
122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		 unsigned long long *ret)
123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	unsigned long long number;
125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *end;
126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* Handle hex, octal, etc. */
128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	errno = 0;
129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	number = strtoull(s, &end, 0);
130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (*end == '\0' && end != s) {
131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		/* we parsed a number, let's see if we want this */
132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (errno != ERANGE && min <= number && (!max || number <= max)) {
133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			*ret = number;
134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return 0;
135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return -1;
138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint string_to_number_l(const char *s, unsigned long min, unsigned long max,
141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		       unsigned long *ret)
142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int result;
144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	unsigned long long number;
145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	result = string_to_number_ll(s, min, max, &number);
147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*ret = (unsigned long)number;
148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return result;
150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint string_to_number(const char *s, unsigned int min, unsigned int max,
153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		unsigned int *ret)
154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int result;
156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	unsigned long number;
157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	result = string_to_number_l(s, min, max, &number);
159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*ret = (unsigned int)number;
160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return result;
162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void free_opts(struct option *local_opts)
165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (local_opts != original_opts) {
167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		free(local_opts);
168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		opts = original_opts;
169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		global_option_offset = 0;
170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct option *
174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatmerge_options(struct option *oldopts, const struct option *newopts,
175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	      unsigned int *option_offset)
176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct option *merge;
178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	unsigned int num_old, num_new, i;
179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (num_old = 0; oldopts[num_old].name; num_old++) ;
181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (num_new = 0; newopts[num_new].name; num_new++) ;
182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*option_offset = global_option_offset + OPTION_OFFSET;
184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	merge = malloc(sizeof (struct option) * (num_new + num_old + 1));
186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	memcpy(merge, oldopts, num_old * sizeof (struct option));
187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (i = 0; i < num_new; i++) {
188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		merge[num_old + i] = newopts[i];
189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		merge[num_old + i].val += *option_offset;
190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	memset(merge + num_old + num_new, 0, sizeof (struct option));
192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return merge;
194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void *
197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatfw_calloc(size_t count, size_t size)
198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	void *p;
200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if ((p = (void *) calloc(count, size)) == NULL) {
202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		perror("iptables: calloc failed");
203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		exit(1);
204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return p;
206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
207dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
208dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct iptables_target *
209dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatfind_t(char *name)
210dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
211dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct iptables_target *m;
212dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (m = t_list; m; m = m->next) {
213dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (strcmp(m->name, name) == 0)
214dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return m;
215dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
216dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
217dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return NULL;
218dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
219dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
220dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct iptables_target *
221dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatget_target_name(const char *name)
222dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
223dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	void *handle;
224dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *error;
225dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *new_name, *lname;
226dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct iptables_target *m;
227dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char path[strlen(lib_dir) + sizeof ("/libipt_.so") + strlen(name)];
228dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
229dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#ifdef NO_SHARED_LIBS
230dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return NULL;
231dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#endif
232dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
233dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	new_name = malloc(strlen(name) + 1);
234dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	lname = malloc(strlen(name) + 1);
235dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (new_name)
236dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memset(new_name, '\0', strlen(name) + 1);
237dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else
238dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		exit_error(PARAMETER_PROBLEM, "get_target_name");
239dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
240dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (lname)
241dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memset(lname, '\0', strlen(name) + 1);
242dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else
243dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		exit_error(PARAMETER_PROBLEM, "get_target_name");
244dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
245dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	strcpy(new_name, name);
246dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	strcpy(lname, name);
247dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
248dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (isupper(lname[0])) {
249dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int i;
250dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		for (i = 0; i < strlen(name); i++) {
251dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			lname[i] = tolower(lname[i]);
252dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
253dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
254dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
255dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (islower(new_name[0])) {
256dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int i;
257dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		for (i = 0; i < strlen(new_name); i++) {
258dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			new_name[i] = toupper(new_name[i]);
259dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
260dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
261dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
262dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* try libxt_xx first */
263dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	sprintf(path, "%s/libxt_%s.so", lib_dir, new_name);
264dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	handle = dlopen(path, RTLD_LAZY);
265dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!handle) {
266dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		/* try libipt_xx next */
267dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		sprintf(path, "%s/libipt_%s.so", lib_dir, new_name);
268dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		handle = dlopen(path, RTLD_LAZY);
269dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
270dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!handle) {
271dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			sprintf(path, "%s/libxt_%s.so", lib_dir , lname);
272dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			handle = dlopen(path, RTLD_LAZY);
273dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
274dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
275dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!handle) {
276dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			sprintf(path, "%s/libipt_%s.so", lib_dir , lname);
277dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			handle = dlopen(path, RTLD_LAZY);
278dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
279dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		/* ok, lets give up .. */
280dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!handle) {
281dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fputs(dlerror(), stderr);
282dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			printf("\n");
283dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			free(new_name);
284dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return NULL;
285dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
286dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
287dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
288dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	m = dlsym(handle, new_name);
289dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if ((error = dlerror()) != NULL) {
290dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		m = (struct iptables_target *) dlsym(handle, lname);
291dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if ((error = dlerror()) != NULL) {
292dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			m = find_t(new_name);
293dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (NULL == m) {
294dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				m = find_t(lname);
295dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (NULL == m) {
296dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					fputs(error, stderr);
297dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					fprintf(stderr, "\n");
298dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					dlclose(handle);
299dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					free(new_name);
300dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					return NULL;
301dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				}
302dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
303dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
304dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
305dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
306dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	free(new_name);
307dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return m;
308dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
309dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
310dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
311dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct in_addr *dotted_to_addr(const char *dotted)
312dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
313dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	static struct in_addr addr;
314dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	unsigned char *addrp;
315dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *p, *q;
316dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	unsigned int onebyte;
317dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int i;
318dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char buf[20];
319dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
320dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* copy dotted string, because we need to modify it */
321dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	strncpy(buf, dotted, sizeof (buf) - 1);
322dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addrp = (unsigned char *) &(addr.s_addr);
323dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
324dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	p = buf;
325dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (i = 0; i < 3; i++) {
326dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if ((q = strchr(p, '.')) == NULL)
327dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return (struct in_addr *) NULL;
328dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
329dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*q = '\0';
330dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (string_to_number(p, 0, 255, &onebyte) == -1)
331dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return (struct in_addr *) NULL;
332dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
333dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		addrp[i] = (unsigned char) onebyte;
334dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		p = q + 1;
335dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
336dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
337dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* we've checked 3 bytes, now we check the last one */
338dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (string_to_number(p, 0, 255, &onebyte) == -1)
339dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return (struct in_addr *) NULL;
340dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
341dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addrp[3] = (unsigned char) onebyte;
342dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
343dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return &addr;
344dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
345dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
346dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void set_revision(char *name, u_int8_t revision)
347dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
348dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* Old kernel sources don't have ".revision" field,
349dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*  but we stole a byte from name. */
350dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	name[IPT_FUNCTION_MAXNAMELEN - 2] = '\0';
351dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	name[IPT_FUNCTION_MAXNAMELEN - 1] = revision;
352dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
353dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
354dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/*
355dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * we may need to check for version mismatch
356dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat*/
357dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint
358dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatbuild_st(struct iptables_target *target, struct ipt_entry_target *t)
359dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
360dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	unsigned int nfcache = 0;
361dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
362dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (target) {
363dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		size_t size;
364dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
365dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		size =
366dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		    IPT_ALIGN(sizeof (struct ipt_entry_target)) + target->size;
367dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
368dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (NULL == t) {
369dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			target->t = fw_calloc(1, size);
370dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			target->t->u.target_size = size;
371dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
372dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (target->init != NULL)
373dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				target->init(target->t, &nfcache);
374dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			set_revision(target->t->u.user.name, target->revision);
375dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else {
376dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			target->t = t;
377dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
378dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		strcpy(target->t->u.user.name, target->name);
379dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return 0;
380dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
381dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
382dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return -1;
383dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
384dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
385dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int parse_ipt(struct action_util *a,int *argc_p,
386dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		     char ***argv_p, int tca_id, struct nlmsghdr *n)
387dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
388dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct iptables_target *m = NULL;
389dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ipt_entry fw;
390dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct rtattr *tail;
391dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int c;
392dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int rargc = *argc_p;
393dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char **argv = *argv_p;
394dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int argc = 0, iargc = 0;
395dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char k[16];
396dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int res = -1;
397dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int size = 0;
398dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int iok = 0, ok = 0;
399dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	__u32 hook = 0, index = 0;
400dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	res = 0;
401dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
402dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	lib_dir = getenv("IPTABLES_LIB_DIR");
403dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!lib_dir)
404dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		lib_dir = IPT_LIB_DIR;
405dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
406dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{
407dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int i;
408dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		for (i = 0; i < rargc; i++) {
409dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) {
410dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				break;
411dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
412dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
413dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		iargc = argc = i;
414dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
415dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
416dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (argc <= 2) {
417dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(stderr,"bad arguements to ipt %d vs %d \n", argc, rargc);
418dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
419dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
420dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
421dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (1) {
422dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		c = getopt_long(argc, argv, "j:", opts, NULL);
423dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (c == -1)
424dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
425dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		switch (c) {
426dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		case 'j':
427dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			m = get_target_name(optarg);
428dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (NULL != m) {
429dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
430dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (0 > build_st(m, NULL)) {
431dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					printf(" %s error \n", m->name);
432dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					return -1;
433dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				}
434dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				opts =
435dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				    merge_options(opts, m->extra_opts,
436dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat						  &m->option_offset);
437dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			} else {
438dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr," failed to find target %s\n\n", optarg);
439dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
440dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
441dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			ok++;
442dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
443dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
444dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		default:
445dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			memset(&fw, 0, sizeof (fw));
446dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (m) {
447dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				m->parse(c - m->option_offset, argv, 0,
448dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					 &m->tflags, NULL, &m->t);
449dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			} else {
450dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr," failed to find target %s\n\n", optarg);
451dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
452dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
453dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
454dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			ok++;
455dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			break;
456dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
457dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
458dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
459dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
460dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (iargc > optind) {
461dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (matches(argv[optind], "index") == 0) {
462dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (get_u32(&index, argv[optind + 1], 10)) {
463dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr, "Illegal \"index\"\n");
464dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				free_opts(opts);
465dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
466dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
467dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			iok++;
468dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
469dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			optind += 2;
470dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
471dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
472dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
473dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!ok && !iok) {
474dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(stderr," ipt Parser BAD!! (%s)\n", *argv);
475dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
476dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
477dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
478dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* check that we passed the correct parameters to the target */
479dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (m)
480dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		m->final_check(m->tflags);
481dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
482dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{
483dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct tcmsg *t = NLMSG_DATA(n);
484dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (t->tcm_parent != TC_H_ROOT
485dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		    && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) {
486dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			hook = NF_IP_PRE_ROUTING;
487dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else {
488dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			hook = NF_IP_POST_ROUTING;
489dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
490dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
491dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
492dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	tail = NLMSG_TAIL(n);
493dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
494dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]);
495dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stdout, "\ttarget: ");
496dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
497dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (m)
498dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		m->print(NULL, m->t, 0);
499dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stdout, " index %d\n", index);
500dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
501dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (strlen(tname) > 16) {
502dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		size = 16;
503dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		k[15] = 0;
504dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
505dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		size = 1 + strlen(tname);
506dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
507dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	strncpy(k, tname, size);
508dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
509dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n, MAX_MSG, TCA_IPT_TABLE, k, size);
510dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n, MAX_MSG, TCA_IPT_HOOK, &hook, 4);
511dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4);
512dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (m)
513dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size);
514dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
515dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
516dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	argc -= optind;
517dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	argv += optind;
518dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*argc_p = rargc - iargc;
519dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*argv_p = argv;
520dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
521dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	optind = 0;
522dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	free_opts(opts);
523dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* Clear flags if target will be used again */
524dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        m->tflags=0;
525dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        m->used=0;
526dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* Free allocated memory */
527dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        if (m->t)
528dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat            free(m->t);
529dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
530dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
531dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
532dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
533dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
534dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
535dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int
536dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatprint_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
537dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
538dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct rtattr *tb[TCA_IPT_MAX + 1];
539dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct ipt_entry_target *t = NULL;
540dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
541dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (arg == NULL)
542dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
543dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
544dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	lib_dir = getenv("IPTABLES_LIB_DIR");
545dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!lib_dir)
546dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		lib_dir = IPT_LIB_DIR;
547dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
548dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	parse_rtattr_nested(tb, TCA_IPT_MAX, arg);
549dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
550dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_IPT_TABLE] == NULL) {
551dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "[NULL ipt table name ] assuming mangle ");
552dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
553dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "tablename: %s ",
554dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			(char *) RTA_DATA(tb[TCA_IPT_TABLE]));
555dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
556dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
557dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_IPT_HOOK] == NULL) {
558dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "[NULL ipt hook name ]\n ");
559dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
560dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
561dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		__u32 hook;
562dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		hook = *(__u32 *) RTA_DATA(tb[TCA_IPT_HOOK]);
563dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, " hook: %s \n", ipthooks[hook]);
564dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
565dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
566dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_IPT_TARG] == NULL) {
567dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "\t[NULL ipt target parameters ] \n");
568dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
569dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
570dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct iptables_target *m = NULL;
571dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		t = RTA_DATA(tb[TCA_IPT_TARG]);
572dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		m = get_target_name(t->u.user.name);
573dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (NULL != m) {
574dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (0 > build_st(m, t)) {
575dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(stderr, " %s error \n", m->name);
576dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
577dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
578dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
579dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			opts =
580dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			    merge_options(opts, m->extra_opts,
581dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					  &m->option_offset);
582dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else {
583dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr, " failed to find target %s\n\n",
584dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				t->u.user.name);
585dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
586dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
587dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, "\ttarget ");
588dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		m->print(NULL, m->t, 0);
589dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (tb[TCA_IPT_INDEX] == NULL) {
590dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(f, " [NULL ipt target index ]\n");
591dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		} else {
592dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			__u32 index;
593dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			index = *(__u32 *) RTA_DATA(tb[TCA_IPT_INDEX]);
594dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(f, " \n\tindex %d", index);
595dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
596dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
597dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (tb[TCA_IPT_CNT]) {
598dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			struct tc_cnt *c  = RTA_DATA(tb[TCA_IPT_CNT]);;
599dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt);
600dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
601dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (show_stats) {
602dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (tb[TCA_IPT_TM]) {
603dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]);
604dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				print_tm(f,tm);
605dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
606dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
607dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, " \n");
608dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
609dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
610dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	free_opts(opts);
611dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
612dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
613dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
614dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
615dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct action_util ipt_action_util = {
616dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        .id = "ipt",
617dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        .parse_aopt = parse_ipt,
618dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat        .print_aopt = print_ipt,
619dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
620dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
621