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