1 /* Shared library add-on to iptables to add connection limit support. */
9 #include <linux/netfilter/xt_connlimit.h>
11 /* Function which prints out usage message. */
12 static void connlimit_help(void)
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
);
22 static const struct option connlimit_opts
[] = {
23 {"connlimit-above", 1, 0, '1'},
24 {"connlimit-mask", 1, 0, '2'},
28 static void connlimit_init(struct ip6t_entry_match
*match
, unsigned int *nfc
)
30 struct xt_connlimit_info
*info
= (void *)match
->data
;
34 info
->v6_mask
[3] = 0xFFFFFFFF;
37 static void prefix_to_netmask(u_int32_t
*mask
, unsigned int prefix_len
)
39 if (prefix_len
== 0) {
40 mask
[0] = mask
[1] = mask
[2] = mask
[3] = 0;
41 } else if (prefix_len
<= 32) {
42 mask
[0] <<= 32 - prefix_len
;
43 mask
[1] = mask
[2] = mask
[3] = 0;
44 } else if (prefix_len
<= 64) {
45 mask
[1] <<= 32 - (prefix_len
- 32);
46 mask
[2] = mask
[3] = 0;
47 } else if (prefix_len
<= 96) {
48 mask
[2] <<= 32 - (prefix_len
- 64);
50 } else if (prefix_len
<= 128) {
51 mask
[3] <<= 32 - (prefix_len
- 96);
53 mask
[0] = htonl(mask
[0]);
54 mask
[1] = htonl(mask
[1]);
55 mask
[2] = htonl(mask
[2]);
56 mask
[3] = htonl(mask
[3]);
59 static int connlimit_parse(int c
, char **argv
, int invert
, unsigned int *flags
,
60 const struct ip6t_entry
*entry
,
61 unsigned int *nfcache
,
62 struct ip6t_entry_match
**match
)
64 struct xt_connlimit_info
*info
= (void *)(*match
)->data
;
69 exit_error(PARAMETER_PROBLEM
,
70 "--connlimit-above and/or --connlimit-mask may "
71 "only be given once");
75 check_inverse(optarg
, &invert
, &optind
, 0);
76 info
->limit
= strtoul(argv
[optind
-1], NULL
, 0);
77 info
->inverse
= invert
;
80 i
= strtoul(argv
[optind
-1], &err
, 0);
81 if (i
> 128 || *err
!= '\0')
82 exit_error(PARAMETER_PROBLEM
,
83 "--connlimit-mask must be between 0 and 128");
84 prefix_to_netmask(info
->v6_mask
, i
);
95 static void connlimit_check(unsigned int flags
)
98 exit_error(PARAMETER_PROBLEM
,
99 "You must specify \"--connlimit-above\"");
102 static unsigned int count_bits(const u_int32_t
*mask
)
104 unsigned int bits
= 0, i
;
107 for (i
= 0; i
< 4; ++i
)
108 for (tmp
[i
] = ~ntohl(mask
[i
]); tmp
[i
] != 0; tmp
[i
] >>= 1)
113 /* Prints out the matchinfo. */
114 static void connlimit_print(const struct ip6t_ip6
*ip
,
115 const struct ip6t_entry_match
*match
, int numeric
)
117 const struct xt_connlimit_info
*info
= (const void *)match
->data
;
119 printf("#conn/%u %s %u ", count_bits(info
->v6_mask
),
120 info
->inverse
? "<=" : ">", info
->limit
);
123 /* Saves the matchinfo in parsable form to stdout. */
124 static void connlimit_save(const struct ip6t_ip6
*ip
,
125 const struct ip6t_entry_match
*match
)
127 const struct xt_connlimit_info
*info
= (const void *)match
->data
;
129 printf("%s--connlimit-above %u --connlimit-mask %u ",
130 info
->inverse
? "! " : "", info
->limit
,
131 count_bits(info
->v6_mask
));
134 static struct ip6tables_match connlimit_reg
= {
136 .version
= IPTABLES_VERSION
,
137 .size
= IP6T_ALIGN(sizeof(struct xt_connlimit_info
)),
138 .userspacesize
= offsetof(struct xt_connlimit_info
, data
),
139 .help
= connlimit_help
,
140 .init
= connlimit_init
,
141 .parse
= connlimit_parse
,
142 .final_check
= connlimit_check
,
143 .print
= connlimit_print
,
144 .save
= connlimit_save
,
145 .extra_opts
= connlimit_opts
,
150 register_match6(&connlimit_reg
);