blob: f6d1039555ede928898fefccb84f9285dc615dd3 [file] [log] [blame]
Jan Engelhardt21df4af2007-07-09 16:50:17 +00001/* 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 "../include/linux/netfilter/xt_connlimit.h"
10
11/* Function which prints out usage message. */
12static void connlimit_help(void)
13{
14 printf(
15"connlimit v%s options:\n"
16"[!] --connlimit-above n match if the number of existing "
17" connections is (not) above n\n"
18" --connlimit-mask n group hosts using mask\n"
19"\n", IPTABLES_VERSION);
20}
21
22static const struct option connlimit_opts[] = {
23 {"connlimit-above", 1, NULL, 1},
24 {"connlimit-mask", 1, NULL, 2},
25 {NULL},
26};
27
28static void connlimit_init(struct ipt_entry_match *match, unsigned int *nfc)
29{
30 struct xt_connlimit_info *info = (void *)match->data;
31 info->v4_mask = 0xFFFFFFFF;
32}
33
34static int connlimit_parse(int c, char **argv, int invert, unsigned int *flags,
35 const struct ipt_entry *entry,
36 unsigned int *nfcache,
37 struct ipt_entry_match **match)
38{
39 struct xt_connlimit_info *info = (void *)(*match)->data;
40 char *err;
41 int i;
42
43 if (*flags & c)
44 exit_error(PARAMETER_PROBLEM,
45 "--connlimit-above and/or --connlimit-mask may "
46 "only be given once");
47
48 switch (c) {
49 case 1:
50 check_inverse(optarg, &invert, &optind, 0);
51 info->limit = strtoul(argv[optind-1], NULL, 0);
52 info->inverse = invert;
53 break;
54 case 2:
55 i = strtoul(argv[optind-1], &err, 0);
56 if (i > 32 || *err != '\0')
57 exit_error(PARAMETER_PROBLEM,
58 "--connlimit-mask must be between 0 and 32");
59 if (i == 0)
60 info->v4_mask = 0;
61 else
62 info->v4_mask = htonl(0xFFFFFFFF << (32 - i));
63 break;
64 default:
65 return 0;
66 }
67
68 *flags |= c;
69 return 1;
70}
71
72/* Final check */
73static void connlimit_check(unsigned int flags)
74{
75 if (!(flags & 1))
76 exit_error(PARAMETER_PROBLEM,
77 "You must specify \"--connlimit-above\"");
78}
79
80static unsigned int count_bits(u_int32_t mask)
81{
82 unsigned int bits = 0;
83
84 for (mask = ~ntohl(mask); mask != 0; mask >>= 1)
85 ++bits;
86
87 return 32 - bits;
88}
89
90/* Prints out the matchinfo. */
91static void connlimit_print(const struct ipt_ip *ip,
92 const struct ipt_entry_match *match, int numeric)
93{
94 const struct xt_connlimit_info *info = (const void *)match->data;
95
96 printf("#conn/%u %s %u ", count_bits(info->v4_mask),
97 info->inverse ? "<" : ">", info->limit);
98}
99
100/* Saves the matchinfo in parsable form to stdout. */
101static void connlimit_save(const struct ipt_ip *ip,
102 const struct ipt_entry_match *match)
103{
104 const struct xt_connlimit_info *info = (const void *)match->data;
105
106 printf("%s--connlimit-above %u --connlimit-mask %u ",
107 info->inverse ? "! " : "", info->limit,
108 count_bits(info->v4_mask));
109}
110
111static struct iptables_match connlimit_reg = {
112 .name = "connlimit",
113 .version = IPTABLES_VERSION,
114 .size = IPT_ALIGN(sizeof(struct xt_connlimit_info)),
115 .userspacesize = offsetof(struct xt_connlimit_info, data),
116 .help = connlimit_help,
117 .init = connlimit_init,
118 .parse = connlimit_parse,
119 .final_check = connlimit_check,
120 .print = connlimit_print,
121 .save = connlimit_save,
122 .extra_opts = connlimit_opts,
123};
124
Yasuyuki KOZAKAIef329f22007-07-13 15:07:10 +0000125void _init(void)
Jan Engelhardt21df4af2007-07-09 16:50:17 +0000126{
127 register_match(&connlimit_reg);
128}