Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / iptables / extensions / libipt_connlimit.c
blob6f2983f2d2a177331ba0230996501d0188ed520b
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>
12 /* Function which prints out usage message. */
13 static void
14 help(void)
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);
23 static struct option opts[] = {
24 { "connlimit-above", 1, 0, '1' },
25 { "connlimit-mask", 1, 0, '2' },
26 {0}
29 static void connlimit_init(struct ipt_entry_match *match, unsigned int *nfc)
31 struct ipt_connlimit_info *info = (void *)match->data;
32 info->mask = htonl(0xFFFFFFFF);
35 /* Function which parses command options; returns true if it
36 ate an option */
37 static int
38 parse(int c, char **argv, int invert, unsigned int *flags,
39 const struct ipt_entry *entry,
40 unsigned int *nfcache,
41 struct ipt_entry_match **match)
43 struct ipt_connlimit_info *info = (struct ipt_connlimit_info*)(*match)->data;
44 char *err;
45 int i;
47 if (*flags & c)
48 exit_error(PARAMETER_PROBLEM,
49 "--connlimit-above and/or --connlimit-mask may "
50 "only be given once");
52 switch (c) {
53 case '1':
54 check_inverse(optarg, &invert, &optind, 0);
55 info->limit = strtoul(argv[optind-1], NULL, 0);
56 info->inverse = invert;
57 break;
59 case '2':
60 i = strtoul(argv[optind-1], &err, 0);
61 if (i > 32 || *err != '\0')
62 exit_error(PARAMETER_PROBLEM,
63 "--connlimit-mask must be between 0 and 32");
64 if (i == 0)
65 info->mask = 0;
66 else
67 info->mask = htonl(0xFFFFFFFF << (32 - i));
68 break;
70 default:
71 return 0;
74 *flags |= c;
75 return 1;
78 /* Final check */
79 static void final_check(unsigned int flags)
81 if (!(flags & 1))
82 exit_error(PARAMETER_PROBLEM,
83 "You must specify \"--connlimit-above\"");
86 static int
87 count_bits(u_int32_t mask)
89 unsigned int bits = 0;
91 for (mask = ~ntohl(mask); mask != 0; mask >>= 1)
92 ++bits;
94 return 32 - bits;
97 /* Prints out the matchinfo. */
98 static void
99 print(const struct ipt_ip *ip,
100 const struct ipt_entry_match *match,
101 int numeric)
103 struct ipt_connlimit_info *info = (struct ipt_connlimit_info*)match->data;
105 printf("#conn/%d %s %d ", count_bits(info->mask),
106 info->inverse ? "<=" : ">", info->limit);
109 /* Saves the matchinfo in parsable form to stdout. */
110 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
112 struct ipt_connlimit_info *info = (struct ipt_connlimit_info*)match->data;
114 printf("%s--connlimit-above %u --connlimit-mask %u ",
115 info->inverse ? "! " : "", info->limit,
116 count_bits(info->mask));
119 static struct iptables_match connlimit = {
120 .name = "connlimit",
121 .version = IPTABLES_VERSION,
122 .size = IPT_ALIGN(sizeof(struct ipt_connlimit_info)),
123 .userspacesize = offsetof(struct ipt_connlimit_info,data),
124 .help = help,
125 .init = connlimit_init,
126 .parse = parse,
127 .final_check = final_check,
128 .print = print,
129 .save = save,
130 .extra_opts = opts
133 void _init(void)
135 register_match(&connlimit);