iptables-1.3.2-20050720
[iptables.git] / extensions / libipt_connrate.c
1 /* Shared library add-on to iptables to add connection rate tracking
2  * support.
3  *
4  * Copyright (c) 2004 Nuutti Kotivuori <naked@iki.fi>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  **/
10 #include <stdio.h>
11 #include <netdb.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <getopt.h>
15 #include <iptables.h>
16 #include <linux/netfilter_ipv4/ip_conntrack.h>
17 #include <linux/netfilter_ipv4/ipt_connrate.h>
18
19 /* Function which prints out usage message. */
20 static void
21 help(void)
22 {
23         printf(
24 "connrate v%s options:\n"
25 " --connrate [!] [from]:[to]\n"
26 "                               Match connection transfer rate in bytes\n"
27 "                               per second. `inf' can be used for maximum\n"
28 "                               expressible value.\n"
29 "\n", IPTABLES_VERSION);
30 }
31
32 static struct option opts[] = {
33         { "connrate", 1, 0, '1' },
34         {0}
35 };
36
37 static u_int32_t
38 parse_value(const char *arg, u_int32_t def)
39 {
40         char *end;
41         size_t len;
42         u_int32_t value;
43
44         len = strlen(arg);
45         if(len == 0)
46                 return def;
47         if(strcmp(arg, "inf") == 0)
48                 return 0xFFFFFFFF;
49         value = strtoul(arg, &end, 0);
50         if(*end != '\0')
51                 exit_error(PARAMETER_PROBLEM,
52                            "Bad value in range `%s'", arg);
53         return value;
54 }
55
56 static void
57 parse_range(const char *arg, struct ipt_connrate_info *si)
58 {
59         char *buffer;
60         char *colon;
61
62         buffer = strdup(arg);
63         if ((colon = strchr(buffer, ':')) == NULL)
64                 exit_error(PARAMETER_PROBLEM, "Bad range `%s'", arg);
65         *colon = '\0';
66         si->from = parse_value(buffer, 0);
67         si->to = parse_value(colon+1, 0xFFFFFFFF);
68         if (si->from > si->to)
69                 exit_error(PARAMETER_PROBLEM, "%u should be less than %u", si->from,si->to);
70         free(buffer);
71 }
72
73 #define CONNRATE_OPT 0x01
74
75 /* Function which parses command options; returns true if it
76    ate an option */
77 static int
78 parse(int c, char **argv, int invert, unsigned int *flags,
79       const struct ipt_entry *entry,
80       unsigned int *nfcache,
81       struct ipt_entry_match **match)
82 {
83         struct ipt_connrate_info *sinfo = (struct ipt_connrate_info *)(*match)->data;
84         u_int32_t tmp;
85
86         switch (c) {
87         case '1':
88                 if (*flags & CONNRATE_OPT)
89                         exit_error(PARAMETER_PROBLEM,
90                                    "Only one `--connrate' allowed");
91                 check_inverse(optarg, &invert, &optind, 0);
92                 parse_range(argv[optind-1], sinfo);
93                 if (invert) {
94                         tmp = sinfo->from;
95                         sinfo->from = sinfo->to;
96                         sinfo->to = tmp;
97                 }
98                 *flags |= CONNRATE_OPT;
99                 break;
100
101         default:
102                 return 0;
103         }
104
105         return 1;
106 }
107
108 static void final_check(unsigned int flags)
109 {
110         if (!(flags & CONNRATE_OPT))
111                 exit_error(PARAMETER_PROBLEM,
112                            "connrate match: You must specify `--connrate'");
113 }
114
115 static void
116 print_value(u_int32_t value)
117 {
118         if(value == 0xFFFFFFFF)
119                 printf("inf");
120         else
121                 printf("%u", value);
122 }
123
124 static void
125 print_range(struct ipt_connrate_info *sinfo)
126 {
127         if (sinfo->from > sinfo->to) {
128                 printf("! ");
129                 print_value(sinfo->to);
130                 printf(":");
131                 print_value(sinfo->from);
132         } else {
133                 print_value(sinfo->from);
134                 printf(":");
135                 print_value(sinfo->to);
136         }
137 }
138
139 /* Prints out the matchinfo. */
140 static void
141 print(const struct ipt_ip *ip,
142       const struct ipt_entry_match *match,
143       int numeric)
144 {
145         struct ipt_connrate_info *sinfo = (struct ipt_connrate_info *)match->data;
146
147         printf("connrate ");
148         print_range(sinfo);
149         printf(" ");
150 }
151
152 /* Saves the matchinfo in parsable form to stdout. */
153 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
154 {
155         struct ipt_connrate_info *sinfo = (struct ipt_connrate_info *)match->data;
156
157         printf("--connrate ");
158         print_range(sinfo);
159         printf(" ");
160 }
161
162 static struct iptables_match state = { 
163         .next           = NULL,
164         .name           = "connrate",
165         .version        = IPTABLES_VERSION,
166         .size           = IPT_ALIGN(sizeof(struct ipt_connrate_info)),
167         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_connrate_info)),
168         .help           = &help,
169         .parse          = &parse,
170         .final_check    = &final_check,
171         .print          = &print,
172         .save           = &save,
173         .extra_opts     = opts
174 };
175
176 void _init(void)
177 {
178         register_match(&state);
179 }