blob: b77ba38b1edb403cec89ad21fa2e39d9cee56484 [file] [log] [blame]
Martin Devera766113a2003-06-19 12:23:37 +00001/* 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>
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +00007#include <xtables.h>
Patrick McHardy40d54752007-04-18 07:00:36 +00008#include <linux/netfilter/nf_conntrack_common.h>
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +00009#include <linux/netfilter/xt_connbytes.h>
Martin Devera766113a2003-06-19 12:23:37 +000010
Jan Engelhardt181dead2007-10-04 16:27:07 +000011static void connbytes_help(void)
Martin Devera766113a2003-06-19 12:23:37 +000012{
13 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020014"connbytes match options:\n"
Martin Devera766113a2003-06-19 12:23:37 +000015" [!] --connbytes from:[to]\n"
Harald Welte93f4a3d2004-11-18 22:50:01 +000016" --connbytes-dir [original, reply, both]\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020017" --connbytes-mode [packets, bytes, avgpkt]\n");
Martin Devera766113a2003-06-19 12:23:37 +000018}
19
Jan Engelhardt181dead2007-10-04 16:27:07 +000020static const struct option connbytes_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000021 { "connbytes", 1, NULL, '1' },
22 { "connbytes-dir", 1, NULL, '2' },
23 { "connbytes-mode", 1, NULL, '3' },
Max Kellermann9ee386a2008-01-29 13:48:05 +000024 { .name = NULL }
Martin Devera766113a2003-06-19 12:23:37 +000025};
26
Martin Devera766113a2003-06-19 12:23:37 +000027static void
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +000028parse_range(const char *arg, struct xt_connbytes_info *si)
Martin Devera766113a2003-06-19 12:23:37 +000029{
30 char *colon,*p;
31
Harald Welte7dc57e22004-11-18 22:59:36 +000032 si->count.from = strtoul(arg,&colon,10);
Martin Devera766113a2003-06-19 12:23:37 +000033 if (*colon != ':')
34 exit_error(PARAMETER_PROBLEM, "Bad range `%s'", arg);
Harald Welte7dc57e22004-11-18 22:59:36 +000035 si->count.to = strtoul(colon+1,&p,10);
Martin Devera766113a2003-06-19 12:23:37 +000036 if (p == colon+1) {
37 /* second number omited */
Harald Welte7dc57e22004-11-18 22:59:36 +000038 si->count.to = 0xffffffff;
Martin Devera766113a2003-06-19 12:23:37 +000039 }
Harald Welte7dc57e22004-11-18 22:59:36 +000040 if (si->count.from > si->count.to)
41 exit_error(PARAMETER_PROBLEM, "%llu should be less than %llu",
Patrick McHardyc329d6a2007-09-05 14:19:23 +000042 (unsigned long long)si->count.from,
43 (unsigned long long)si->count.to);
Martin Devera766113a2003-06-19 12:23:37 +000044}
45
Martin Devera766113a2003-06-19 12:23:37 +000046static int
Jan Engelhardt181dead2007-10-04 16:27:07 +000047connbytes_parse(int c, char **argv, int invert, unsigned int *flags,
48 const void *entry, struct xt_entry_match **match)
Martin Devera766113a2003-06-19 12:23:37 +000049{
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +000050 struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)(*match)->data;
Martin Josefsson11460882004-05-08 14:02:36 +000051 unsigned long i;
Martin Devera766113a2003-06-19 12:23:37 +000052
53 switch (c) {
54 case '1':
Harald Welte7dc57e22004-11-18 22:59:36 +000055 if (check_inverse(optarg, &invert, &optind, 0))
Martin Devera766113a2003-06-19 12:23:37 +000056 optind++;
57
58 parse_range(argv[optind-1], sinfo);
59 if (invert) {
Harald Welte93f4a3d2004-11-18 22:50:01 +000060 i = sinfo->count.from;
Harald Welte7dc57e22004-11-18 22:59:36 +000061 sinfo->count.from = sinfo->count.to;
Harald Welte93f4a3d2004-11-18 22:50:01 +000062 sinfo->count.to = i;
Martin Devera766113a2003-06-19 12:23:37 +000063 }
Harald Welte93f4a3d2004-11-18 22:50:01 +000064 *flags |= 1;
Martin Devera766113a2003-06-19 12:23:37 +000065 break;
Harald Welte93f4a3d2004-11-18 22:50:01 +000066 case '2':
67 if (!strcmp(optarg, "original"))
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +000068 sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL;
Harald Welte93f4a3d2004-11-18 22:50:01 +000069 else if (!strcmp(optarg, "reply"))
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +000070 sinfo->direction = XT_CONNBYTES_DIR_REPLY;
Harald Welte93f4a3d2004-11-18 22:50:01 +000071 else if (!strcmp(optarg, "both"))
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +000072 sinfo->direction = XT_CONNBYTES_DIR_BOTH;
Harald Welte93f4a3d2004-11-18 22:50:01 +000073 else
74 exit_error(PARAMETER_PROBLEM,
75 "Unknown --connbytes-dir `%s'", optarg);
Martin Devera766113a2003-06-19 12:23:37 +000076
Harald Welte93f4a3d2004-11-18 22:50:01 +000077 *flags |= 2;
78 break;
79 case '3':
Harald Welte7dc57e22004-11-18 22:59:36 +000080 if (!strcmp(optarg, "packets"))
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +000081 sinfo->what = XT_CONNBYTES_PKTS;
Harald Welte93f4a3d2004-11-18 22:50:01 +000082 else if (!strcmp(optarg, "bytes"))
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +000083 sinfo->what = XT_CONNBYTES_BYTES;
Harald Welte93f4a3d2004-11-18 22:50:01 +000084 else if (!strcmp(optarg, "avgpkt"))
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +000085 sinfo->what = XT_CONNBYTES_AVGPKT;
Harald Welte93f4a3d2004-11-18 22:50:01 +000086 else
87 exit_error(PARAMETER_PROBLEM,
88 "Unknown --connbytes-mode `%s'", optarg);
89 *flags |= 4;
Piotrek Kaczmarek1c0f2362005-04-24 16:19:51 +000090 break;
Martin Devera766113a2003-06-19 12:23:37 +000091 default:
92 return 0;
93 }
94
95 return 1;
96}
97
Jan Engelhardt181dead2007-10-04 16:27:07 +000098static void connbytes_check(unsigned int flags)
Martin Devera766113a2003-06-19 12:23:37 +000099{
Harald Welte93f4a3d2004-11-18 22:50:01 +0000100 if (flags != 7)
101 exit_error(PARAMETER_PROBLEM, "You must specify `--connbytes'"
Harald Welte402c3112005-12-05 12:08:03 +0000102 "`--connbytes-dir' and `--connbytes-mode'");
Harald Welte93f4a3d2004-11-18 22:50:01 +0000103}
104
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000105static void print_mode(struct xt_connbytes_info *sinfo)
Harald Welte93f4a3d2004-11-18 22:50:01 +0000106{
107 switch (sinfo->what) {
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000108 case XT_CONNBYTES_PKTS:
Harald Welte93f4a3d2004-11-18 22:50:01 +0000109 fputs("packets ", stdout);
110 break;
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000111 case XT_CONNBYTES_BYTES:
Harald Welte93f4a3d2004-11-18 22:50:01 +0000112 fputs("bytes ", stdout);
113 break;
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000114 case XT_CONNBYTES_AVGPKT:
Harald Welte93f4a3d2004-11-18 22:50:01 +0000115 fputs("avgpkt ", stdout);
116 break;
Harald Welte7dc57e22004-11-18 22:59:36 +0000117 default:
Harald Welte93f4a3d2004-11-18 22:50:01 +0000118 fputs("unknown ", stdout);
Harald Welte7dc57e22004-11-18 22:59:36 +0000119 break;
Harald Welte93f4a3d2004-11-18 22:50:01 +0000120 }
121}
122
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000123static void print_direction(struct xt_connbytes_info *sinfo)
Harald Welte93f4a3d2004-11-18 22:50:01 +0000124{
125 switch (sinfo->direction) {
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000126 case XT_CONNBYTES_DIR_ORIGINAL:
Harald Welte7dc57e22004-11-18 22:59:36 +0000127 fputs("original ", stdout);
Harald Welte93f4a3d2004-11-18 22:50:01 +0000128 break;
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000129 case XT_CONNBYTES_DIR_REPLY:
Harald Welte7dc57e22004-11-18 22:59:36 +0000130 fputs("reply ", stdout);
Harald Welte93f4a3d2004-11-18 22:50:01 +0000131 break;
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000132 case XT_CONNBYTES_DIR_BOTH:
Harald Welte7dc57e22004-11-18 22:59:36 +0000133 fputs("both ", stdout);
134 break;
135 default:
136 fputs("unknown ", stdout);
Harald Welte93f4a3d2004-11-18 22:50:01 +0000137 break;
138 }
Martin Devera766113a2003-06-19 12:23:37 +0000139}
140
Martin Devera766113a2003-06-19 12:23:37 +0000141static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000142connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric)
Martin Devera766113a2003-06-19 12:23:37 +0000143{
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000144 struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)match->data;
Martin Devera766113a2003-06-19 12:23:37 +0000145
Harald Welte7dc57e22004-11-18 22:59:36 +0000146 if (sinfo->count.from > sinfo->count.to)
Patrick McHardyc329d6a2007-09-05 14:19:23 +0000147 printf("connbytes ! %llu:%llu ",
148 (unsigned long long)sinfo->count.to,
149 (unsigned long long)sinfo->count.from);
Martin Devera766113a2003-06-19 12:23:37 +0000150 else
Patrick McHardyc329d6a2007-09-05 14:19:23 +0000151 printf("connbytes %llu:%llu ",
152 (unsigned long long)sinfo->count.from,
153 (unsigned long long)sinfo->count.to);
Harald Welte93f4a3d2004-11-18 22:50:01 +0000154
155 fputs("connbytes mode ", stdout);
156 print_mode(sinfo);
157
158 fputs("connbytes direction ", stdout);
159 print_direction(sinfo);
Martin Devera766113a2003-06-19 12:23:37 +0000160}
161
Jan Engelhardt181dead2007-10-04 16:27:07 +0000162static void connbytes_save(const void *ip, const struct xt_entry_match *match)
Martin Devera766113a2003-06-19 12:23:37 +0000163{
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000164 struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)match->data;
Martin Devera766113a2003-06-19 12:23:37 +0000165
Harald Welte93f4a3d2004-11-18 22:50:01 +0000166 if (sinfo->count.from > sinfo->count.to)
Patrick McHardyc329d6a2007-09-05 14:19:23 +0000167 printf("! --connbytes %llu:%llu ",
168 (unsigned long long)sinfo->count.to,
169 (unsigned long long)sinfo->count.from);
Martin Devera766113a2003-06-19 12:23:37 +0000170 else
Patrick McHardyc329d6a2007-09-05 14:19:23 +0000171 printf("--connbytes %llu:%llu ",
172 (unsigned long long)sinfo->count.from,
173 (unsigned long long)sinfo->count.to);
Harald Welte93f4a3d2004-11-18 22:50:01 +0000174
175 fputs("--connbytes-mode ", stdout);
176 print_mode(sinfo);
177
Harald Welte402c3112005-12-05 12:08:03 +0000178 fputs("--connbytes-dir ", stdout);
Harald Welte93f4a3d2004-11-18 22:50:01 +0000179 print_direction(sinfo);
Martin Devera766113a2003-06-19 12:23:37 +0000180}
181
Jan Engelhardt181dead2007-10-04 16:27:07 +0000182static struct xtables_match connbytes_match = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100183 .family = NFPROTO_IPV4,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000184 .name = "connbytes",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200185 .version = XTABLES_VERSION,
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000186 .size = XT_ALIGN(sizeof(struct xt_connbytes_info)),
187 .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000188 .help = connbytes_help,
189 .parse = connbytes_parse,
190 .final_check = connbytes_check,
191 .print = connbytes_print,
192 .save = connbytes_save,
193 .extra_opts = connbytes_opts,
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000194};
195
Jan Engelhardt181dead2007-10-04 16:27:07 +0000196static struct xtables_match connbytes_match6 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100197 .family = NFPROTO_IPV6,
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000198 .name = "connbytes",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200199 .version = XTABLES_VERSION,
Yasuyuki KOZAKAI6aac5002007-08-04 08:25:43 +0000200 .size = XT_ALIGN(sizeof(struct xt_connbytes_info)),
201 .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000202 .help = connbytes_help,
203 .parse = connbytes_parse,
204 .final_check = connbytes_check,
205 .print = connbytes_print,
206 .save = connbytes_save,
207 .extra_opts = connbytes_opts,
Martin Devera766113a2003-06-19 12:23:37 +0000208};
209
210void _init(void)
211{
Jan Engelhardt181dead2007-10-04 16:27:07 +0000212 xtables_register_match(&connbytes_match);
213 xtables_register_match(&connbytes_match6);
Martin Devera766113a2003-06-19 12:23:37 +0000214}