1 /* Shared library add-on to iptables to add byte tracking support. */
8 #include <linux/netfilter/nf_conntrack_common.h>
9 #include <linux/netfilter_ipv4/ipt_connbytes.h>
11 /* Function which prints out usage message. */
16 "connbytes v%s options:\n"
17 " [!] --connbytes from:[to]\n"
18 " --connbytes-dir [original, reply, both]\n"
19 " --connbytes-mode [packets, bytes, avgpkt]\n"
20 "\n", IPTABLES_VERSION
);
23 static struct option opts
[] = {
24 { "connbytes", 1, 0, '1' },
25 { "connbytes-dir", 1, 0, '2' },
26 { "connbytes-mode", 1, 0, '3' },
31 parse_range(const char *arg
, struct ipt_connbytes_info
*si
)
35 si
->count
.from
= strtoul(arg
,&colon
,10);
37 exit_error(PARAMETER_PROBLEM
, "Bad range `%s'", arg
);
38 si
->count
.to
= strtoul(colon
+1,&p
,10);
40 /* second number omited */
41 si
->count
.to
= 0xffffffff;
43 if (si
->count
.from
> si
->count
.to
)
44 exit_error(PARAMETER_PROBLEM
, "%llu should be less than %llu",
45 si
->count
.from
, si
->count
.to
);
48 /* Function which parses command options; returns true if it
51 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
52 const struct ipt_entry
*entry
,
53 unsigned int *nfcache
,
54 struct ipt_entry_match
**match
)
56 struct ipt_connbytes_info
*sinfo
= (struct ipt_connbytes_info
*)(*match
)->data
;
61 if (check_inverse(optarg
, &invert
, &optind
, 0))
64 parse_range(argv
[optind
-1], sinfo
);
66 i
= sinfo
->count
.from
;
67 sinfo
->count
.from
= sinfo
->count
.to
;
73 if (!strcmp(optarg
, "original"))
74 sinfo
->direction
= IPT_CONNBYTES_DIR_ORIGINAL
;
75 else if (!strcmp(optarg
, "reply"))
76 sinfo
->direction
= IPT_CONNBYTES_DIR_REPLY
;
77 else if (!strcmp(optarg
, "both"))
78 sinfo
->direction
= IPT_CONNBYTES_DIR_BOTH
;
80 exit_error(PARAMETER_PROBLEM
,
81 "Unknown --connbytes-dir `%s'", optarg
);
86 if (!strcmp(optarg
, "packets"))
87 sinfo
->what
= IPT_CONNBYTES_PKTS
;
88 else if (!strcmp(optarg
, "bytes"))
89 sinfo
->what
= IPT_CONNBYTES_BYTES
;
90 else if (!strcmp(optarg
, "avgpkt"))
91 sinfo
->what
= IPT_CONNBYTES_AVGPKT
;
93 exit_error(PARAMETER_PROBLEM
,
94 "Unknown --connbytes-mode `%s'", optarg
);
104 static void final_check(unsigned int flags
)
107 exit_error(PARAMETER_PROBLEM
, "You must specify `--connbytes'"
108 "`--connbytes-dir' and `--connbytes-mode'");
111 static void print_mode(struct ipt_connbytes_info
*sinfo
)
113 switch (sinfo
->what
) {
114 case IPT_CONNBYTES_PKTS
:
115 fputs("packets ", stdout
);
117 case IPT_CONNBYTES_BYTES
:
118 fputs("bytes ", stdout
);
120 case IPT_CONNBYTES_AVGPKT
:
121 fputs("avgpkt ", stdout
);
124 fputs("unknown ", stdout
);
129 static void print_direction(struct ipt_connbytes_info
*sinfo
)
131 switch (sinfo
->direction
) {
132 case IPT_CONNBYTES_DIR_ORIGINAL
:
133 fputs("original ", stdout
);
135 case IPT_CONNBYTES_DIR_REPLY
:
136 fputs("reply ", stdout
);
138 case IPT_CONNBYTES_DIR_BOTH
:
139 fputs("both ", stdout
);
142 fputs("unknown ", stdout
);
147 /* Prints out the matchinfo. */
149 print(const struct ipt_ip
*ip
,
150 const struct ipt_entry_match
*match
,
153 struct ipt_connbytes_info
*sinfo
= (struct ipt_connbytes_info
*)match
->data
;
155 if (sinfo
->count
.from
> sinfo
->count
.to
)
156 printf("connbytes ! %llu:%llu ", sinfo
->count
.to
,
159 printf("connbytes %llu:%llu ",sinfo
->count
.from
,
163 fputs("direction ", stdout
);
164 print_direction(sinfo
);
167 /* Saves the matchinfo in parsable form to stdout. */
168 static void save(const struct ipt_ip
*ip
, const struct ipt_entry_match
*match
)
170 struct ipt_connbytes_info
*sinfo
= (struct ipt_connbytes_info
*)match
->data
;
172 if (sinfo
->count
.from
> sinfo
->count
.to
)
173 printf("! --connbytes %llu:%llu ", sinfo
->count
.to
,
176 printf("--connbytes %llu:%llu ", sinfo
->count
.from
,
179 fputs("--connbytes-mode ", stdout
);
182 fputs("--connbytes-dir ", stdout
);
183 print_direction(sinfo
);
186 static struct iptables_match state
= {
189 .version
= IPTABLES_VERSION
,
190 .size
= IPT_ALIGN(sizeof(struct ipt_connbytes_info
)),
191 .userspacesize
= IPT_ALIGN(sizeof(struct ipt_connbytes_info
)),
194 .final_check
= &final_check
,
202 register_match(&state
);