1 /* Shared library add-on to iptables to add connection limit support. */
9 #include "../include/linux/netfilter/xt_connlimit.h"
11 static void connlimit_help(void)
14 "connlimit match options:\n"
15 "[!] --connlimit-above n match if the number of existing "
16 " connections is (not) above n\n"
17 " --connlimit-mask n group hosts using mask\n");
20 static const struct option connlimit_opts[] = {
21 {"connlimit-above", 1, NULL, 'A'},
22 {"connlimit-mask", 1, NULL, 'M'},
26 static void connlimit_init(struct xt_entry_match *match)
28 struct xt_connlimit_info *info = (void *)match->data;
29 info->v4_mask = 0xFFFFFFFFUL;
32 static void prefix_to_netmask(u_int32_t *mask, unsigned int prefix_len)
34 if (prefix_len == 0) {
35 mask[0] = mask[1] = mask[2] = mask[3] = 0;
36 } else if (prefix_len <= 32) {
37 mask[0] <<= 32 - prefix_len;
38 mask[1] = mask[2] = mask[3] = 0;
39 } else if (prefix_len <= 64) {
40 mask[1] <<= 32 - (prefix_len - 32);
41 mask[2] = mask[3] = 0;
42 } else if (prefix_len <= 96) {
43 mask[2] <<= 32 - (prefix_len - 64);
45 } else if (prefix_len <= 128) {
46 mask[3] <<= 32 - (prefix_len - 96);
48 mask[0] = htonl(mask[0]);
49 mask[1] = htonl(mask[1]);
50 mask[2] = htonl(mask[2]);
51 mask[3] = htonl(mask[3]);
54 static int connlimit_parse(int c, char **argv, int invert, unsigned int *flags,
55 struct xt_connlimit_info *info, unsigned int family)
63 exit_error(PARAMETER_PROBLEM,
64 "--connlimit-above may be given only once");
66 check_inverse(optarg, &invert, &optind, 0);
67 info->limit = strtoul(argv[optind-1], NULL, 0);
68 info->inverse = invert;
72 exit_error(PARAMETER_PROBLEM,
73 "--connlimit-mask may be given only once");
76 i = strtoul(argv[optind-1], &err, 0);
77 if (family == AF_INET6) {
78 if (i > 128 || *err != '\0')
79 exit_error(PARAMETER_PROBLEM,
80 "--connlimit-mask must be between "
82 prefix_to_netmask(info->v6_mask, i);
84 if (i > 32 || *err != '\0')
85 exit_error(PARAMETER_PROBLEM,
86 "--connlimit-mask must be between "
91 info->v4_mask = htonl(0xFFFFFFFF << (32 - i));
101 static int connlimit_parse4(int c, char **argv, int invert,
102 unsigned int *flags, const void *entry,
103 struct xt_entry_match **match)
105 return connlimit_parse(c, argv, invert, flags,
106 (void *)(*match)->data, AF_INET);
109 static int connlimit_parse6(int c, char **argv, int invert,
110 unsigned int *flags, const void *entry,
111 struct xt_entry_match **match)
113 return connlimit_parse(c, argv, invert, flags,
114 (void *)(*match)->data, AF_INET6);
117 static void connlimit_check(unsigned int flags)
120 exit_error(PARAMETER_PROBLEM,
121 "You must specify \"--connlimit-above\"");
124 static unsigned int count_bits4(u_int32_t mask)
126 unsigned int bits = 0;
128 for (mask = ~ntohl(mask); mask != 0; mask >>= 1)
134 static unsigned int count_bits6(const u_int32_t *mask)
136 unsigned int bits = 0, i;
139 for (i = 0; i < 4; ++i)
140 for (tmp[i] = ~ntohl(mask[i]); tmp[i] != 0; tmp[i] >>= 1)
145 static void connlimit_print4(const void *ip,
146 const struct xt_entry_match *match, int numeric)
148 const struct xt_connlimit_info *info = (const void *)match->data;
150 printf("#conn/%u %s %u ", count_bits4(info->v4_mask),
151 info->inverse ? "<=" : ">", info->limit);
154 static void connlimit_print6(const void *ip,
155 const struct xt_entry_match *match, int numeric)
157 const struct xt_connlimit_info *info = (const void *)match->data;
158 printf("#conn/%u %s %u ", count_bits6(info->v6_mask),
159 info->inverse ? "<=" : ">", info->limit);
162 static void connlimit_save4(const void *ip, const struct xt_entry_match *match)
164 const struct xt_connlimit_info *info = (const void *)match->data;
166 printf("%s--connlimit-above %u --connlimit-mask %u ",
167 info->inverse ? "! " : "", info->limit,
168 count_bits4(info->v4_mask));
171 static void connlimit_save6(const void *ip, const struct xt_entry_match *match)
173 const struct xt_connlimit_info *info = (const void *)match->data;
175 printf("%s--connlimit-above %u --connlimit-mask %u ",
176 info->inverse ? "! " : "", info->limit,
177 count_bits6(info->v6_mask));
180 static struct xtables_match connlimit_match = {
183 .version = XTABLES_VERSION,
184 .size = XT_ALIGN(sizeof(struct xt_connlimit_info)),
185 .userspacesize = offsetof(struct xt_connlimit_info, data),
186 .help = connlimit_help,
187 .init = connlimit_init,
188 .parse = connlimit_parse4,
189 .final_check = connlimit_check,
190 .print = connlimit_print4,
191 .save = connlimit_save4,
192 .extra_opts = connlimit_opts,
195 static struct xtables_match connlimit_match6 = {
198 .version = XTABLES_VERSION,
199 .size = XT_ALIGN(sizeof(struct xt_connlimit_info)),
200 .userspacesize = offsetof(struct xt_connlimit_info, data),
201 .help = connlimit_help,
202 .init = connlimit_init,
203 .parse = connlimit_parse6,
204 .final_check = connlimit_check,
205 .print = connlimit_print6,
206 .save = connlimit_save6,
207 .extra_opts = connlimit_opts,
212 xtables_register_match(&connlimit_match);
213 xtables_register_match(&connlimit_match6);