K2.6 patches and update.
[tomato.git] / release / src / router / iptables / extensions / libip6t_connbytes.c
blobf86edc562ee9be52b14532e37277e0814743b747
1 /* Shared library add-on to iptables to add byte tracking support. */
2 #include <stdio.h>
3 #include <netdb.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7 #include <ip6tables.h>
8 #include <linux/netfilter/nf_conntrack_common.h>
9 #include <linux/netfilter_ipv6/ip6_tables.h>
10 #include <linux/netfilter_ipv4/ipt_connbytes.h>
12 /* Function which prints out usage message. */
13 static void
14 help(void)
16 printf(
17 "connbytes v%s options:\n"
18 " [!] --connbytes from:[to]\n"
19 " --connbytes-dir [original, reply, both]\n"
20 " --connbytes-mode [packets, bytes, avgpkt]\n"
21 "\n", IPTABLES_VERSION);
24 static struct option opts[] = {
25 { "connbytes", 1, 0, '1' },
26 { "connbytes-dir", 1, 0, '2' },
27 { "connbytes-mode", 1, 0, '3' },
28 {0}
31 static void
32 parse_range(const char *arg, struct ipt_connbytes_info *si)
34 char *colon,*p;
36 si->count.from = strtoul(arg,&colon,10);
37 if (*colon != ':')
38 exit_error(PARAMETER_PROBLEM, "Bad range `%s'", arg);
39 si->count.to = strtoul(colon+1,&p,10);
40 if (p == colon+1) {
41 /* second number omited */
42 si->count.to = 0xffffffff;
44 if (si->count.from > si->count.to)
45 exit_error(PARAMETER_PROBLEM, "%llu should be less than %llu",
46 si->count.from, si->count.to);
49 /* Function which parses command options; returns true if it
50 ate an option */
51 static int
52 parse(int c, char **argv, int invert, unsigned int *flags,
53 const struct ip6t_entry *entry,
54 unsigned int *nfcache,
55 struct ip6t_entry_match **match)
57 struct ipt_connbytes_info *sinfo = (struct ipt_connbytes_info *)(*match)->data;
58 unsigned long i;
60 switch (c) {
61 case '1':
62 if (check_inverse(optarg, &invert, &optind, 0))
63 optind++;
65 parse_range(argv[optind-1], sinfo);
66 if (invert) {
67 i = sinfo->count.from;
68 sinfo->count.from = sinfo->count.to;
69 sinfo->count.to = i;
71 *flags |= 1;
72 break;
73 case '2':
74 if (!strcmp(optarg, "original"))
75 sinfo->direction = IPT_CONNBYTES_DIR_ORIGINAL;
76 else if (!strcmp(optarg, "reply"))
77 sinfo->direction = IPT_CONNBYTES_DIR_REPLY;
78 else if (!strcmp(optarg, "both"))
79 sinfo->direction = IPT_CONNBYTES_DIR_BOTH;
80 else
81 exit_error(PARAMETER_PROBLEM,
82 "Unknown --connbytes-dir `%s'", optarg);
84 *flags |= 2;
85 break;
86 case '3':
87 if (!strcmp(optarg, "packets"))
88 sinfo->what = IPT_CONNBYTES_PKTS;
89 else if (!strcmp(optarg, "bytes"))
90 sinfo->what = IPT_CONNBYTES_BYTES;
91 else if (!strcmp(optarg, "avgpkt"))
92 sinfo->what = IPT_CONNBYTES_AVGPKT;
93 else
94 exit_error(PARAMETER_PROBLEM,
95 "Unknown --connbytes-mode `%s'", optarg);
96 *flags |= 4;
97 break;
98 default:
99 return 0;
102 return 1;
105 static void final_check(unsigned int flags)
107 if (flags != 7)
108 exit_error(PARAMETER_PROBLEM, "You must specify `--connbytes'"
109 "`--connbytes-dir' and `--connbytes-mode'");
112 static void print_mode(struct ipt_connbytes_info *sinfo)
114 switch (sinfo->what) {
115 case IPT_CONNBYTES_PKTS:
116 fputs("packets ", stdout);
117 break;
118 case IPT_CONNBYTES_BYTES:
119 fputs("bytes ", stdout);
120 break;
121 case IPT_CONNBYTES_AVGPKT:
122 fputs("avgpkt ", stdout);
123 break;
124 default:
125 fputs("unknown ", stdout);
126 break;
130 static void print_direction(struct ipt_connbytes_info *sinfo)
132 switch (sinfo->direction) {
133 case IPT_CONNBYTES_DIR_ORIGINAL:
134 fputs("original ", stdout);
135 break;
136 case IPT_CONNBYTES_DIR_REPLY:
137 fputs("reply ", stdout);
138 break;
139 case IPT_CONNBYTES_DIR_BOTH:
140 fputs("both ", stdout);
141 break;
142 default:
143 fputs("unknown ", stdout);
144 break;
148 /* Prints out the matchinfo. */
149 static void
150 print(const struct ip6t_ip6 *ip,
151 const struct ip6t_entry_match *match,
152 int numeric)
154 struct ipt_connbytes_info *sinfo = (struct ipt_connbytes_info *)match->data;
156 if (sinfo->count.from > sinfo->count.to)
157 printf("connbytes ! %llu:%llu ", sinfo->count.to,
158 sinfo->count.from);
159 else
160 printf("connbytes %llu:%llu ",sinfo->count.from,
161 sinfo->count.to);
162 print_mode(sinfo);
164 fputs("direction ", stdout);
165 print_direction(sinfo);
168 /* Saves the matchinfo in parsable form to stdout. */
169 static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
171 struct ipt_connbytes_info *sinfo = (struct ipt_connbytes_info *)match->data;
173 if (sinfo->count.from > sinfo->count.to)
174 printf("! --connbytes %llu:%llu ", sinfo->count.to,
175 sinfo->count.from);
176 else
177 printf("--connbytes %llu:%llu ", sinfo->count.from,
178 sinfo->count.to);
180 fputs("--connbytes-mode ", stdout);
181 print_mode(sinfo);
183 fputs("--connbytes-dir ", stdout);
184 print_direction(sinfo);
187 static struct ip6tables_match state = {
188 .next = NULL,
189 .name = "connbytes",
190 .version = IPTABLES_VERSION,
191 .size = IP6T_ALIGN(sizeof(struct ipt_connbytes_info)),
192 .userspacesize = IP6T_ALIGN(sizeof(struct ipt_connbytes_info)),
193 .help = &help,
194 .parse = &parse,
195 .final_check = &final_check,
196 .print = &print,
197 .save = &save,
198 .extra_opts = opts
201 void _init(void)
203 register_match6(&state);