iptables-1.2.9-2.3.1.src.rpm
[iptables.git] / extensions / libipt_connlimit.c
1 /* Shared library add-on to iptables to add connection limit support. */
2 #include <stdio.h>
3 #include <netdb.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <stddef.h>
7 #include <getopt.h>
8 #include <iptables.h>
9 #include <linux/netfilter_ipv4/ip_conntrack.h>
10 #include <linux/netfilter_ipv4/ipt_connlimit.h>
11
12 /* Function which prints out usage message. */
13 static void
14 help(void)
15 {
16         printf(
17 "connlimit v%s options:\n"
18 "[!] --connlimit-above n                match if the number of existing tcp connections is (not) above n\n"
19 " --connlimit-mask n            group hosts using mask\n"
20 "\n", IPTABLES_VERSION);
21 }
22
23 static struct option opts[] = {
24         { "connlimit-above", 1, 0, '1' },
25         { "connlimit-mask",  1, 0, '2' },
26         {0}
27 };
28
29 /* Initialize the match. */
30 static void
31 init(struct ipt_entry_match *m, unsigned int *nfcache)
32 {
33         /* Can't cache this */
34         *nfcache |= NFC_UNKNOWN;
35 }
36
37 /* Function which parses command options; returns true if it
38    ate an option */
39 static int
40 parse(int c, char **argv, int invert, unsigned int *flags,
41       const struct ipt_entry *entry,
42       unsigned int *nfcache,
43       struct ipt_entry_match **match)
44 {
45         struct ipt_connlimit_info *info = (struct ipt_connlimit_info*)(*match)->data;
46
47         if (0 == (*flags & 2)) {
48                 /* set default mask unless we've already seen a mask option */
49                 info->mask = htonl(0xFFFFFFFF);
50         }
51
52         switch (c) {
53         case '1':
54                 check_inverse(optarg, &invert, &optind, 0);
55                 info->limit = atoi(argv[optind-1]);
56                 info->inverse = invert;
57                 *flags |= 1;
58                 break;
59
60         case '2':
61                 info->mask = htonl(0xFFFFFFFF << (32 - atoi(argv[optind-1])));
62                 *flags |= 2;
63                 break;
64
65         default:
66                 return 0;
67         }
68
69         return 1;
70 }
71
72 /* Final check */
73 static void final_check(unsigned int flags)
74 {
75         if (!flags & 1)
76                 exit_error(PARAMETER_PROBLEM, "You must specify `--connlimit-above'");
77 }
78
79 static int
80 count_bits(u_int32_t mask)
81 {
82         int i, bits;
83
84         for (bits = 0, i = 31; i >= 0; i--) {
85                 if (mask & htonl((u_int32_t)1 << i)) {
86                         bits++;
87                         continue;
88                 }
89                 break;
90         }
91         return bits;
92 }
93
94 /* Prints out the matchinfo. */
95 static void
96 print(const struct ipt_ip *ip,
97       const struct ipt_entry_match *match,
98       int numeric)
99 {
100         struct ipt_connlimit_info *info = (struct ipt_connlimit_info*)match->data;
101
102         printf("#conn/%d %s %d ", count_bits(info->mask),
103                info->inverse ? "<" : ">", info->limit);
104 }
105
106 /* Saves the matchinfo in parsable form to stdout. */
107 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
108 {
109         struct ipt_connlimit_info *info = (struct ipt_connlimit_info*)match->data;
110
111         printf("%s--connlimit-above %d ",info->inverse ? "! " : "",info->limit);
112         printf("--connlimit-mask %d ",count_bits(info->mask));
113 }
114
115 static struct iptables_match connlimit = {
116         name:           "connlimit",
117         version:        IPTABLES_VERSION,
118         size:           IPT_ALIGN(sizeof(struct ipt_connlimit_info)),
119         userspacesize:  offsetof(struct ipt_connlimit_info,data),
120         help:           help,
121         init:           init,
122         parse:          parse,
123         final_check:    final_check,
124         print:          print,
125         save:           save,
126         extra_opts:     opts
127 };
128
129 void _init(void)
130 {
131         register_match(&connlimit);
132 }