11ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger/*
2ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger * m_ipt.c	iptables based targets
31ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger * 		utilities mostly ripped from iptables <duh, its the linux way>
41ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger *
51ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger *		This program is free software; you can distribute it and/or
61ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger *		modify it under the terms of the GNU General Public License
71ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger *		as published by the Free Software Foundation; either version
81ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger *		2 of the License, or (at your option) any later version.
91ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger *
10ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger * Authors:  J Hadi Salim (hadi@cyberus.ca)
11de539ecf6cc04530ee88839722be700fd1b0db01Stephen Hemminger */
121ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
131ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <syslog.h>
141ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <sys/socket.h>
151ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <netinet/in.h>
161ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <arpa/inet.h>
17f7cd9b0354c1d60415f5aaddf3e608ca0e546e1bStephen Hemminger#include <linux/if.h>
181ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <iptables.h>
19ece02ea0a388a0bda5e5dff425fe93e50b2d5c9bStephen Hemminger#include <linux/netfilter.h>
201ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <linux/netfilter_ipv4/ip_tables.h>
211ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include "utils.h"
221ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include "tc_util.h"
231ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <linux/tc_act/tc_ipt.h>
241ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <stdio.h>
251ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <dlfcn.h>
261ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <getopt.h>
271ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <errno.h>
281ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <string.h>
291ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <netdb.h>
301ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <stdlib.h>
311ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <ctype.h>
321ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <stdarg.h>
331ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <unistd.h>
341ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <fcntl.h>
351ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#include <sys/wait.h>
361ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3795dd5950491a4f60265494969731c019fcd7f9bcMike Frysingerstatic const char *pname = "tc-ipt";
3895dd5950491a4f60265494969731c019fcd7f9bcMike Frysingerstatic const char *tname = "mangle";
3995dd5950491a4f60265494969731c019fcd7f9bcMike Frysingerstatic const char *pversion = "0.1";
401ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
411ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstatic const char *ipthooks[] = {
421ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	"NF_IP_PRE_ROUTING",
431ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	"NF_IP_LOCAL_IN",
441ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	"NF_IP_FORWARD",
451ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	"NF_IP_LOCAL_OUT",
461ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	"NF_IP_POST_ROUTING",
471ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger};
481ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
491ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstatic struct option original_opts[] = {
501ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	{"jump", 1, 0, 'j'},
511ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	{0, 0, 0, 0}
521ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger};
531ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
541ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstatic struct iptables_target *t_list = NULL;
556d4662d4f7508fa9d247ab0f5a179946722499fcshemmingerstatic struct option *opts = original_opts;
561ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstatic unsigned int global_option_offset = 0;
571ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger#define OPTION_OFFSET 256
581ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
59de539ecf6cc04530ee88839722be700fd1b0db01Stephen Hemmingerchar *lib_dir;
601ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
611ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingervoid
621ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerregister_target(struct iptables_target *me)
631ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
641ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger/*      fprintf(stderr, "\nDummy register_target %s \n", me->name);
651ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger*/
661ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	me->next = t_list;
671ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	t_list = me;
681ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
691ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
701ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
711ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingervoid
7253c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenkoxtables_register_target(struct iptables_target *me)
7353c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko{
7453c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko	me->next = t_list;
7553c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko	t_list = me;
7653c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko}
7753c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko
7853c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenkovoid
791ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerexit_tryhelp(int status)
801ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
811ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
821ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		pname, pname);
831ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	exit(status);
841ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
851ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
861ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingervoid
871ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerexit_error(enum exittype status, char *msg, ...)
881ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
891ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	va_list args;
901ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
911ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	va_start(args, msg);
921ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	fprintf(stderr, "%s v%s: ", pname, pversion);
931ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	vfprintf(stderr, msg, args);
941ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	va_end(args);
951ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	fprintf(stderr, "\n");
961ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (status == PARAMETER_PROBLEM)
971ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		exit_tryhelp(status);
981ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (status == VERSION_PROBLEM)
991ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		fprintf(stderr,
1001ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			"Perhaps iptables or your kernel needs to be upgraded.\n");
1011ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	exit(status);
1021ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
1031ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1041ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger/* stolen from iptables 1.2.11
1051ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerThey should really have them as a library so i can link to them
1061ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerEmail them next time i remember
1071ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger*/
1081ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1091ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerchar *
1101ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingeraddr_to_dotted(const struct in_addr *addrp)
1111ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
1121ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	static char buf[20];
1131ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	const unsigned char *bytep;
1141ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1151ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	bytep = (const unsigned char *) &(addrp->s_addr);
1161ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
1171ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return buf;
1181ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
1191ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
120ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemmingerint string_to_number_ll(const char *s, unsigned long long min,
1211ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			unsigned long long max,
1221ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		 unsigned long long *ret)
1231ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
1241ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	unsigned long long number;
1251ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	char *end;
1261ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1271ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	/* Handle hex, octal, etc. */
1281ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	errno = 0;
1291ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	number = strtoull(s, &end, 0);
1301ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (*end == '\0' && end != s) {
1311ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		/* we parsed a number, let's see if we want this */
1321ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (errno != ERANGE && min <= number && (!max || number <= max)) {
1331ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			*ret = number;
1341ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			return 0;
1351ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
1361ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
1371ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return -1;
1381ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
1391ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1401ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerint string_to_number_l(const char *s, unsigned long min, unsigned long max,
1411ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		       unsigned long *ret)
1421ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
1431ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	int result;
1441ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	unsigned long long number;
1451ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1461ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	result = string_to_number_ll(s, min, max, &number);
1471ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	*ret = (unsigned long)number;
1481ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1491ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return result;
1501ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
1511ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1521ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerint string_to_number(const char *s, unsigned int min, unsigned int max,
1531ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		unsigned int *ret)
1541ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
1551ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	int result;
1561ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	unsigned long number;
1571ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1581ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	result = string_to_number_l(s, min, max, &number);
1591ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	*ret = (unsigned int)number;
1601ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1611ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return result;
1621ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
1631ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
164a589dcda9cc10c8475db18258e6456c1d9c15371Denys Fedoryschenkostatic void free_opts(struct option *local_opts)
1651ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
166a589dcda9cc10c8475db18258e6456c1d9c15371Denys Fedoryschenko	if (local_opts != original_opts) {
167a589dcda9cc10c8475db18258e6456c1d9c15371Denys Fedoryschenko		free(local_opts);
1686d4662d4f7508fa9d247ab0f5a179946722499fcshemminger		opts = original_opts;
1696d4662d4f7508fa9d247ab0f5a179946722499fcshemminger		global_option_offset = 0;
1706d4662d4f7508fa9d247ab0f5a179946722499fcshemminger	}
1711ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
1721ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1731ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstatic struct option *
1741ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingermerge_options(struct option *oldopts, const struct option *newopts,
1751ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	      unsigned int *option_offset)
1761ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
1771ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	struct option *merge;
1781ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	unsigned int num_old, num_new, i;
1791ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1801ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	for (num_old = 0; oldopts[num_old].name; num_old++) ;
1811ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	for (num_new = 0; newopts[num_new].name; num_new++) ;
1821ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1831ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	*option_offset = global_option_offset + OPTION_OFFSET;
1841ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1851ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	merge = malloc(sizeof (struct option) * (num_new + num_old + 1));
1861ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	memcpy(merge, oldopts, num_old * sizeof (struct option));
1871ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	for (i = 0; i < num_new; i++) {
1881ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		merge[num_old + i] = newopts[i];
1891ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		merge[num_old + i].val += *option_offset;
1901ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
1911ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	memset(merge + num_old + num_new, 0, sizeof (struct option));
1921ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1931ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return merge;
1941ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
1951ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
1961ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstatic void *
1971ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerfw_calloc(size_t count, size_t size)
1981ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
1991ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	void *p;
2001ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
2011ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if ((p = (void *) calloc(count, size)) == NULL) {
2021ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		perror("iptables: calloc failed");
2031ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		exit(1);
2041ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
2051ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return p;
2061ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
2071ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
2081ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstatic struct iptables_target *
2091ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerfind_t(char *name)
2101ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
2111ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	struct iptables_target *m;
2121ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	for (m = t_list; m; m = m->next) {
2131ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (strcmp(m->name, name) == 0)
2141ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			return m;
2151ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
2161ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
2171ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return NULL;
2181ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
2191ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
2201ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstatic struct iptables_target *
221de539ecf6cc04530ee88839722be700fd1b0db01Stephen Hemmingerget_target_name(const char *name)
2221ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
2231ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	void *handle;
2241ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	char *error;
2251ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	char *new_name, *lname;
2261ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	struct iptables_target *m;
227de539ecf6cc04530ee88839722be700fd1b0db01Stephen Hemminger	char path[strlen(lib_dir) + sizeof ("/libipt_.so") + strlen(name)];
2281ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
229f2e27cfb016e2465cd3f07e0b556058060702578Mike Frysinger#ifdef NO_SHARED_LIBS
230f2e27cfb016e2465cd3f07e0b556058060702578Mike Frysinger	return NULL;
231f2e27cfb016e2465cd3f07e0b556058060702578Mike Frysinger#endif
232f2e27cfb016e2465cd3f07e0b556058060702578Mike Frysinger
2331ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	new_name = malloc(strlen(name) + 1);
2341ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	lname = malloc(strlen(name) + 1);
2351ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (new_name)
2361ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		memset(new_name, '\0', strlen(name) + 1);
2371ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	else
2381ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		exit_error(PARAMETER_PROBLEM, "get_target_name");
2391ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
2401ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (lname)
2411ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		memset(lname, '\0', strlen(name) + 1);
2421ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	else
2431ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		exit_error(PARAMETER_PROBLEM, "get_target_name");
2441ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
2451ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	strcpy(new_name, name);
2461ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	strcpy(lname, name);
2471ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
2481ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (isupper(lname[0])) {
2491ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		int i;
2501ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		for (i = 0; i < strlen(name); i++) {
2511ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			lname[i] = tolower(lname[i]);
2521ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
2531ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
2541ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
2551ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (islower(new_name[0])) {
2561ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		int i;
2571ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		for (i = 0; i < strlen(new_name); i++) {
2581ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			new_name[i] = toupper(new_name[i]);
2591ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
2601ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
2611ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
26253c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko	/* try libxt_xx first */
26353c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko	sprintf(path, "%s/libxt_%s.so", lib_dir, new_name);
2641ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	handle = dlopen(path, RTLD_LAZY);
2651ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (!handle) {
26653c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko		/* try libipt_xx next */
26753c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko		sprintf(path, "%s/libipt_%s.so", lib_dir, new_name);
2681ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		handle = dlopen(path, RTLD_LAZY);
26953c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko
27053c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko		if (!handle) {
27153c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko			sprintf(path, "%s/libxt_%s.so", lib_dir , lname);
27253c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko			handle = dlopen(path, RTLD_LAZY);
27353c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko		}
27453c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko
27553c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko		if (!handle) {
27653c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko			sprintf(path, "%s/libipt_%s.so", lib_dir , lname);
27753c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko			handle = dlopen(path, RTLD_LAZY);
27853c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko		}
27953c017880b311d7d68926109d4248c900286f6b7Denys Fedoryshchenko		/* ok, lets give up .. */
2801ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (!handle) {
2811ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			fputs(dlerror(), stderr);
2821ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			printf("\n");
2836e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko			free(new_name);
2841a6543c56bead259a44d5d1f288392503eaec292Thomas Jarosch			free(lname);
2851ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			return NULL;
2861ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
2871ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
2881ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
2891ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	m = dlsym(handle, new_name);
2901ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if ((error = dlerror()) != NULL) {
2911ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		m = (struct iptables_target *) dlsym(handle, lname);
2921ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if ((error = dlerror()) != NULL) {
2931ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			m = find_t(new_name);
2941ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			if (NULL == m) {
2951ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				m = find_t(lname);
2961ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				if (NULL == m) {
2971ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger					fputs(error, stderr);
2981ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger					fprintf(stderr, "\n");
2991ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger					dlclose(handle);
3006e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko					free(new_name);
3011a6543c56bead259a44d5d1f288392503eaec292Thomas Jarosch					free(lname);
3021ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger					return NULL;
3031ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				}
3041ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			}
3051ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
3061ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
3071ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3086e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko	free(new_name);
3091a6543c56bead259a44d5d1f288392503eaec292Thomas Jarosch	free(lname);
3101ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return m;
3111ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
3121ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3131ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3141ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstruct in_addr *dotted_to_addr(const char *dotted)
3151ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
3161ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	static struct in_addr addr;
3171ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	unsigned char *addrp;
3181ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	char *p, *q;
3191ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	unsigned int onebyte;
3201ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	int i;
3211ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	char buf[20];
3221ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3231ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	/* copy dotted string, because we need to modify it */
3241ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	strncpy(buf, dotted, sizeof (buf) - 1);
3251ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	addrp = (unsigned char *) &(addr.s_addr);
3261ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3271ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	p = buf;
3281ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	for (i = 0; i < 3; i++) {
3291ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if ((q = strchr(p, '.')) == NULL)
3301ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			return (struct in_addr *) NULL;
3311ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3321ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		*q = '\0';
3331ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (string_to_number(p, 0, 255, &onebyte) == -1)
3341ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			return (struct in_addr *) NULL;
3351ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3361ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		addrp[i] = (unsigned char) onebyte;
3371ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		p = q + 1;
3381ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
3391ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3401ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	/* we've checked 3 bytes, now we check the last one */
3411ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (string_to_number(p, 0, 255, &onebyte) == -1)
3421ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		return (struct in_addr *) NULL;
3431ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3441ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	addrp[3] = (unsigned char) onebyte;
3451ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3461ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return &addr;
3471ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
3481ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
349894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemmingerstatic void set_revision(char *name, u_int8_t revision)
350894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger{
351894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger	/* Old kernel sources don't have ".revision" field,
352894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger	*  but we stole a byte from name. */
353894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger	name[IPT_FUNCTION_MAXNAMELEN - 2] = '\0';
354894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger	name[IPT_FUNCTION_MAXNAMELEN - 1] = revision;
355894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger}
356894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger
357ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger/*
358894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger * we may need to check for version mismatch
359894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger*/
3601ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerint
3611ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerbuild_st(struct iptables_target *target, struct ipt_entry_target *t)
3621ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
3631ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	unsigned int nfcache = 0;
3641ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3651ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (target) {
3661ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		size_t size;
3671ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3681ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		size =
3691ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		    IPT_ALIGN(sizeof (struct ipt_entry_target)) + target->size;
3701ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3711ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (NULL == t) {
3721ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			target->t = fw_calloc(1, size);
3731ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			target->t->u.target_size = size;
374894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger
375894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger			if (target->init != NULL)
376894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger				target->init(target->t, &nfcache);
377894b1c66872ceb943e8e1b8a3c121ce7e9cc2fd9net[shemminger]!shemminger			set_revision(target->t->u.user.name, target->revision);
3781ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		} else {
3791ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			target->t = t;
3801ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
3811ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		strcpy(target->t->u.user.name, target->name);
3821ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		return 0;
3831ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
3841ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
3851ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return -1;
3861ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
3871ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
388ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemmingerstatic int parse_ipt(struct action_util *a,int *argc_p,
3891ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		     char ***argv_p, int tca_id, struct nlmsghdr *n)
3901ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
3911ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	struct iptables_target *m = NULL;
3921ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	struct ipt_entry fw;
3931ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	struct rtattr *tail;
3941ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	int c;
3951ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	int rargc = *argc_p;
3961ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	char **argv = *argv_p;
3971ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	int argc = 0, iargc = 0;
3981ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	char k[16];
3991ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	int size = 0;
4001ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	int iok = 0, ok = 0;
4011ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	__u32 hook = 0, index = 0;
4021ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
403de539ecf6cc04530ee88839722be700fd1b0db01Stephen Hemminger	lib_dir = getenv("IPTABLES_LIB_DIR");
404de539ecf6cc04530ee88839722be700fd1b0db01Stephen Hemminger	if (!lib_dir)
405de539ecf6cc04530ee88839722be700fd1b0db01Stephen Hemminger		lib_dir = IPT_LIB_DIR;
406de539ecf6cc04530ee88839722be700fd1b0db01Stephen Hemminger
4071ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	{
4081ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		int i;
4091ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		for (i = 0; i < rargc; i++) {
4101ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) {
4111ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				break;
4121ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			}
4131ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
4141ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		iargc = argc = i;
4151ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
4161ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4171ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (argc <= 2) {
4181ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		fprintf(stderr,"bad arguements to ipt %d vs %d \n", argc, rargc);
4191ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		return -1;
4201ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
4211ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4221ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	while (1) {
4231ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		c = getopt_long(argc, argv, "j:", opts, NULL);
4241ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (c == -1)
4251ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			break;
4261ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		switch (c) {
4271ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		case 'j':
4281ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			m = get_target_name(optarg);
4291ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			if (NULL != m) {
4301ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4311ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				if (0 > build_st(m, NULL)) {
4321ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger					printf(" %s error \n", m->name);
4331ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger					return -1;
4341ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				}
4351ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				opts =
4361ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				    merge_options(opts, m->extra_opts,
4371ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger						  &m->option_offset);
4381ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			} else {
4391ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				fprintf(stderr," failed to find target %s\n\n", optarg);
4401ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				return -1;
4411ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			}
4421ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			ok++;
4431ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			break;
4441ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4451ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		default:
4461ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			memset(&fw, 0, sizeof (fw));
4471ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			if (m) {
4481ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				m->parse(c - m->option_offset, argv, 0,
4496d4662d4f7508fa9d247ab0f5a179946722499fcshemminger					 &m->tflags, NULL, &m->t);
4501ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			} else {
4511ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				fprintf(stderr," failed to find target %s\n\n", optarg);
4521ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				return -1;
4531ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4541ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			}
4551ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			ok++;
4561ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			break;
4571ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4581ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
4591ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
4601ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4611ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (iargc > optind) {
4621ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (matches(argv[optind], "index") == 0) {
4631ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			if (get_u32(&index, argv[optind + 1], 10)) {
4641ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				fprintf(stderr, "Illegal \"index\"\n");
4656d4662d4f7508fa9d247ab0f5a179946722499fcshemminger				free_opts(opts);
4661ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				return -1;
4671ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			}
4681ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			iok++;
4691ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4701ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			optind += 2;
4711ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
4721ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
4731ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4741ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (!ok && !iok) {
4751ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		fprintf(stderr," ipt Parser BAD!! (%s)\n", *argv);
4761ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		return -1;
4771ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
4781ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4796d4662d4f7508fa9d247ab0f5a179946722499fcshemminger	/* check that we passed the correct parameters to the target */
4806d4662d4f7508fa9d247ab0f5a179946722499fcshemminger	if (m)
4816d4662d4f7508fa9d247ab0f5a179946722499fcshemminger		m->final_check(m->tflags);
4826d4662d4f7508fa9d247ab0f5a179946722499fcshemminger
4831ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	{
4841ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		struct tcmsg *t = NLMSG_DATA(n);
4851ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (t->tcm_parent != TC_H_ROOT
4861ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		    && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) {
4871ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			hook = NF_IP_PRE_ROUTING;
4881ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		} else {
4891ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			hook = NF_IP_POST_ROUTING;
4901ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
4911ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
4921ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
493fc78a8e98dcb8efad64b06dc65716d97fc99b307n);	tail = NLMSG_TAIL(n);
4941ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
4951ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]);
4961ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	fprintf(stdout, "\ttarget: ");
4971ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
4981ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (m)
4991ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		m->print(NULL, m->t, 0);
5001ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	fprintf(stdout, " index %d\n", index);
5011ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5021ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (strlen(tname) > 16) {
5031ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		size = 16;
5041ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		k[15] = 0;
5051ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	} else {
5061ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		size = 1 + strlen(tname);
5071ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
5081ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	strncpy(k, tname, size);
5091ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5101ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	addattr_l(n, MAX_MSG, TCA_IPT_TABLE, k, size);
5111ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	addattr_l(n, MAX_MSG, TCA_IPT_HOOK, &hook, 4);
5121ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4);
5131ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (m)
5141ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size);
515fc78a8e98dcb8efad64b06dc65716d97fc99b307void *) NLMSG_TAIL(n) - (void *) tail;	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
5161ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5171ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	argc -= optind;
5181ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	argv += optind;
5191ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	*argc_p = rargc - iargc;
5201ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	*argv_p = argv;
521ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
5226e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko	optind = 0;
5236d4662d4f7508fa9d247ab0f5a179946722499fcshemminger	free_opts(opts);
5246e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko	/* Clear flags if target will be used again */
5256e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko        m->tflags=0;
5266e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko        m->used=0;
5276e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko	/* Free allocated memory */
5286e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko        if (m->t)
5296e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko            free(m->t);
5306e34e7dc0ae01176f1c2a2fa2e6310b0e04ae204Denys Fedoryshchenko
5311ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5321ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return 0;
5331ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5341ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
5351ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5361ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstatic int
5371ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerprint_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
5381ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger{
5391ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	struct rtattr *tb[TCA_IPT_MAX + 1];
5401ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	struct ipt_entry_target *t = NULL;
5411ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5421ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (arg == NULL)
5431ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		return -1;
5441ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
545c6ab5b824714fd89a5799c91ddbee975c3c84f75Patrick McHardy	lib_dir = getenv("IPTABLES_LIB_DIR");
546c6ab5b824714fd89a5799c91ddbee975c3c84f75Patrick McHardy	if (!lib_dir)
547c6ab5b824714fd89a5799c91ddbee975c3c84f75Patrick McHardy		lib_dir = IPT_LIB_DIR;
548c6ab5b824714fd89a5799c91ddbee975c3c84f75Patrick McHardy
54978934000777e1f1837450ed6bfe738df1fde5a03tb, TCA_IPT_MAX, arg);	parse_rtattr_nested(tb, TCA_IPT_MAX, arg);
5501ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5511ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (tb[TCA_IPT_TABLE] == NULL) {
5521ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		fprintf(f, "[NULL ipt table name ] assuming mangle ");
5531ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	} else {
5541ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		fprintf(f, "tablename: %s ",
555ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			rta_getattr_str(tb[TCA_IPT_TABLE]));
5561ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
5571ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5581ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (tb[TCA_IPT_HOOK] == NULL) {
5591ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		fprintf(f, "[NULL ipt hook name ]\n ");
5601ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		return -1;
5611ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	} else {
5621ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		__u32 hook;
563ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger		hook = rta_getattr_u32(tb[TCA_IPT_HOOK]);
5641ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		fprintf(f, " hook: %s \n", ipthooks[hook]);
5651ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
5661ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5671ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	if (tb[TCA_IPT_TARG] == NULL) {
5681ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		fprintf(f, "\t[NULL ipt target parameters ] \n");
5691ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		return -1;
5701ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	} else {
5711ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		struct iptables_target *m = NULL;
5721ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		t = RTA_DATA(tb[TCA_IPT_TARG]);
5731ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		m = get_target_name(t->u.user.name);
5741ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (NULL != m) {
5751ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			if (0 > build_st(m, t)) {
5761ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				fprintf(stderr, " %s error \n", m->name);
5771ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				return -1;
5781ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			}
5791ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5801ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			opts =
5811ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			    merge_options(opts, m->extra_opts,
5821ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger					  &m->option_offset);
5831ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		} else {
5841ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			fprintf(stderr, " failed to find target %s\n\n",
5851ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				t->u.user.name);
5861ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			return -1;
5871ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
5881ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		fprintf(f, "\ttarget ");
5891ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		m->print(NULL, m->t, 0);
5901ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (tb[TCA_IPT_INDEX] == NULL) {
5911ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			fprintf(f, " [NULL ipt target index ]\n");
5921ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		} else {
5931ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			__u32 index;
594ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			index = rta_getattr_u32(tb[TCA_IPT_INDEX]);
5951ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			fprintf(f, " \n\tindex %d", index);
5961ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
5971ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
5981ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (tb[TCA_IPT_CNT]) {
5991ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			struct tc_cnt *c  = RTA_DATA(tb[TCA_IPT_CNT]);;
6001ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			fprintf(f, " ref %d bind %d", c->refcnt, c->bindcnt);
6011ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		}
6021ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		if (show_stats) {
6031ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			if (tb[TCA_IPT_TM]) {
6041ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				struct tcf_t *tm = RTA_DATA(tb[TCA_IPT_TM]);
6051ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger				print_tm(f,tm);
6061ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger			}
607ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger		}
6081ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger		fprintf(f, " \n");
6091ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
6101ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	}
6116d4662d4f7508fa9d247ab0f5a179946722499fcshemminger	free_opts(opts);
6121ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
6131ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger	return 0;
6141ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger}
6151ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
6161ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemmingerstruct action_util ipt_action_util = {
6171ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger        .id = "ipt",
6181ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger        .parse_aopt = parse_ipt,
6191ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger        .print_aopt = print_ipt,
6201ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger};
6211ffd7fd23eeaff57eb3b83b9dbbbda89ddf030e3net[shemminger]!shemminger
622