1 /* Shared library add-on to iptables to add byte tracking support. */
8 #include <linux/netfilter/nf_conntrack_common.h>
9 #include <linux/netfilter/xt_connbytes.h>
11 /* Function which prints out usage message. */
12 static void connbytes_help(void)
15 "connbytes match options:\n"
16 " [!] --connbytes from:[to]\n"
17 " --connbytes-dir [original, reply, both]\n"
18 " --connbytes-mode [packets, bytes, avgpkt]\n");
21 static const struct option connbytes_opts[] = {
22 { "connbytes", 1, NULL, '1' },
23 { "connbytes-dir", 1, NULL, '2' },
24 { "connbytes-mode", 1, NULL, '3' },
29 parse_range(const char *arg, struct xt_connbytes_info *si)
33 si->count.from = strtoul(arg,&colon,10);
35 exit_error(PARAMETER_PROBLEM, "Bad range `%s'", arg);
36 si->count.to = strtoul(colon+1,&p,10);
38 /* second number omited */
39 si->count.to = 0xffffffff;
41 if (si->count.from > si->count.to)
42 exit_error(PARAMETER_PROBLEM, "%llu should be less than %llu",
43 (unsigned long long)si->count.from,
44 (unsigned long long)si->count.to);
47 /* Function which parses command options; returns true if it
50 connbytes_parse(int c, char **argv, int invert, unsigned int *flags,
51 const void *entry, struct xt_entry_match **match)
53 struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)(*match)->data;
58 if (check_inverse(optarg, &invert, &optind, 0))
61 parse_range(argv[optind-1], sinfo);
63 i = sinfo->count.from;
64 sinfo->count.from = sinfo->count.to;
70 if (!strcmp(optarg, "original"))
71 sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL;
72 else if (!strcmp(optarg, "reply"))
73 sinfo->direction = XT_CONNBYTES_DIR_REPLY;
74 else if (!strcmp(optarg, "both"))
75 sinfo->direction = XT_CONNBYTES_DIR_BOTH;
77 exit_error(PARAMETER_PROBLEM,
78 "Unknown --connbytes-dir `%s'", optarg);
83 if (!strcmp(optarg, "packets"))
84 sinfo->what = XT_CONNBYTES_PKTS;
85 else if (!strcmp(optarg, "bytes"))
86 sinfo->what = XT_CONNBYTES_BYTES;
87 else if (!strcmp(optarg, "avgpkt"))
88 sinfo->what = XT_CONNBYTES_AVGPKT;
90 exit_error(PARAMETER_PROBLEM,
91 "Unknown --connbytes-mode `%s'", optarg);
101 static void connbytes_check(unsigned int flags)
104 exit_error(PARAMETER_PROBLEM, "You must specify `--connbytes'"
105 "`--connbytes-dir' and `--connbytes-mode'");
108 static void print_mode(struct xt_connbytes_info *sinfo)
110 switch (sinfo->what) {
111 case XT_CONNBYTES_PKTS:
112 fputs("packets ", stdout);
114 case XT_CONNBYTES_BYTES:
115 fputs("bytes ", stdout);
117 case XT_CONNBYTES_AVGPKT:
118 fputs("avgpkt ", stdout);
121 fputs("unknown ", stdout);
126 static void print_direction(struct xt_connbytes_info *sinfo)
128 switch (sinfo->direction) {
129 case XT_CONNBYTES_DIR_ORIGINAL:
130 fputs("original ", stdout);
132 case XT_CONNBYTES_DIR_REPLY:
133 fputs("reply ", stdout);
135 case XT_CONNBYTES_DIR_BOTH:
136 fputs("both ", stdout);
139 fputs("unknown ", stdout);
144 /* Prints out the matchinfo. */
146 connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric)
148 struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)match->data;
150 if (sinfo->count.from > sinfo->count.to)
151 printf("connbytes ! %llu:%llu ",
152 (unsigned long long)sinfo->count.to,
153 (unsigned long long)sinfo->count.from);
155 printf("connbytes %llu:%llu ",
156 (unsigned long long)sinfo->count.from,
157 (unsigned long long)sinfo->count.to);
159 fputs("connbytes mode ", stdout);
162 fputs("connbytes direction ", stdout);
163 print_direction(sinfo);
166 /* Saves the matchinfo in parsable form to stdout. */
167 static void connbytes_save(const void *ip, const struct xt_entry_match *match)
169 struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)match->data;
171 if (sinfo->count.from > sinfo->count.to)
172 printf("! --connbytes %llu:%llu ",
173 (unsigned long long)sinfo->count.to,
174 (unsigned long long)sinfo->count.from);
176 printf("--connbytes %llu:%llu ",
177 (unsigned long long)sinfo->count.from,
178 (unsigned long long)sinfo->count.to);
180 fputs("--connbytes-mode ", stdout);
183 fputs("--connbytes-dir ", stdout);
184 print_direction(sinfo);
187 static struct xtables_match connbytes_match = {
190 .version = XTABLES_VERSION,
191 .size = XT_ALIGN(sizeof(struct xt_connbytes_info)),
192 .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)),
193 .help = connbytes_help,
194 .parse = connbytes_parse,
195 .final_check = connbytes_check,
196 .print = connbytes_print,
197 .save = connbytes_save,
198 .extra_opts = connbytes_opts,
201 static struct xtables_match connbytes_match6 = {
204 .version = XTABLES_VERSION,
205 .size = XT_ALIGN(sizeof(struct xt_connbytes_info)),
206 .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)),
207 .help = connbytes_help,
208 .parse = connbytes_parse,
209 .final_check = connbytes_check,
210 .print = connbytes_print,
211 .save = connbytes_save,
212 .extra_opts = connbytes_opts,
217 xtables_register_match(&connbytes_match);
218 xtables_register_match(&connbytes_match6);