blob: 1600dea0b872453c739263930764995b7ba6ef44 [file] [log] [blame]
Gerd Knorrd2d02632000-12-18 06:07:23 +00001/* Shared library add-on to iptables to add state tracking support. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
7#include <iptables.h>
8#include <linux/netfilter_ipv4/ip_conntrack.h>
9#include <linux/netfilter_ipv4/ipt_iplimit.h>
10
11/* Function which prints out usage message. */
12static void
13help(void)
14{
15 printf(
16"iplimit v%s options:\n"
17"[!] --iplimit-above n match if the number of existing tcp connections is (not) above n\n"
18" --iplimit-mask n group hosts using mask\n"
19"\n", NETFILTER_VERSION);
20}
21
22static struct option opts[] = {
23 { "iplimit-above", 1, 0, '1' },
24 { "iplimit-mask", 1, 0, '2' },
25 {0}
26};
27
28/* Initialize the match. */
29static void
30init(struct ipt_entry_match *m, unsigned int *nfcache)
31{
32 /* Can't cache this */
33 *nfcache |= NFC_UNKNOWN;
34}
35
36/* Function which parses command options; returns true if it
37 ate an option */
38static int
39parse(int c, char **argv, int invert, unsigned int *flags,
40 const struct ipt_entry *entry,
41 unsigned int *nfcache,
42 struct ipt_entry_match **match)
43{
44 struct ipt_iplimit_info *info = (struct ipt_iplimit_info*)(*match)->data;
45
46 if (0 == (*flags & 2)) {
47 /* set default mask unless we've already seen a mask option */
48 info->mask = htonl(0xFFFFFFFF);
49 }
50
51 switch (c) {
52 case '1':
53 if (check_inverse(optarg, &invert))
54 optind++;
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 */
73static void final_check(unsigned int flags)
74{
75 if (!flags & 1)
76 exit_error(PARAMETER_PROBLEM, "You must specify `--iplimit-above'");
77}
78
79static int
80count_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. */
95static void
96print(const struct ipt_ip *ip,
97 const struct ipt_entry_match *match,
98 int numeric)
99{
100 struct ipt_iplimit_info *info = (struct ipt_iplimit_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. */
107static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
108{
109 struct ipt_iplimit_info *info = (struct ipt_iplimit_info*)match->data;
110
111 printf("%s--iplimit-above %d",info->inverse ? "! " : "",info->limit);
112 printf(" --iplimit-mask %d",count_bits(info->mask));
113}
114
115struct iptables_match iplimit
116= { NULL,
117 "iplimit",
118 NETFILTER_VERSION,
119 IPT_ALIGN(sizeof(struct ipt_iplimit_info)),
120 IPT_ALIGN(sizeof(struct ipt_iplimit_info)),
121 &help,
122 &init,
123 &parse,
124 &final_check,
125 &print,
126 &save,
127 opts
128};
129
130void _init(void)
131{
132 register_match(&iplimit);
133}