Sapan says vnet_tun is obsolete.
[iptables.git] / extensions / libxt_connbytes.c
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 <xtables.h>
8 #include <linux/netfilter/nf_conntrack_common.h>
9 #include <linux/netfilter/xt_connbytes.h>
10
11 /* Function which prints out usage message. */
12 static void connbytes_help(void)
13 {
14         printf(
15 "connbytes match options:\n"
16 " [!] --connbytes from:[to]\n"
17 "     --connbytes-dir [original, reply, both]\n"
18 "     --connbytes-mode [packets, bytes, avgpkt]\n");
19 }
20
21 static const struct option connbytes_opts[] = {
22         { "connbytes", 1, NULL, '1' },
23         { "connbytes-dir", 1, NULL, '2' },
24         { "connbytes-mode", 1, NULL, '3' },
25         { .name = NULL }
26 };
27
28 static void
29 parse_range(const char *arg, struct xt_connbytes_info *si)
30 {
31         char *colon,*p;
32
33         si->count.from = strtoul(arg,&colon,10);
34         if (*colon != ':') 
35                 exit_error(PARAMETER_PROBLEM, "Bad range `%s'", arg);
36         si->count.to = strtoul(colon+1,&p,10);
37         if (p == colon+1) {
38                 /* second number omited */
39                 si->count.to = 0xffffffff;
40         }
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);
45 }
46
47 /* Function which parses command options; returns true if it
48    ate an option */
49 static int
50 connbytes_parse(int c, char **argv, int invert, unsigned int *flags,
51                 const void *entry, struct xt_entry_match **match)
52 {
53         struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)(*match)->data;
54         unsigned long i;
55
56         switch (c) {
57         case '1':
58                 if (check_inverse(optarg, &invert, &optind, 0))
59                         optind++;
60
61                 parse_range(argv[optind-1], sinfo);
62                 if (invert) {
63                         i = sinfo->count.from;
64                         sinfo->count.from = sinfo->count.to;
65                         sinfo->count.to = i;
66                 }
67                 *flags |= 1;
68                 break;
69         case '2':
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;
76                 else
77                         exit_error(PARAMETER_PROBLEM,
78                                    "Unknown --connbytes-dir `%s'", optarg);
79
80                 *flags |= 2;
81                 break;
82         case '3':
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;
89                 else
90                         exit_error(PARAMETER_PROBLEM,
91                                    "Unknown --connbytes-mode `%s'", optarg);
92                 *flags |= 4;
93                 break;
94         default:
95                 return 0;
96         }
97
98         return 1;
99 }
100
101 static void connbytes_check(unsigned int flags)
102 {
103         if (flags != 7)
104                 exit_error(PARAMETER_PROBLEM, "You must specify `--connbytes'"
105                            "`--connbytes-dir' and `--connbytes-mode'");
106 }
107
108 static void print_mode(struct xt_connbytes_info *sinfo)
109 {
110         switch (sinfo->what) {
111                 case XT_CONNBYTES_PKTS:
112                         fputs("packets ", stdout);
113                         break;
114                 case XT_CONNBYTES_BYTES:
115                         fputs("bytes ", stdout);
116                         break;
117                 case XT_CONNBYTES_AVGPKT:
118                         fputs("avgpkt ", stdout);
119                         break;
120                 default:
121                         fputs("unknown ", stdout);
122                         break;
123         }
124 }
125
126 static void print_direction(struct xt_connbytes_info *sinfo)
127 {
128         switch (sinfo->direction) {
129                 case XT_CONNBYTES_DIR_ORIGINAL:
130                         fputs("original ", stdout);
131                         break;
132                 case XT_CONNBYTES_DIR_REPLY:
133                         fputs("reply ", stdout);
134                         break;
135                 case XT_CONNBYTES_DIR_BOTH:
136                         fputs("both ", stdout);
137                         break;
138                 default:
139                         fputs("unknown ", stdout);
140                         break;
141         }
142 }
143
144 /* Prints out the matchinfo. */
145 static void
146 connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric)
147 {
148         struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)match->data;
149
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);
154         else
155                 printf("connbytes %llu:%llu ",
156                         (unsigned long long)sinfo->count.from,
157                         (unsigned long long)sinfo->count.to);
158
159         fputs("connbytes mode ", stdout);
160         print_mode(sinfo);
161
162         fputs("connbytes direction ", stdout);
163         print_direction(sinfo);
164 }
165
166 /* Saves the matchinfo in parsable form to stdout. */
167 static void connbytes_save(const void *ip, const struct xt_entry_match *match)
168 {
169         struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)match->data;
170
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);
175         else
176                 printf("--connbytes %llu:%llu ",
177                         (unsigned long long)sinfo->count.from,
178                         (unsigned long long)sinfo->count.to);
179
180         fputs("--connbytes-mode ", stdout);
181         print_mode(sinfo);
182
183         fputs("--connbytes-dir ", stdout);
184         print_direction(sinfo);
185 }
186
187 static struct xtables_match connbytes_match = {
188         .family         = AF_INET,
189         .name           = "connbytes",
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,
199 };
200
201 static struct xtables_match connbytes_match6 = {
202         .family         = AF_INET6,
203         .name           = "connbytes",
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,
213 };
214
215 void _init(void)
216 {
217         xtables_register_match(&connbytes_match);
218         xtables_register_match(&connbytes_match6);
219 }