1 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ip_conntrack_helper.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ip_conntrack_helper.h
2 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ip_conntrack_helper.h 2004-03-04 06:16:37.000000000 +0000
3 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ip_conntrack_helper.h 2004-03-04 08:39:18.000000000 +0000
6 extern struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple);
9 +/* Allocate space for an expectation: this is mandatory before calling
10 + ip_conntrack_expect_related. */
11 +extern int ip_conntrack_expect_alloc(struct ip_conntrack_expect **new);
12 /* Add an expected connection: can have more than one per connection */
13 -extern int ip_conntrack_expect_related(struct ip_conntrack *related_to,
14 - struct ip_conntrack_expect *exp);
15 +extern int ip_conntrack_expect_related(struct ip_conntrack_expect *exp,
16 + struct ip_conntrack *related_to);
17 extern int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
18 struct ip_conntrack_tuple *newtuple);
19 extern void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp);
20 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_TTL.h
21 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 00:00:00.000000000 +0000
22 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_TTL.h 2004-03-04 08:39:28.000000000 +0000
24 +/* TTL modification module for IP tables
25 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
36 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
38 +struct ipt_TTL_info {
45 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_connlimit.h
46 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 00:00:00.000000000 +0000
47 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_connlimit.h 2004-03-04 08:39:29.000000000 +0000
49 +#ifndef _IPT_CONNLIMIT_H
50 +#define _IPT_CONNLIMIT_H
52 +struct ipt_connlimit_data;
54 +struct ipt_connlimit_info {
58 + struct ipt_connlimit_data *data;
60 +#endif /* _IPT_CONNLIMIT_H */
61 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_dstlimit.h
62 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 00:00:00.000000000 +0000
63 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-03-04 08:39:30.000000000 +0000
65 +#ifndef _IPT_DSTLIMIT_H
66 +#define _IPT_DSTLIMIT_H
68 +/* timings are in milliseconds. */
69 +#define IPT_DSTLIMIT_SCALE 10000
70 +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
71 + seconds, or one every 59 hours. */
73 +/* details of this structure hidden by the implementation */
74 +struct ipt_dstlimit_htable;
76 +#define IPT_DSTLIMIT_HASH_DIP 0x0001
77 +#define IPT_DSTLIMIT_HASH_DPT 0x0002
78 +#define IPT_DSTLIMIT_HASH_SIP 0x0004
80 +struct dstlimit_cfg {
81 + u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
82 + u_int32_t avg; /* Average secs between packets * scale */
83 + u_int32_t burst; /* Period multiplier for upper limit. */
85 + /* user specified */
86 + u_int32_t size; /* how many buckets */
87 + u_int32_t max; /* max number of entries */
88 + u_int32_t gc_interval; /* gc interval */
89 + u_int32_t expire; /* when do entries expire? */
92 +struct ipt_dstlimit_info {
93 + char name [IFNAMSIZ]; /* name */
94 + struct dstlimit_cfg cfg;
95 + struct ipt_dstlimit_htable *hinfo;
97 + /* Used internally by the kernel */
100 + struct ipt_dstlimit_info *master;
103 +#endif /*_IPT_DSTLIMIT_H*/
104 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_fuzzy.h
105 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 00:00:00.000000000 +0000
106 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_fuzzy.h 2004-03-04 08:39:30.000000000 +0000
108 +#ifndef _IPT_FUZZY_H
109 +#define _IPT_FUZZY_H
111 +#include <linux/param.h>
112 +#include <linux/types.h>
114 +#define MAXFUZZYRATE 10000000
115 +#define MINFUZZYRATE 3
117 +struct ipt_fuzzy_info {
118 + u_int32_t minimum_rate;
119 + u_int32_t maximum_rate;
120 + u_int32_t packets_total;
121 + u_int32_t bytes_total;
122 + u_int32_t previous_time;
123 + u_int32_t present_time;
124 + u_int32_t mean_rate;
125 + u_int8_t acceptance_rate;
128 +#endif /*_IPT_FUZZY_H*/
129 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_ipv4options.h
130 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 00:00:00.000000000 +0000
131 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_ipv4options.h 2004-03-04 08:39:31.000000000 +0000
133 +#ifndef __ipt_ipv4options_h_included__
134 +#define __ipt_ipv4options_h_included__
136 +#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
137 +#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
138 +#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
139 +#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
140 +#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
141 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
142 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
143 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
144 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
145 +#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
146 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
148 +struct ipt_ipv4options_info {
153 +#endif /* __ipt_ipv4options_h_included__ */
154 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_mport.h
155 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 00:00:00.000000000 +0000
156 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_mport.h 2004-03-04 08:39:33.000000000 +0000
158 +#ifndef _IPT_MPORT_H
159 +#define _IPT_MPORT_H
160 +#include <linux/netfilter_ipv4/ip_tables.h>
162 +#define IPT_MPORT_SOURCE (1<<0)
163 +#define IPT_MPORT_DESTINATION (1<<1)
164 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
166 +#define IPT_MULTI_PORTS 15
168 +/* Must fit inside union ipt_matchinfo: 32 bytes */
169 +/* every entry in ports[] except for the last one has one bit in pflags
170 + * associated with it. If this bit is set, the port is the first port of
171 + * a portrange, with the next entry being the last.
172 + * End of list is marked with pflags bit set and port=65535.
173 + * If 14 ports are used (last one does not have a pflag), the last port
174 + * is repeated to fill the last entry in ports[] */
177 + u_int8_t flags:2; /* Type of comparison */
178 + u_int16_t pflags:14; /* Port flags */
179 + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
181 +#endif /*_IPT_MPORT_H*/
182 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_nth.h
183 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 00:00:00.000000000 +0000
184 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_nth.h 2004-03-04 08:39:34.000000000 +0000
189 +#include <linux/param.h>
190 +#include <linux/types.h>
192 +#ifndef IPT_NTH_NUM_COUNTERS
193 +#define IPT_NTH_NUM_COUNTERS 16
196 +struct ipt_nth_info {
204 +#endif /*_IPT_NTH_H*/
205 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_quota.h
206 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 00:00:00.000000000 +0000
207 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_quota.h 2004-03-04 08:39:36.000000000 +0000
209 +#ifndef _IPT_QUOTA_H
210 +#define _IPT_QUOTA_H
212 +/* print debug info in both kernel/netfilter module & iptable library */
213 +//#define DEBUG_IPT_QUOTA
215 +struct ipt_quota_info {
219 +#endif /*_IPT_QUOTA_H*/
220 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_realm.h
221 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_realm.h 1970-01-01 00:00:00.000000000 +0000
222 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_realm.h 2004-03-04 08:39:54.000000000 +0000
224 +#ifndef _IPT_REALM_H
225 +#define _IPT_REALM_H
227 +struct ipt_realm_info {
232 +#endif /*_IPT_REALM_H*/
233 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_sctp.h
234 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 00:00:00.000000000 +0000
235 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_sctp.h 2004-03-04 08:39:55.000000000 +0000
237 +#ifndef _IPT_SCTP_H_
238 +#define _IPT_SCTP_H_
240 +#define IPT_SCTP_SRC_PORTS 0x01
241 +#define IPT_SCTP_DEST_PORTS 0x02
242 +#define IPT_SCTP_CHUNK_TYPES 0x04
244 +#define IPT_SCTP_VALID_FLAGS 0x07
246 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
249 +struct ipt_sctp_flag_info {
250 + u_int8_t chunktype;
252 + u_int8_t flag_mask;
255 +#define IPT_NUM_SCTP_FLAGS 4
257 +struct ipt_sctp_info {
258 + u_int16_t dpts[2]; /* Min, Max */
259 + u_int16_t spts[2]; /* Min, Max */
261 + u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
263 +#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
264 +#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
265 +#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
267 + u_int32_t chunk_match_type;
268 + struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
272 + u_int32_t invflags;
275 +#define bytes(type) (sizeof(type) * 8)
277 +#define SCTP_CHUNKMAP_SET(chunkmap, type) \
279 + chunkmap[type / bytes(u_int32_t)] |= \
280 + 1 << (type % bytes(u_int32_t)); \
283 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
285 + chunkmap[type / bytes(u_int32_t)] &= \
286 + ~(1 << (type % bytes(u_int32_t))); \
289 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
291 + (chunkmap[type / bytes (u_int32_t)] & \
292 + (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
295 +#define SCTP_CHUNKMAP_RESET(chunkmap) \
298 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
302 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
305 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
306 + chunkmap[i] = ~0; \
309 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
312 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
313 + destmap[i] = srcmap[i]; \
316 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
320 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
321 + if (chunkmap[i]) { \
329 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
333 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
334 + if (chunkmap[i] != ~0) { \
342 +#endif /* _IPT_SCTP_H_ */
344 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_HL.h
345 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 00:00:00.000000000 +0000
346 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_HL.h 2004-03-04 08:39:25.000000000 +0000
348 +/* Hop Limit modification module for ip6tables
349 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
350 + * Based on HW's TTL module */
352 +#ifndef _IP6T_HOPLIMIT_H
353 +#define _IP6T_HOPLIMIT_H
356 + IP6T_HOPLIMIT_SET = 0,
361 +#define IP6T_HOPLIMIT_MAXMODE IP6T_HOPLIMIT_DEC
363 +struct ip6t_HOPLIMIT_info {
365 + u_int8_t hop_limit;
370 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_REJECT.h
371 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-03-04 06:16:34.000000000 +0000
372 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-03-04 08:39:28.000000000 +0000
374 #define _IP6T_REJECT_H
376 enum ip6t_reject_with {
377 - IP6T_ICMP_NET_UNREACHABLE,
378 - IP6T_ICMP_HOST_UNREACHABLE,
379 - IP6T_ICMP_PROT_UNREACHABLE,
380 - IP6T_ICMP_PORT_UNREACHABLE,
381 - IP6T_ICMP_ECHOREPLY
382 + IP6T_ICMP6_NO_ROUTE,
383 + IP6T_ICMP6_ADM_PROHIBITED,
384 + IP6T_ICMP6_NOT_NEIGHBOUR,
385 + IP6T_ICMP6_ADDR_UNREACH,
386 + IP6T_ICMP6_PORT_UNREACH,
387 + IP6T_ICMP6_ECHOREPLY,
391 struct ip6t_reject_info {
392 enum ip6t_reject_with with; /* reject type */
395 -#endif /*_IPT_REJECT_H*/
396 +#endif /*_IP6T_REJECT_H*/
397 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_fuzzy.h
398 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 00:00:00.000000000 +0000
399 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2004-03-04 08:39:30.000000000 +0000
401 +#ifndef _IP6T_FUZZY_H
402 +#define _IP6T_FUZZY_H
404 +#include <linux/param.h>
405 +#include <linux/types.h>
407 +#define MAXFUZZYRATE 10000000
408 +#define MINFUZZYRATE 3
410 +struct ip6t_fuzzy_info {
411 + u_int32_t minimum_rate;
412 + u_int32_t maximum_rate;
413 + u_int32_t packets_total;
414 + u_int32_t bytes_total;
415 + u_int32_t previous_time;
416 + u_int32_t present_time;
417 + u_int32_t mean_rate;
418 + u_int8_t acceptance_rate;
421 +#endif /*_IP6T_FUZZY_H*/
422 diff -Nur linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_nth.h
423 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 00:00:00.000000000 +0000
424 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_nth.h 2004-03-04 08:39:34.000000000 +0000
429 +#include <linux/param.h>
430 +#include <linux/types.h>
432 +#ifndef IP6T_NTH_NUM_COUNTERS
433 +#define IP6T_NTH_NUM_COUNTERS 16
436 +struct ip6t_nth_info {
444 +#endif /*_IP6T_NTH_H*/
445 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/Kconfig linux-2.6.4-rc2/net/ipv4/netfilter/Kconfig
446 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/Kconfig 2004-03-04 06:16:58.000000000 +0000
447 +++ linux-2.6.4-rc2/net/ipv4/netfilter/Kconfig 2004-03-04 08:39:55.000000000 +0000
450 To compile it as a module, choose M here. If unsure, say N.
452 +config IP_NF_TARGET_IPV4OPTSSTRIP
453 + tristate 'IPV4OPTSSTRIP target support'
454 + depends on IP_NF_MANGLE
457 +config IP_NF_TARGET_TTL
458 + tristate 'TTL target support'
459 + depends on IP_NF_MANGLE
462 +config IP_NF_MATCH_CONNLIMIT
463 + tristate 'Connections/IP limit match support'
464 + depends on IP_NF_IPTABLES
467 +config IP_NF_MATCH_DSTLIMIT
468 + tristate 'dstlimit match support'
469 + depends on IP_NF_IPTABLES
472 +config IP_NF_MATCH_FUZZY
473 + tristate 'fuzzy match support'
474 + depends on IP_NF_IPTABLES
477 +config IP_NF_MATCH_IPV4OPTIONS
478 + tristate 'IPV4OPTIONS match support'
479 + depends on IP_NF_IPTABLES
482 +config IP_NF_MATCH_MPORT
483 + tristate 'Multiple port with ranges match support'
484 + depends on IP_NF_IPTABLES
487 +config IP_NF_MATCH_NTH
488 + tristate 'Nth match support'
489 + depends on IP_NF_IPTABLES
492 +config IP_NF_MATCH_QUOTA
493 + tristate 'quota match support'
494 + depends on IP_NF_IPTABLES
497 +config IP_NF_MATCH_REALM
498 + tristate 'realm match support'
499 + depends on IP_NF_IPTABLES && NET_CLS_ROUTE
502 +config IP_NF_MATCH_SCTP
503 + tristate 'SCTP protocol match support'
504 + depends on IP_NF_IPTABLES
509 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/Makefile linux-2.6.4-rc2/net/ipv4/netfilter/Makefile
510 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/Makefile 2004-03-04 06:16:38.000000000 +0000
511 +++ linux-2.6.4-rc2/net/ipv4/netfilter/Makefile 2004-03-04 08:39:55.000000000 +0000
514 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
515 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
516 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
517 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
518 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
519 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
520 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
521 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
523 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
524 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
526 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
528 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
529 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
531 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
533 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
536 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
538 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
540 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
543 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
544 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
545 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
546 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
547 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
548 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
550 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
553 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
554 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
555 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
556 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
557 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
558 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
559 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
561 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_amanda.c linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_amanda.c
562 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_amanda.c 2004-03-04 06:16:50.000000000 +0000
563 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_amanda.c 2004-03-04 08:39:18.000000000 +0000
565 static int help(struct sk_buff *skb,
566 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
568 - struct ip_conntrack_expect exp;
569 + struct ip_conntrack_expect *exp;
570 struct ip_ct_amanda_expect *exp_amanda_info;
571 char *data, *data_limit, *tmp;
572 unsigned int dataoff, i;
575 data += strlen("CONNECT ");
577 - memset(&exp, 0, sizeof(exp));
578 - exp.tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
579 - exp.tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
580 - exp.tuple.dst.protonum = IPPROTO_TCP;
581 - exp.mask.src.ip = 0xFFFFFFFF;
582 - exp.mask.dst.ip = 0xFFFFFFFF;
583 - exp.mask.dst.protonum = 0xFFFF;
584 - exp.mask.dst.u.tcp.port = 0xFFFF;
585 + if (ip_conntrack_expect_alloc(&exp) < 0)
588 + exp->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
589 + exp->tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
590 + exp->tuple.dst.protonum = IPPROTO_TCP;
591 + exp->mask.src.ip = 0xFFFFFFFF;
592 + exp->mask.dst.ip = 0xFFFFFFFF;
593 + exp->mask.dst.protonum = 0xFFFF;
594 + exp->mask.dst.u.tcp.port = 0xFFFF;
596 /* Only search first line. */
597 if ((tmp = strchr(data, '\n')))
600 - exp_amanda_info = &exp.help.exp_amanda_info;
601 + exp_amanda_info = &exp->help.exp_amanda_info;
602 for (i = 0; i < ARRAY_SIZE(conns); i++) {
603 char *match = strstr(data, conns[i]);
606 if (exp_amanda_info->port == 0 || exp_amanda_info->len > 5)
609 - exp.tuple.dst.u.tcp.port = htons(exp_amanda_info->port);
610 - ip_conntrack_expect_related(ct, &exp);
611 + exp->tuple.dst.u.tcp.port = htons(exp_amanda_info->port);
612 + ip_conntrack_expect_related(exp, ct);
616 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_core.c
617 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-03-04 06:16:34.000000000 +0000
618 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_core.c 2004-03-04 08:39:20.000000000 +0000
619 @@ -691,42 +691,50 @@
620 struct ip_conntrack_expect *, tuple);
621 READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
623 - /* If master is not in hash table yet (ie. packet hasn't left
624 - this machine yet), how can other end know about expected?
625 - Hence these are not the droids you are looking for (if
626 - master ct never got confirmed, we'd hold a reference to it
627 - and weird things would happen to future packets). */
628 - if (expected && !is_confirmed(expected->expectant))
631 - /* Look up the conntrack helper for master connections only */
633 - conntrack->helper = ip_ct_find_helper(&repl_tuple);
635 - /* If the expectation is dying, then this is a loser. */
637 - && expected->expectant->helper->timeout
638 - && ! del_timer(&expected->timeout))
642 - DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
643 - conntrack, expected);
644 - /* Welcome, Mr. Bond. We've been expecting you... */
645 - IP_NF_ASSERT(master_ct(conntrack));
646 - __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
647 - conntrack->master = expected;
648 - expected->sibling = conntrack;
649 - LIST_DELETE(&ip_conntrack_expect_list, expected);
650 - expected->expectant->expecting--;
651 - nf_conntrack_get(&master_ct(conntrack)->infos[0]);
653 - atomic_inc(&ip_conntrack_count);
654 + /* If master is not in hash table yet (ie. packet hasn't left
655 + this machine yet), how can other end know about expected?
656 + Hence these are not the droids you are looking for (if
657 + master ct never got confirmed, we'd hold a reference to it
658 + and weird things would happen to future packets). */
659 + if (!is_confirmed(expected->expectant)) {
661 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
665 + /* Expectation is dying... */
666 + if (expected->expectant->helper->timeout
667 + && ! del_timer(&expected->timeout)) {
671 + DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
672 + conntrack, expected);
673 + /* Welcome, Mr. Bond. We've been expecting you... */
674 + IP_NF_ASSERT(master_ct(conntrack));
675 + __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
676 + conntrack->master = expected;
677 + expected->sibling = conntrack;
678 + LIST_DELETE(&ip_conntrack_expect_list, expected);
679 + expected->expectant->expecting--;
680 + nf_conntrack_get(&master_ct(conntrack)->infos[0]);
682 + /* this is a braindead... --pablo */
683 + atomic_inc(&ip_conntrack_count);
684 + WRITE_UNLOCK(&ip_conntrack_lock);
686 + if (expected->expectfn)
687 + expected->expectfn(conntrack);
691 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
693 +end: atomic_inc(&ip_conntrack_count);
694 WRITE_UNLOCK(&ip_conntrack_lock);
696 - if (expected && expected->expectfn)
697 - expected->expectfn(conntrack);
698 - return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
699 +ret: return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
702 /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
703 @@ -917,11 +925,53 @@
704 WRITE_UNLOCK(&ip_conntrack_lock);
708 +ip_conntrack_expect_alloc(struct ip_conntrack_expect **new)
710 + *new = (struct ip_conntrack_expect *)
711 + kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
713 + DEBUGP("expect_related: OOM allocating expect\n");
717 + /* tuple_cmp compares whole union, we have to initialized cleanly */
718 + memset(*new, 0, sizeof(struct ip_conntrack_expect));
724 +ip_conntrack_expect_insert(struct ip_conntrack_expect *new,
725 + struct ip_conntrack *related_to)
727 + DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
728 + new->expectant = related_to;
729 + new->sibling = NULL;
730 + atomic_set(&new->use, 1);
732 + /* add to expected list for this connection */
733 + list_add(&new->expected_list, &related_to->sibling_list);
734 + /* add to global list of expectations */
736 + list_prepend(&ip_conntrack_expect_list, &new->list);
737 + /* add and start timer if required */
738 + if (related_to->helper->timeout) {
739 + init_timer(&new->timeout);
740 + new->timeout.data = (unsigned long)new;
741 + new->timeout.function = expectation_timed_out;
742 + new->timeout.expires = jiffies +
743 + related_to->helper->timeout * HZ;
744 + add_timer(&new->timeout);
746 + related_to->expecting++;
749 /* Add a related connection. */
750 -int ip_conntrack_expect_related(struct ip_conntrack *related_to,
751 - struct ip_conntrack_expect *expect)
752 +int ip_conntrack_expect_related(struct ip_conntrack_expect *expect,
753 + struct ip_conntrack *related_to)
755 - struct ip_conntrack_expect *old, *new;
756 + struct ip_conntrack_expect *old;
759 WRITE_LOCK(&ip_conntrack_lock);
761 if (related_to->helper->timeout) {
762 if (!del_timer(&old->timeout)) {
763 /* expectation is dying. Fall through */
767 old->timeout.expires = jiffies +
768 related_to->helper->timeout * HZ;
769 @@ -951,10 +1001,10 @@
774 - WRITE_UNLOCK(&ip_conntrack_lock);
777 + WRITE_UNLOCK(&ip_conntrack_lock);
781 } else if (related_to->helper->max_expected &&
782 related_to->expecting >= related_to->helper->max_expected) {
783 struct list_head *cur_item;
785 related_to->helper->name,
786 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
787 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
791 DEBUGP("ip_conntrack: max number of expected "
792 @@ -1010,37 +1061,12 @@
794 WRITE_UNLOCK(&ip_conntrack_lock);
795 DEBUGP("expect_related: busy!\n");
801 - new = (struct ip_conntrack_expect *)
802 - kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
804 - WRITE_UNLOCK(&ip_conntrack_lock);
805 - DEBUGP("expect_relaed: OOM allocating expect\n");
809 - DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
810 - memcpy(new, expect, sizeof(*expect));
811 - new->expectant = related_to;
812 - new->sibling = NULL;
813 - atomic_set(&new->use, 1);
815 - /* add to expected list for this connection */
816 - list_add(&new->expected_list, &related_to->sibling_list);
817 - /* add to global list of expectations */
818 - list_prepend(&ip_conntrack_expect_list, &new->list);
819 - /* add and start timer if required */
820 - if (related_to->helper->timeout) {
821 - init_timer(&new->timeout);
822 - new->timeout.data = (unsigned long)new;
823 - new->timeout.function = expectation_timed_out;
824 - new->timeout.expires = jiffies +
825 - related_to->helper->timeout * HZ;
826 - add_timer(&new->timeout);
828 - related_to->expecting++;
830 +out: ip_conntrack_expect_insert(expect, related_to);
832 WRITE_UNLOCK(&ip_conntrack_lock);
834 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_ftp.c
835 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-03-04 06:16:55.000000000 +0000
836 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-03-04 08:39:18.000000000 +0000
838 int dir = CTINFO2DIR(ctinfo);
839 unsigned int matchlen, matchoff;
840 struct ip_ct_ftp_master *ct_ftp_info = &ct->help.ct_ftp_info;
841 - struct ip_conntrack_expect expect, *exp = &expect;
842 - struct ip_ct_ftp_expect *exp_ftp_info = &exp->help.exp_ftp_info;
843 + struct ip_conntrack_expect *exp;
844 + struct ip_ct_ftp_expect *exp_ftp_info;
849 DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
850 (int)matchlen, data + matchoff,
851 matchlen, ntohl(tcph.seq) + matchoff);
853 - memset(&expect, 0, sizeof(expect));
855 + /* Allocate expectation which will be inserted */
856 + if (ip_conntrack_expect_alloc(&exp) < 0)
859 + exp_ftp_info = &exp->help.exp_ftp_info;
861 /* Update the ftp info */
862 if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3])
864 exp->expectfn = NULL;
866 /* Ignore failure; should only happen with NAT */
867 - ip_conntrack_expect_related(ct, &expect);
868 + ip_conntrack_expect_related(exp, ct);
871 UNLOCK_BH(&ip_ftp_lock);
872 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_irc.c
873 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_irc.c 2004-03-04 06:16:55.000000000 +0000
874 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_irc.c 2004-03-04 08:39:18.000000000 +0000
877 char *data, *data_limit;
878 int dir = CTINFO2DIR(ctinfo);
879 - struct ip_conntrack_expect expect, *exp = &expect;
880 - struct ip_ct_irc_expect *exp_irc_info = &exp->help.exp_irc_info;
881 + struct ip_conntrack_expect *exp;
882 + struct ip_ct_irc_expect *exp_irc_info = NULL;
891 - memset(&expect, 0, sizeof(expect));
893 + if (ip_conntrack_expect_alloc(&exp) < 0)
896 + exp_irc_info = &exp->help.exp_irc_info;
898 /* save position of address in dcc string,
899 * necessary for NAT */
901 NIPQUAD(exp->tuple.dst.ip),
902 ntohs(exp->tuple.dst.u.tcp.port));
904 - ip_conntrack_expect_related(ct, &expect);
905 + ip_conntrack_expect_related(exp, ct);
908 } /* for .. NUM_DCCPROTO */
909 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_standalone.c
910 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-03-04 06:16:44.000000000 +0000
911 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-03-04 08:39:18.000000000 +0000
913 EXPORT_SYMBOL(ip_ct_find_proto);
914 EXPORT_SYMBOL(__ip_ct_find_proto);
915 EXPORT_SYMBOL(ip_ct_find_helper);
916 +EXPORT_SYMBOL(ip_conntrack_expect_alloc);
917 EXPORT_SYMBOL(ip_conntrack_expect_related);
918 EXPORT_SYMBOL(ip_conntrack_change_expect);
919 EXPORT_SYMBOL(ip_conntrack_unexpect_related);
920 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_standalone.c.orig linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_standalone.c.orig
921 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_standalone.c.orig 1970-01-01 00:00:00.000000000 +0000
922 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_standalone.c.orig 2004-03-04 06:16:44.000000000 +0000
924 +/* This file contains all the functions required for the standalone
925 + ip_conntrack module.
927 + These are not required by the compatibility layer.
930 +/* (C) 1999-2001 Paul `Rusty' Russell
931 + * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
933 + * This program is free software; you can redistribute it and/or modify
934 + * it under the terms of the GNU General Public License version 2 as
935 + * published by the Free Software Foundation.
938 +#include <linux/config.h>
939 +#include <linux/types.h>
940 +#include <linux/ip.h>
941 +#include <linux/netfilter.h>
942 +#include <linux/netfilter_ipv4.h>
943 +#include <linux/module.h>
944 +#include <linux/skbuff.h>
945 +#include <linux/proc_fs.h>
946 +#ifdef CONFIG_SYSCTL
947 +#include <linux/sysctl.h>
949 +#include <net/checksum.h>
951 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
952 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
954 +#include <linux/netfilter_ipv4/ip_conntrack.h>
955 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
956 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
957 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
958 +#include <linux/netfilter_ipv4/listhelp.h>
961 +#define DEBUGP printk
963 +#define DEBUGP(format, args...)
966 +MODULE_LICENSE("GPL");
968 +static int kill_proto(const struct ip_conntrack *i, void *data)
970 + return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
971 + *((u_int8_t *) data));
975 +print_tuple(char *buffer, const struct ip_conntrack_tuple *tuple,
976 + struct ip_conntrack_protocol *proto)
980 + len = sprintf(buffer, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
981 + NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
983 + len += proto->print_tuple(buffer + len, tuple);
988 +/* FIXME: Don't print source proto part. --RR */
990 +print_expect(char *buffer, const struct ip_conntrack_expect *expect)
994 + if (expect->expectant->helper->timeout)
995 + len = sprintf(buffer, "EXPECTING: %lu ",
996 + timer_pending(&expect->timeout)
997 + ? (expect->timeout.expires - jiffies)/HZ : 0);
999 + len = sprintf(buffer, "EXPECTING: - ");
1000 + len += sprintf(buffer + len, "use=%u proto=%u ",
1001 + atomic_read(&expect->use), expect->tuple.dst.protonum);
1002 + len += print_tuple(buffer + len, &expect->tuple,
1003 + __ip_ct_find_proto(expect->tuple.dst.protonum));
1004 + len += sprintf(buffer + len, "\n");
1008 +static unsigned int
1009 +print_conntrack(char *buffer, struct ip_conntrack *conntrack)
1012 + struct ip_conntrack_protocol *proto
1013 + = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
1014 + .tuple.dst.protonum);
1016 + len = sprintf(buffer, "%-8s %u %lu ",
1018 + conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
1019 + .tuple.dst.protonum,
1020 + timer_pending(&conntrack->timeout)
1021 + ? (conntrack->timeout.expires - jiffies)/HZ : 0);
1023 + len += proto->print_conntrack(buffer + len, conntrack);
1024 + len += print_tuple(buffer + len,
1025 + &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
1027 + if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
1028 + len += sprintf(buffer + len, "[UNREPLIED] ");
1029 + len += print_tuple(buffer + len,
1030 + &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
1032 + if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
1033 + len += sprintf(buffer + len, "[ASSURED] ");
1034 + len += sprintf(buffer + len, "use=%u ",
1035 + atomic_read(&conntrack->ct_general.use));
1036 + len += sprintf(buffer + len, "\n");
1041 +/* Returns true when finished. */
1043 +conntrack_iterate(const struct ip_conntrack_tuple_hash *hash,
1044 + char *buffer, off_t offset, off_t *upto,
1045 + unsigned int *len, unsigned int maxlen)
1047 + unsigned int newlen;
1048 + IP_NF_ASSERT(hash->ctrack);
1050 + MUST_BE_READ_LOCKED(&ip_conntrack_lock);
1052 + /* Only count originals */
1053 + if (DIRECTION(hash))
1056 + if ((*upto)++ < offset)
1059 + newlen = print_conntrack(buffer + *len, hash->ctrack);
1060 + if (*len + newlen > maxlen)
1062 + else *len += newlen;
1068 +list_conntracks(char *buffer, char **start, off_t offset, int length)
1071 + unsigned int len = 0;
1073 + struct list_head *e;
1075 + READ_LOCK(&ip_conntrack_lock);
1076 + /* Traverse hash; print originals then reply. */
1077 + for (i = 0; i < ip_conntrack_htable_size; i++) {
1078 + if (LIST_FIND(&ip_conntrack_hash[i], conntrack_iterate,
1079 + struct ip_conntrack_tuple_hash *,
1080 + buffer, offset, &upto, &len, length))
1084 + /* Now iterate through expecteds. */
1085 + READ_LOCK(&ip_conntrack_expect_tuple_lock);
1086 + list_for_each(e, &ip_conntrack_expect_list) {
1087 + unsigned int last_len;
1088 + struct ip_conntrack_expect *expect
1089 + = (struct ip_conntrack_expect *)e;
1090 + if (upto++ < offset) continue;
1093 + len += print_expect(buffer + len, expect);
1094 + if (len > length) {
1096 + goto finished_expects;
1101 + READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
1103 + READ_UNLOCK(&ip_conntrack_lock);
1105 + /* `start' hack - see fs/proc/generic.c line ~165 */
1106 + *start = (char *)((unsigned int)upto - offset);
1110 +static unsigned int ip_confirm(unsigned int hooknum,
1111 + struct sk_buff **pskb,
1112 + const struct net_device *in,
1113 + const struct net_device *out,
1114 + int (*okfn)(struct sk_buff *))
1116 + /* We've seen it coming out the other side: confirm it */
1117 + return ip_conntrack_confirm(*pskb);
1120 +static unsigned int ip_refrag(unsigned int hooknum,
1121 + struct sk_buff **pskb,
1122 + const struct net_device *in,
1123 + const struct net_device *out,
1124 + int (*okfn)(struct sk_buff *))
1126 + struct rtable *rt = (struct rtable *)(*pskb)->dst;
1128 + /* We've seen it coming out the other side: confirm */
1129 + if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
1132 + /* Local packets are never produced too large for their
1133 + interface. We degfragment them at LOCAL_OUT, however,
1134 + so we have to refragment them here. */
1135 + if ((*pskb)->len > dst_pmtu(&rt->u.dst) &&
1136 + !skb_shinfo(*pskb)->tso_size) {
1137 + /* No hook can be after us, so this should be OK. */
1138 + ip_fragment(*pskb, okfn);
1144 +static unsigned int ip_conntrack_local(unsigned int hooknum,
1145 + struct sk_buff **pskb,
1146 + const struct net_device *in,
1147 + const struct net_device *out,
1148 + int (*okfn)(struct sk_buff *))
1150 + /* root is playing with raw sockets. */
1151 + if ((*pskb)->len < sizeof(struct iphdr)
1152 + || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
1153 + if (net_ratelimit())
1154 + printk("ipt_hook: happy cracking.\n");
1157 + return ip_conntrack_in(hooknum, pskb, in, out, okfn);
1160 +/* Connection tracking may drop packets, but never alters them, so
1161 + make it the first hook. */
1162 +static struct nf_hook_ops ip_conntrack_in_ops = {
1163 + .hook = ip_conntrack_in,
1164 + .owner = THIS_MODULE,
1166 + .hooknum = NF_IP_PRE_ROUTING,
1167 + .priority = NF_IP_PRI_CONNTRACK,
1170 +static struct nf_hook_ops ip_conntrack_local_out_ops = {
1171 + .hook = ip_conntrack_local,
1172 + .owner = THIS_MODULE,
1174 + .hooknum = NF_IP_LOCAL_OUT,
1175 + .priority = NF_IP_PRI_CONNTRACK,
1178 +/* Refragmenter; last chance. */
1179 +static struct nf_hook_ops ip_conntrack_out_ops = {
1180 + .hook = ip_refrag,
1181 + .owner = THIS_MODULE,
1183 + .hooknum = NF_IP_POST_ROUTING,
1184 + .priority = NF_IP_PRI_LAST,
1187 +static struct nf_hook_ops ip_conntrack_local_in_ops = {
1188 + .hook = ip_confirm,
1189 + .owner = THIS_MODULE,
1191 + .hooknum = NF_IP_LOCAL_IN,
1192 + .priority = NF_IP_PRI_LAST-1,
1195 +/* Sysctl support */
1197 +#ifdef CONFIG_SYSCTL
1199 +/* From ip_conntrack_core.c */
1200 +extern int ip_conntrack_max;
1201 +extern unsigned int ip_conntrack_htable_size;
1203 +/* From ip_conntrack_proto_tcp.c */
1204 +extern unsigned long ip_ct_tcp_timeout_syn_sent;
1205 +extern unsigned long ip_ct_tcp_timeout_syn_recv;
1206 +extern unsigned long ip_ct_tcp_timeout_established;
1207 +extern unsigned long ip_ct_tcp_timeout_fin_wait;
1208 +extern unsigned long ip_ct_tcp_timeout_close_wait;
1209 +extern unsigned long ip_ct_tcp_timeout_last_ack;
1210 +extern unsigned long ip_ct_tcp_timeout_time_wait;
1211 +extern unsigned long ip_ct_tcp_timeout_close;
1213 +/* From ip_conntrack_proto_udp.c */
1214 +extern unsigned long ip_ct_udp_timeout;
1215 +extern unsigned long ip_ct_udp_timeout_stream;
1217 +/* From ip_conntrack_proto_icmp.c */
1218 +extern unsigned long ip_ct_icmp_timeout;
1220 +/* From ip_conntrack_proto_icmp.c */
1221 +extern unsigned long ip_ct_generic_timeout;
1223 +static struct ctl_table_header *ip_ct_sysctl_header;
1225 +static ctl_table ip_ct_sysctl_table[] = {
1227 + .ctl_name = NET_IPV4_NF_CONNTRACK_MAX,
1228 + .procname = "ip_conntrack_max",
1229 + .data = &ip_conntrack_max,
1230 + .maxlen = sizeof(int),
1232 + .proc_handler = &proc_dointvec,
1235 + .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS,
1236 + .procname = "ip_conntrack_buckets",
1237 + .data = &ip_conntrack_htable_size,
1238 + .maxlen = sizeof(unsigned int),
1240 + .proc_handler = &proc_dointvec,
1243 + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
1244 + .procname = "ip_conntrack_tcp_timeout_syn_sent",
1245 + .data = &ip_ct_tcp_timeout_syn_sent,
1246 + .maxlen = sizeof(unsigned int),
1248 + .proc_handler = &proc_dointvec_jiffies,
1251 + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
1252 + .procname = "ip_conntrack_tcp_timeout_syn_recv",
1253 + .data = &ip_ct_tcp_timeout_syn_recv,
1254 + .maxlen = sizeof(unsigned int),
1256 + .proc_handler = &proc_dointvec_jiffies,
1259 + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
1260 + .procname = "ip_conntrack_tcp_timeout_established",
1261 + .data = &ip_ct_tcp_timeout_established,
1262 + .maxlen = sizeof(unsigned int),
1264 + .proc_handler = &proc_dointvec_jiffies,
1267 + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
1268 + .procname = "ip_conntrack_tcp_timeout_fin_wait",
1269 + .data = &ip_ct_tcp_timeout_fin_wait,
1270 + .maxlen = sizeof(unsigned int),
1272 + .proc_handler = &proc_dointvec_jiffies,
1275 + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
1276 + .procname = "ip_conntrack_tcp_timeout_close_wait",
1277 + .data = &ip_ct_tcp_timeout_close_wait,
1278 + .maxlen = sizeof(unsigned int),
1280 + .proc_handler = &proc_dointvec_jiffies,
1283 + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
1284 + .procname = "ip_conntrack_tcp_timeout_last_ack",
1285 + .data = &ip_ct_tcp_timeout_last_ack,
1286 + .maxlen = sizeof(unsigned int),
1288 + .proc_handler = &proc_dointvec_jiffies,
1291 + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
1292 + .procname = "ip_conntrack_tcp_timeout_time_wait",
1293 + .data = &ip_ct_tcp_timeout_time_wait,
1294 + .maxlen = sizeof(unsigned int),
1296 + .proc_handler = &proc_dointvec_jiffies,
1299 + .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
1300 + .procname = "ip_conntrack_tcp_timeout_close",
1301 + .data = &ip_ct_tcp_timeout_close,
1302 + .maxlen = sizeof(unsigned int),
1304 + .proc_handler = &proc_dointvec_jiffies,
1307 + .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT,
1308 + .procname = "ip_conntrack_udp_timeout",
1309 + .data = &ip_ct_udp_timeout,
1310 + .maxlen = sizeof(unsigned int),
1312 + .proc_handler = &proc_dointvec_jiffies,
1315 + .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
1316 + .procname = "ip_conntrack_udp_timeout_stream",
1317 + .data = &ip_ct_udp_timeout_stream,
1318 + .maxlen = sizeof(unsigned int),
1320 + .proc_handler = &proc_dointvec_jiffies,
1323 + .ctl_name = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
1324 + .procname = "ip_conntrack_icmp_timeout",
1325 + .data = &ip_ct_icmp_timeout,
1326 + .maxlen = sizeof(unsigned int),
1328 + .proc_handler = &proc_dointvec_jiffies,
1331 + .ctl_name = NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT,
1332 + .procname = "ip_conntrack_generic_timeout",
1333 + .data = &ip_ct_generic_timeout,
1334 + .maxlen = sizeof(unsigned int),
1336 + .proc_handler = &proc_dointvec_jiffies,
1341 +#define NET_IP_CONNTRACK_MAX 2089
1343 +static ctl_table ip_ct_netfilter_table[] = {
1345 + .ctl_name = NET_IPV4_NETFILTER,
1346 + .procname = "netfilter",
1348 + .child = ip_ct_sysctl_table,
1351 + .ctl_name = NET_IP_CONNTRACK_MAX,
1352 + .procname = "ip_conntrack_max",
1353 + .data = &ip_conntrack_max,
1354 + .maxlen = sizeof(int),
1356 + .proc_handler = &proc_dointvec
1361 +static ctl_table ip_ct_ipv4_table[] = {
1363 + .ctl_name = NET_IPV4,
1364 + .procname = "ipv4",
1366 + .child = ip_ct_netfilter_table,
1371 +static ctl_table ip_ct_net_table[] = {
1373 + .ctl_name = CTL_NET,
1374 + .procname = "net",
1376 + .child = ip_ct_ipv4_table,
1381 +static int init_or_cleanup(int init)
1383 + struct proc_dir_entry *proc;
1386 + if (!init) goto cleanup;
1388 + ret = ip_conntrack_init();
1390 + goto cleanup_nothing;
1392 + proc = proc_net_create("ip_conntrack",0,list_conntracks);
1393 + if (!proc) goto cleanup_init;
1394 + proc->owner = THIS_MODULE;
1396 + ret = nf_register_hook(&ip_conntrack_in_ops);
1398 + printk("ip_conntrack: can't register pre-routing hook.\n");
1399 + goto cleanup_proc;
1401 + ret = nf_register_hook(&ip_conntrack_local_out_ops);
1403 + printk("ip_conntrack: can't register local out hook.\n");
1404 + goto cleanup_inops;
1406 + ret = nf_register_hook(&ip_conntrack_out_ops);
1408 + printk("ip_conntrack: can't register post-routing hook.\n");
1409 + goto cleanup_inandlocalops;
1411 + ret = nf_register_hook(&ip_conntrack_local_in_ops);
1413 + printk("ip_conntrack: can't register local in hook.\n");
1414 + goto cleanup_inoutandlocalops;
1416 +#ifdef CONFIG_SYSCTL
1417 + ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
1418 + if (ip_ct_sysctl_header == NULL) {
1419 + printk("ip_conntrack: can't register to sysctl.\n");
1427 +#ifdef CONFIG_SYSCTL
1428 + unregister_sysctl_table(ip_ct_sysctl_header);
1430 + nf_unregister_hook(&ip_conntrack_local_in_ops);
1431 + cleanup_inoutandlocalops:
1432 + nf_unregister_hook(&ip_conntrack_out_ops);
1433 + cleanup_inandlocalops:
1434 + nf_unregister_hook(&ip_conntrack_local_out_ops);
1436 + nf_unregister_hook(&ip_conntrack_in_ops);
1438 + proc_net_remove("ip_conntrack");
1440 + ip_conntrack_cleanup();
1445 +/* FIXME: Allow NULL functions and sub in pointers to generic for
1447 +int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
1450 + struct list_head *i;
1452 + WRITE_LOCK(&ip_conntrack_lock);
1453 + list_for_each(i, &protocol_list) {
1454 + if (((struct ip_conntrack_protocol *)i)->proto
1455 + == proto->proto) {
1461 + list_prepend(&protocol_list, proto);
1464 + WRITE_UNLOCK(&ip_conntrack_lock);
1468 +void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
1470 + WRITE_LOCK(&ip_conntrack_lock);
1472 + /* ip_ct_find_proto() returns proto_generic in case there is no protocol
1473 + * helper. So this should be enough - HW */
1474 + LIST_DELETE(&protocol_list, proto);
1475 + WRITE_UNLOCK(&ip_conntrack_lock);
1477 + /* Somebody could be still looking at the proto in bh. */
1478 + synchronize_net();
1480 + /* Remove all contrack entries for this protocol */
1481 + ip_ct_selective_cleanup(kill_proto, &proto->proto);
1484 +static int __init init(void)
1486 + return init_or_cleanup(1);
1489 +static void __exit fini(void)
1491 + init_or_cleanup(0);
1497 +/* Some modules need us, but don't depend directly on any symbol.
1498 + They should call this. */
1499 +void need_ip_conntrack(void)
1503 +EXPORT_SYMBOL(ip_conntrack_protocol_register);
1504 +EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
1505 +EXPORT_SYMBOL(invert_tuplepr);
1506 +EXPORT_SYMBOL(ip_conntrack_alter_reply);
1507 +EXPORT_SYMBOL(ip_conntrack_destroyed);
1508 +EXPORT_SYMBOL(ip_conntrack_get);
1509 +EXPORT_SYMBOL(need_ip_conntrack);
1510 +EXPORT_SYMBOL(ip_conntrack_helper_register);
1511 +EXPORT_SYMBOL(ip_conntrack_helper_unregister);
1512 +EXPORT_SYMBOL(ip_ct_selective_cleanup);
1513 +EXPORT_SYMBOL(ip_ct_refresh);
1514 +EXPORT_SYMBOL(ip_ct_find_proto);
1515 +EXPORT_SYMBOL(__ip_ct_find_proto);
1516 +EXPORT_SYMBOL(ip_ct_find_helper);
1517 +EXPORT_SYMBOL(ip_conntrack_expect_related);
1518 +EXPORT_SYMBOL(ip_conntrack_change_expect);
1519 +EXPORT_SYMBOL(ip_conntrack_unexpect_related);
1520 +EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
1521 +EXPORT_SYMBOL_GPL(ip_conntrack_expect_put);
1522 +EXPORT_SYMBOL(ip_conntrack_tuple_taken);
1523 +EXPORT_SYMBOL(ip_ct_gather_frags);
1524 +EXPORT_SYMBOL(ip_conntrack_htable_size);
1525 +EXPORT_SYMBOL(ip_conntrack_expect_list);
1526 +EXPORT_SYMBOL(ip_conntrack_lock);
1527 +EXPORT_SYMBOL(ip_conntrack_hash);
1528 +EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
1529 +EXPORT_SYMBOL_GPL(ip_conntrack_put);
1530 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_tftp.c linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_tftp.c
1531 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_tftp.c 2004-03-04 06:16:41.000000000 +0000
1532 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_tftp.c 2004-03-04 08:39:18.000000000 +0000
1534 enum ip_conntrack_info ctinfo)
1536 struct tftphdr tftph;
1537 - struct ip_conntrack_expect exp;
1538 + struct ip_conntrack_expect *exp;
1540 if (skb_copy_bits(skb, skb->nh.iph->ihl * 4 + sizeof(struct udphdr),
1541 &tftph, sizeof(tftph)) != 0)
1544 DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
1545 DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
1546 - memset(&exp, 0, sizeof(exp));
1548 - exp.tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
1549 - exp.mask.src.ip = 0xffffffff;
1550 - exp.mask.dst.ip = 0xffffffff;
1551 - exp.mask.dst.u.udp.port = 0xffff;
1552 - exp.mask.dst.protonum = 0xffff;
1553 - exp.expectfn = NULL;
1554 + if (ip_conntrack_expect_alloc(&exp) < 0)
1557 + exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
1558 + exp->mask.src.ip = 0xffffffff;
1559 + exp->mask.dst.ip = 0xffffffff;
1560 + exp->mask.dst.u.udp.port = 0xffff;
1561 + exp->mask.dst.protonum = 0xffff;
1562 + exp->expectfn = NULL;
1565 - DUMP_TUPLE(&exp.tuple);
1566 - DUMP_TUPLE(&exp.mask);
1567 - ip_conntrack_expect_related(ct, &exp);
1568 + DUMP_TUPLE(&exp->tuple);
1569 + DUMP_TUPLE(&exp->mask);
1570 + ip_conntrack_expect_related(exp, ct);
1573 DEBUGP("Unknown opcode\n");
1574 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
1575 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 00:00:00.000000000 +0000
1576 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2004-03-04 08:39:26.000000000 +0000
1579 + * Strip all IP options in the IP packet header.
1581 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
1582 + * This software is distributed under GNU GPL v2, 1991
1585 +#include <linux/module.h>
1586 +#include <linux/skbuff.h>
1587 +#include <linux/ip.h>
1588 +#include <net/checksum.h>
1590 +#include <linux/netfilter_ipv4/ip_tables.h>
1592 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
1593 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
1594 +MODULE_LICENSE("GPL");
1596 +static unsigned int
1597 +target(struct sk_buff **pskb,
1598 + const struct net_device *in,
1599 + const struct net_device *out,
1600 + unsigned int hooknum,
1601 + const void *targinfo,
1604 + struct iphdr *iph;
1605 + struct sk_buff *skb;
1606 + struct ip_options *opt;
1607 + unsigned char *optiph;
1610 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
1614 + iph = (*pskb)->nh.iph;
1615 + optiph = skb->nh.raw;
1616 + l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
1618 + /* if no options in packet then nothing to clear. */
1619 + if (iph->ihl * 4 == sizeof(struct iphdr))
1620 + return IPT_CONTINUE;
1622 + /* else clear all options */
1623 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
1624 + memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
1625 + opt = &(IPCB(skb)->opt);
1629 + skb->nfcache |= NFC_ALTERED;
1631 + return IPT_CONTINUE;
1635 +checkentry(const char *tablename,
1636 + const struct ipt_entry *e,
1638 + unsigned int targinfosize,
1639 + unsigned int hook_mask)
1641 + if (strcmp(tablename, "mangle")) {
1642 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1645 + /* nothing else to check because no parameters */
1649 +static struct ipt_target ipt_ipv4optsstrip_reg = {
1650 + .name = "IPV4OPTSSTRIP",
1652 + .checkentry = checkentry,
1653 + .me = THIS_MODULE };
1655 +static int __init init(void)
1657 + return ipt_register_target(&ipt_ipv4optsstrip_reg);
1660 +static void __exit fini(void)
1662 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
1667 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_TTL.c
1668 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 00:00:00.000000000 +0000
1669 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_TTL.c 2004-03-04 08:39:28.000000000 +0000
1671 +/* TTL modification target for IP tables
1672 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
1674 + * Version: $Revision$
1676 + * This software is distributed under the terms of GNU GPL
1679 +#include <linux/module.h>
1680 +#include <linux/skbuff.h>
1681 +#include <linux/ip.h>
1682 +#include <net/checksum.h>
1684 +#include <linux/netfilter_ipv4/ip_tables.h>
1685 +#include <linux/netfilter_ipv4/ipt_TTL.h>
1687 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
1688 +MODULE_DESCRIPTION("IP tables TTL modification module");
1689 +MODULE_LICENSE("GPL");
1691 +static unsigned int
1692 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
1693 + const struct net_device *out, unsigned int hooknum,
1694 + const void *targinfo, void *userinfo)
1696 + struct iphdr *iph;
1697 + const struct ipt_TTL_info *info = targinfo;
1698 + u_int16_t diffs[2];
1701 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
1704 + iph = (*pskb)->nh.iph;
1706 + switch (info->mode) {
1708 + new_ttl = info->ttl;
1711 + new_ttl = iph->ttl + info->ttl;
1712 + if (new_ttl > 255)
1716 + new_ttl = iph->ttl + info->ttl;
1721 + new_ttl = iph->ttl;
1725 + if (new_ttl != iph->ttl) {
1726 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
1727 + iph->ttl = new_ttl;
1728 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
1729 + iph->check = csum_fold(csum_partial((char *)diffs,
1731 + iph->check^0xFFFF));
1732 + (*pskb)->nfcache |= NFC_ALTERED;
1735 + return IPT_CONTINUE;
1738 +static int ipt_ttl_checkentry(const char *tablename,
1739 + const struct ipt_entry *e,
1741 + unsigned int targinfosize,
1742 + unsigned int hook_mask)
1744 + struct ipt_TTL_info *info = targinfo;
1746 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
1747 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
1749 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
1753 + if (strcmp(tablename, "mangle")) {
1754 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1758 + if (info->mode > IPT_TTL_MAXMODE) {
1759 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
1764 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
1765 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
1772 +static struct ipt_target ipt_TTL = {
1774 + .target = ipt_ttl_target,
1775 + .checkentry = ipt_ttl_checkentry,
1779 +static int __init init(void)
1781 + return ipt_register_target(&ipt_TTL);
1784 +static void __exit fini(void)
1786 + ipt_unregister_target(&ipt_TTL);
1791 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_connlimit.c
1792 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 00:00:00.000000000 +0000
1793 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_connlimit.c 2004-03-04 08:39:29.000000000 +0000
1796 + * netfilter module to limit the number of parallel tcp
1797 + * connections per IP address.
1798 + * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
1799 + * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
1800 + * only ignore TIME_WAIT or gone connections
1804 + * Kernel module to match connection tracking information.
1805 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
1807 +#include <linux/module.h>
1808 +#include <linux/skbuff.h>
1809 +#include <linux/list.h>
1810 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1811 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
1812 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
1813 +#include <linux/netfilter_ipv4/ip_tables.h>
1814 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
1818 +MODULE_LICENSE("GPL");
1820 +/* we'll save the tuples of all connections we care about */
1821 +struct ipt_connlimit_conn
1823 + struct list_head list;
1824 + struct ip_conntrack_tuple tuple;
1827 +struct ipt_connlimit_data {
1829 + struct list_head iphash[256];
1832 +static int ipt_iphash(u_int32_t addr)
1836 + hash = addr & 0xff;
1837 + hash ^= (addr >> 8) & 0xff;
1838 + hash ^= (addr >> 16) & 0xff;
1839 + hash ^= (addr >> 24) & 0xff;
1843 +static int count_them(struct ipt_connlimit_data *data,
1844 + u_int32_t addr, u_int32_t mask,
1845 + struct ip_conntrack *ct)
1848 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
1849 + "fin_wait", "time_wait", "close", "close_wait",
1850 + "last_ack", "listen" };
1852 + int addit = 1, matches = 0;
1853 + struct ip_conntrack_tuple tuple;
1854 + struct ip_conntrack_tuple_hash *found;
1855 + struct ipt_connlimit_conn *conn;
1856 + struct list_head *hash,*lh;
1858 + spin_lock(&data->lock);
1859 + tuple = ct->tuplehash[0].tuple;
1860 + hash = &data->iphash[ipt_iphash(addr & mask)];
1862 + /* check the saved connections */
1863 + for (lh = hash->next; lh != hash; lh = lh->next) {
1864 + conn = list_entry(lh,struct ipt_connlimit_conn,list);
1865 + found = ip_conntrack_find_get(&conn->tuple,ct);
1866 + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
1868 + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
1869 + /* Just to be sure we have it only once in the list.
1870 + We should'nt see tuples twice unless someone hooks this
1871 + into a table without "-p tcp --syn" */
1875 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
1876 + ipt_iphash(addr & mask),
1877 + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
1878 + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
1879 + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
1881 + if (NULL == found) {
1882 + /* this one is gone */
1884 + list_del(lh->next);
1888 + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
1889 + /* we don't care about connections which are
1890 + closed already -> ditch it */
1892 + list_del(lh->next);
1894 + nf_conntrack_put(&found->ctrack->infos[0]);
1897 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
1898 + /* same source IP address -> be counted! */
1901 + nf_conntrack_put(&found->ctrack->infos[0]);
1904 + /* save the new connection in our list */
1906 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
1907 + ipt_iphash(addr & mask),
1908 + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
1909 + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
1911 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
1914 + memset(conn,0,sizeof(*conn));
1915 + INIT_LIST_HEAD(&conn->list);
1916 + conn->tuple = tuple;
1917 + list_add(&conn->list,hash);
1920 + spin_unlock(&data->lock);
1925 +match(const struct sk_buff *skb,
1926 + const struct net_device *in,
1927 + const struct net_device *out,
1928 + const void *matchinfo,
1932 + const struct ipt_connlimit_info *info = matchinfo;
1933 + int connections, match;
1934 + struct ip_conntrack *ct;
1935 + enum ip_conntrack_info ctinfo;
1937 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
1939 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
1943 + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
1944 + if (-1 == connections) {
1945 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
1946 + *hotdrop = 1; /* let's free some memory :-) */
1949 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
1951 + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
1952 + "connections=%d limit=%d match=%s\n",
1953 + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
1954 + connections, info->limit, match ? "yes" : "no");
1960 +static int check(const char *tablename,
1961 + const struct ipt_ip *ip,
1963 + unsigned int matchsize,
1964 + unsigned int hook_mask)
1966 + struct ipt_connlimit_info *info = matchinfo;
1970 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
1973 + /* refuse anything but tcp */
1974 + if (ip->proto != IPPROTO_TCP)
1977 + /* init private data */
1978 + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
1979 + spin_lock_init(&(info->data->lock));
1980 + for (i = 0; i < 256; i++)
1981 + INIT_LIST_HEAD(&(info->data->iphash[i]));
1986 +static void destroy(void *matchinfo, unsigned int matchinfosize)
1988 + struct ipt_connlimit_info *info = matchinfo;
1989 + struct ipt_connlimit_conn *conn;
1990 + struct list_head *hash;
1994 + for (i = 0; i < 256; i++) {
1995 + hash = &(info->data->iphash[i]);
1996 + while (hash != hash->next) {
1997 + conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
1998 + list_del(hash->next);
2002 + kfree(info->data);
2005 +static struct ipt_match connlimit_match = {
2006 + .name = "connlimit",
2008 + .checkentry = &check,
2009 + .destroy = &destroy,
2013 +static int __init init(void)
2015 + return ipt_register_match(&connlimit_match);
2018 +static void __exit fini(void)
2020 + ipt_unregister_match(&connlimit_match);
2025 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_dstlimit.c
2026 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 00:00:00.000000000 +0000
2027 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_dstlimit.c 2004-03-04 08:39:30.000000000 +0000
2029 +/* iptables match extension to limit the number of packets per second
2030 + * seperately for each destination.
2032 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
2036 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
2038 + * based on ipt_limit.c by:
2039 + * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
2040 + * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
2041 + * Rusty Russell <rusty@rustcorp.com.au>
2043 + * The general idea is to create a hash table for every dstip and have a
2044 + * seperate limit counter per tuple. This way you can do something like 'limit
2045 + * the number of syn packets for each of my internal addresses.
2047 + * Ideally this would just be implemented as a general 'hash' match, which would
2048 + * allow us to attach any iptables target to it's hash buckets. But this is
2049 + * not possible in the current iptables architecture. As always, pkttables for
2050 + * 2.7.x will help ;)
2052 +#include <linux/module.h>
2053 +#include <linux/skbuff.h>
2054 +#include <linux/spinlock.h>
2055 +#include <linux/random.h>
2056 +#include <linux/jhash.h>
2057 +#include <linux/slab.h>
2058 +#include <linux/vmalloc.h>
2059 +#include <linux/tcp.h>
2060 +#include <linux/udp.h>
2061 +#include <linux/proc_fs.h>
2062 +#include <linux/seq_file.h>
2064 +#define ASSERT_READ_LOCK(x)
2065 +#define ASSERT_WRITE_LOCK(x)
2066 +#include <linux/netfilter_ipv4/lockhelp.h>
2067 +#include <linux/netfilter_ipv4/listhelp.h>
2069 +#include <linux/netfilter_ipv4/ip_tables.h>
2070 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
2072 +/* FIXME: this is just for IP_NF_ASSERRT */
2073 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2075 +#define MS2JIFFIES(x) ((x*HZ)/1000)
2077 +MODULE_LICENSE("GPL");
2078 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2079 +MODULE_DESCRIPTION("iptables match for limiting per destination");
2081 +/* need to declare this at the top */
2082 +static struct proc_dir_entry *dstlimit_procdir;
2083 +static struct file_operations dl_file_ops;
2085 +/* hash table crap */
2087 +struct dsthash_dst {
2093 +struct dsthash_ent {
2094 + /* static / read-only parts in the beginning */
2095 + struct list_head list;
2096 + struct dsthash_dst dst;
2098 + /* modified structure members in the end */
2099 + unsigned long expires; /* precalculated expiry time */
2101 + unsigned long prev; /* last modification */
2103 + u_int32_t credit_cap, cost;
2107 +struct ipt_dstlimit_htable {
2108 + struct list_head list; /* global list of all htables */
2111 + struct dstlimit_cfg cfg; /* config */
2113 + /* used internally */
2114 + spinlock_t lock; /* lock for list_head */
2115 + u_int32_t rnd; /* random seed for hash */
2116 + struct timer_list timer; /* timer for gc */
2117 + atomic_t count; /* number entries in table */
2119 + /* seq_file stuff */
2120 + struct proc_dir_entry *pde;
2122 + struct list_head hash[0]; /* hashtable itself */
2125 +DECLARE_RWLOCK(dstlimit_lock); /* protects htables list */
2126 +static LIST_HEAD(dstlimit_htables);
2127 +static kmem_cache_t *dstlimit_cachep;
2129 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
2131 + return (ent->dst.dst_ip == b->dst_ip
2132 + && ent->dst.port == b->port
2133 + && ent->dst.src_ip == b->src_ip);
2136 +static inline u_int32_t
2137 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
2139 + return (jhash_3words(dst->dst_ip, dst->port,
2140 + dst->src_ip, ht->rnd) % ht->cfg.size);
2143 +static inline struct dsthash_ent *
2144 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2146 + struct dsthash_ent *ent;
2147 + u_int32_t hash = hash_dst(ht, dst);
2148 + MUST_BE_LOCKED(&ht->lock);
2149 + ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
2153 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
2154 +static struct dsthash_ent *
2155 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2157 + struct dsthash_ent *ent;
2159 + /* initialize hash with random val at the time we allocate
2160 + * the first hashtable entry */
2162 + get_random_bytes(&ht->rnd, 4);
2164 + if (ht->cfg.max &&
2165 + atomic_read(&ht->count) >= ht->cfg.max) {
2166 + /* FIXME: do something. question is what.. */
2167 + if (net_ratelimit())
2168 + printk(KERN_WARNING
2169 + "ipt_dstlimit: max count of %u reached\n",
2174 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
2176 + if (net_ratelimit())
2178 + "ipt_dstlimit: can't allocate dsthash_ent\n");
2182 + atomic_inc(&ht->count);
2184 + ent->dst.dst_ip = dst->dst_ip;
2185 + ent->dst.port = dst->port;
2186 + ent->dst.src_ip = dst->src_ip;
2188 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
2194 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
2196 + MUST_BE_LOCKED(&ht->lock);
2198 + list_del(&ent->list);
2199 + kmem_cache_free(dstlimit_cachep, ent);
2200 + atomic_dec(&ht->count);
2202 +static void htable_gc(unsigned long htlong);
2204 +static int htable_create(struct ipt_dstlimit_info *minfo)
2207 + unsigned int size;
2208 + struct ipt_dstlimit_htable *hinfo;
2210 + if (minfo->cfg.size)
2211 + size = minfo->cfg.size;
2213 + size = (((num_physpages << PAGE_SHIFT) / 16384)
2214 + / sizeof(struct list_head));
2215 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
2220 + /* FIXME: don't use vmalloc() here or anywhere else -HW */
2221 + hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
2222 + + (sizeof(struct list_head) * size));
2224 + printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
2227 + minfo->hinfo = hinfo;
2229 + /* copy match config into hashtable config */
2230 + memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
2231 + hinfo->cfg.size = size;
2232 + if (!hinfo->cfg.max)
2233 + hinfo->cfg.max = 8 * hinfo->cfg.size;
2234 + else if (hinfo->cfg.max < hinfo->cfg.size)
2235 + hinfo->cfg.max = hinfo->cfg.size;
2237 + for (i = 0; i < hinfo->cfg.size; i++)
2238 + INIT_LIST_HEAD(&hinfo->hash[i]);
2240 + atomic_set(&hinfo->count, 0);
2241 + atomic_set(&hinfo->use, 1);
2243 + hinfo->lock = SPIN_LOCK_UNLOCKED;
2244 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
2245 + if (!hinfo->pde) {
2249 + hinfo->pde->proc_fops = &dl_file_ops;
2250 + hinfo->pde->data = hinfo;
2252 + init_timer(&hinfo->timer);
2253 + hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
2254 + hinfo->timer.data = (unsigned long )hinfo;
2255 + hinfo->timer.function = htable_gc;
2256 + add_timer(&hinfo->timer);
2258 + WRITE_LOCK(&dstlimit_lock);
2259 + list_add(&hinfo->list, &dstlimit_htables);
2260 + WRITE_UNLOCK(&dstlimit_lock);
2265 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
2270 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
2272 + return (jiffies >= he->expires);
2275 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
2276 + int (*select)(struct ipt_dstlimit_htable *ht,
2277 + struct dsthash_ent *he))
2281 + IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
2283 + /* lock hash table and iterate over it */
2284 + LOCK_BH(&ht->lock);
2285 + for (i = 0; i < ht->cfg.size; i++) {
2286 + struct dsthash_ent *dh, *n;
2287 + list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
2288 + if ((*select)(ht, dh))
2289 + __dsthash_free(ht, dh);
2292 + UNLOCK_BH(&ht->lock);
2295 +/* hash table garbage collector, run by timer */
2296 +static void htable_gc(unsigned long htlong)
2298 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
2300 + htable_selective_cleanup(ht, select_gc);
2302 + /* re-add the timer accordingly */
2303 + ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
2304 + add_timer(&ht->timer);
2307 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
2309 + /* remove timer, if it is pending */
2310 + if (timer_pending(&hinfo->timer))
2311 + del_timer(&hinfo->timer);
2313 + /* remove proc entry */
2314 + remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
2316 + htable_selective_cleanup(hinfo, select_all);
2320 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
2322 + struct ipt_dstlimit_htable *hinfo;
2324 + READ_LOCK(&dstlimit_lock);
2325 + list_for_each_entry(hinfo, &dstlimit_htables, list) {
2326 + if (!strcmp(name, hinfo->pde->name)) {
2327 + atomic_inc(&hinfo->use);
2328 + READ_UNLOCK(&dstlimit_lock);
2332 + READ_UNLOCK(&dstlimit_lock);
2337 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
2339 + if (atomic_dec_and_test(&hinfo->use)) {
2340 + WRITE_LOCK(&dstlimit_lock);
2341 + list_del(&hinfo->list);
2342 + WRITE_UNLOCK(&dstlimit_lock);
2343 + htable_destroy(hinfo);
2348 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
2349 + * see net/sched/sch_tbf.c in the linux source tree
2352 +/* Rusty: This is my (non-mathematically-inclined) understanding of
2353 + this algorithm. The `average rate' in jiffies becomes your initial
2354 + amount of credit `credit' and the most credit you can ever have
2355 + `credit_cap'. The `peak rate' becomes the cost of passing the
2358 + `prev' tracks the last packet hit: you gain one credit per jiffy.
2359 + If you get credit balance more than this, the extra credit is
2360 + discarded. Every time the match passes, you lose `cost' credits;
2361 + if you don't have that many, the test fails.
2363 + See Alexey's formal explanation in net/sched/sch_tbf.c.
2365 + To get the maximum range, we multiply by this factor (ie. you get N
2366 + credits per jiffy). We want to allow a rate as low as 1 per day
2367 + (slowest userspace tool allows), which means
2368 + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
2370 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
2372 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
2373 + * us the power of 2 below the theoretical max, so GCC simply does a
2375 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
2376 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
2377 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
2378 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
2379 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
2380 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
2382 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
2384 +/* Precision saver. */
2385 +static inline u_int32_t
2386 +user2credits(u_int32_t user)
2388 + /* If multiplying would overflow... */
2389 + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
2390 + /* Divide first. */
2391 + return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
2393 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
2396 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
2398 + dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
2399 + * CREDITS_PER_JIFFY;
2400 + if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
2401 + dh->rateinfo.credit = dh->rateinfo.credit_cap;
2405 +dstlimit_match(const struct sk_buff *skb,
2406 + const struct net_device *in,
2407 + const struct net_device *out,
2408 + const void *matchinfo,
2412 + struct ipt_dstlimit_info *r =
2413 + ((struct ipt_dstlimit_info *)matchinfo)->u.master;
2414 + struct ipt_dstlimit_htable *hinfo = r->hinfo;
2415 + unsigned long now = jiffies;
2416 + struct dsthash_ent *dh;
2417 + struct dsthash_dst dst;
2419 + memset(&dst, 0, sizeof(dst));
2421 + /* dest ip is always in hash */
2422 + dst.dst_ip = skb->nh.iph->daddr;
2424 + /* source ip only if respective hashmode, otherwise set to
2426 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
2427 + dst.src_ip = skb->nh.iph->saddr;
2429 + /* dest port only if respective mode */
2430 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
2433 + /* Must not be a fragment. */
2437 + /* Must be big enough to read ports (both UDP and TCP have
2438 + them at the start). */
2439 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
2440 + /* We've been asked to examine this packet, and we
2441 + can't. Hence, no choice but to drop. */
2446 + switch (skb->nh.iph->protocol) {
2447 + struct tcphdr *th;
2448 + struct udphdr *uh;
2450 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
2451 + dst.port = th->dest;
2454 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
2455 + dst.port = uh->dest;
2462 + LOCK_BH(&hinfo->lock);
2463 + dh = __dsthash_find(hinfo, &dst);
2465 + dh = __dsthash_alloc_init(hinfo, &dst);
2468 + /* enomem... don't match == DROP */
2469 + if (net_ratelimit())
2470 + printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
2471 + UNLOCK_BH(&hinfo->lock);
2475 + dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
2477 + dh->rateinfo.prev = jiffies;
2478 + dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
2479 + hinfo->cfg.burst);
2480 + dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
2481 + hinfo->cfg.burst);
2482 + dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
2484 + UNLOCK_BH(&hinfo->lock);
2488 + /* update expiration timeout */
2489 + dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
2491 + rateinfo_recalc(dh, now);
2492 + if (dh->rateinfo.credit >= dh->rateinfo.cost) {
2493 + /* We're underlimit. */
2494 + dh->rateinfo.credit -= dh->rateinfo.cost;
2495 + UNLOCK_BH(&hinfo->lock);
2499 + UNLOCK_BH(&hinfo->lock);
2501 + /* default case: we're overlimit, thus don't match */
2506 +dstlimit_checkentry(const char *tablename,
2507 + const struct ipt_ip *ip,
2509 + unsigned int matchsize,
2510 + unsigned int hook_mask)
2512 + struct ipt_dstlimit_info *r = matchinfo;
2514 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
2517 + /* Check for overflow. */
2518 + if (r->cfg.burst == 0
2519 + || user2credits(r->cfg.avg * r->cfg.burst) <
2520 + user2credits(r->cfg.avg)) {
2521 + printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
2522 + r->cfg.avg, r->cfg.burst);
2526 + if (r->cfg.mode == 0
2527 + || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
2528 + |IPT_DSTLIMIT_HASH_DIP
2529 + |IPT_DSTLIMIT_HASH_SIP))
2532 + if (!r->cfg.gc_interval)
2535 + if (!r->cfg.expire)
2538 + r->hinfo = htable_find_get(r->name);
2539 + if (!r->hinfo && (htable_create(r) != 0)) {
2543 + /* Ugly hack: For SMP, we only want to use one set */
2550 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
2552 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
2554 + htable_put(r->hinfo);
2557 +static struct ipt_match ipt_dstlimit = {
2558 + .list = { .prev = NULL, .next = NULL },
2559 + .name = "dstlimit",
2560 + .match = dstlimit_match,
2561 + .checkentry = dstlimit_checkentry,
2562 + .destroy = dstlimit_destroy,
2568 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
2570 + struct proc_dir_entry *pde = s->private;
2571 + struct ipt_dstlimit_htable *htable = pde->data;
2572 + unsigned int *bucket;
2574 + LOCK_BH(&htable->lock);
2575 + if (*pos >= htable->cfg.size)
2578 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
2580 + return ERR_PTR(-ENOMEM);
2586 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
2588 + struct proc_dir_entry *pde = s->private;
2589 + struct ipt_dstlimit_htable *htable = pde->data;
2590 + unsigned int *bucket = (unsigned int *)v;
2592 + *pos = ++(*bucket);
2593 + if (*pos >= htable->cfg.size) {
2600 +static void dl_seq_stop(struct seq_file *s, void *v)
2602 + struct proc_dir_entry *pde = s->private;
2603 + struct ipt_dstlimit_htable *htable = pde->data;
2604 + unsigned int *bucket = (unsigned int *)v;
2608 + UNLOCK_BH(&htable->lock);
2611 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
2613 + /* recalculate to show accurate numbers */
2614 + rateinfo_recalc(ent, jiffies);
2616 + return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
2617 + (ent->expires - jiffies)/HZ,
2618 + NIPQUAD(ent->dst.src_ip),
2619 + NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
2620 + ent->rateinfo.credit, ent->rateinfo.credit_cap,
2621 + ent->rateinfo.cost);
2624 +static int dl_seq_show(struct seq_file *s, void *v)
2626 + struct proc_dir_entry *pde = s->private;
2627 + struct ipt_dstlimit_htable *htable = pde->data;
2628 + unsigned int *bucket = (unsigned int *)v;
2630 + if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
2631 + struct dsthash_ent *, s)) {
2632 + /* buffer was filled and unable to print that tuple */
2638 +static struct seq_operations dl_seq_ops = {
2639 + .start = dl_seq_start,
2640 + .next = dl_seq_next,
2641 + .stop = dl_seq_stop,
2642 + .show = dl_seq_show
2645 +static int dl_proc_open(struct inode *inode, struct file *file)
2647 + int ret = seq_open(file, &dl_seq_ops);
2650 + struct seq_file *sf = file->private_data;
2651 + sf->private = PDE(inode);
2656 +static struct file_operations dl_file_ops = {
2657 + .owner = THIS_MODULE,
2658 + .open = dl_proc_open,
2660 + .llseek = seq_lseek,
2661 + .release = seq_release
2664 +static int init_or_fini(int fini)
2671 + if (ipt_register_match(&ipt_dstlimit)) {
2673 + goto cleanup_nothing;
2676 + /* FIXME: do we really want HWCACHE_ALIGN since our objects are
2677 + * quite small ? */
2678 + dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
2679 + sizeof(struct dsthash_ent), 0,
2680 + SLAB_HWCACHE_ALIGN, NULL, NULL);
2681 + if (!dstlimit_cachep) {
2682 + printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
2684 + goto cleanup_unreg_match;
2687 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
2688 + if (!dstlimit_procdir) {
2689 + printk(KERN_ERR "Unable to create proc dir entry\n");
2691 + goto cleanup_free_slab;
2697 + remove_proc_entry("ipt_dstlimit", proc_net);
2699 + kmem_cache_destroy(dstlimit_cachep);
2700 +cleanup_unreg_match:
2701 + ipt_unregister_match(&ipt_dstlimit);
2707 +static int __init init(void)
2709 + return init_or_fini(0);
2712 +static void __exit fini(void)
2719 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_fuzzy.c
2720 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_fuzzy.c 1970-01-01 00:00:00.000000000 +0000
2721 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_fuzzy.c 2004-03-04 08:39:30.000000000 +0000
2724 + * This module implements a simple TSK FLC
2725 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
2726 + * to limit , in an adaptive and flexible way , the packet rate crossing
2727 + * a given stream . It serves as an initial and very simple (but effective)
2728 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
2729 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
2730 + * into our code in a precise , adaptive and efficient manner.
2731 + * The goal is very similar to that of "limit" match , but using techniques of
2732 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
2733 + * avoiding over and undershoots - and stuff like that .
2736 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
2737 + * 2002-08-17 : Changed to eliminate floating point operations .
2738 + * 2002-08-23 : Coding style changes .
2741 +#include <linux/module.h>
2742 +#include <linux/skbuff.h>
2743 +#include <linux/ip.h>
2744 +#include <linux/random.h>
2745 +#include <net/tcp.h>
2746 +#include <linux/spinlock.h>
2747 +#include <linux/netfilter_ipv4/ip_tables.h>
2748 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
2751 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
2752 + Expressed in percentage
2755 +#define PAR_LOW 1/100
2758 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
2760 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
2761 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
2762 +MODULE_LICENSE("GPL");
2764 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
2772 + return ( (100*(tx-mini)) / (maxi-mini) );
2775 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
2783 + return ( (100*( maxi - tx )) / ( maxi - mini ) );
2787 +ipt_fuzzy_match(const struct sk_buff *pskb,
2788 + const struct net_device *in,
2789 + const struct net_device *out,
2790 + const void *matchinfo,
2794 + /* From userspace */
2796 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
2798 + u_int8_t random_number;
2799 + unsigned long amount;
2800 + u_int8_t howhigh, howlow;
2803 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
2805 + info->bytes_total += pskb->len;
2806 + info->packets_total++;
2808 + info->present_time = jiffies;
2810 + if (info->present_time >= info->previous_time)
2811 + amount = info->present_time - info->previous_time;
2813 + /* There was a transition : I choose to re-sample
2814 + and keep the old acceptance rate...
2818 + info->previous_time = info->present_time;
2819 + info->bytes_total = info->packets_total = 0;
2822 + if (amount > HZ/10) /* More than 100 ms elapsed ... */
2825 + info->mean_rate = (u_int32_t) ((HZ*info->packets_total) \
2828 + info->previous_time = info->present_time;
2829 + info->bytes_total = info->packets_total = 0;
2831 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
2832 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
2834 + info->acceptance_rate = (u_int8_t) \
2835 + (howhigh*PAR_LOW + PAR_HIGH*howlow);
2837 + /* In fact , the above defuzzification would require a denominator
2838 + proportional to (howhigh+howlow) but , in this particular case ,
2839 + that expression is constant .
2840 + An imediate consequence is that it isn't necessary to call
2841 + both mf_high and mf_low - but to keep things understandable ,
2846 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
2849 + if ( info->acceptance_rate < 100 )
2851 + get_random_bytes((void *)(&random_number), 1);
2853 + /* If within the acceptance , it can pass => don't match */
2854 + if (random_number <= (255 * info->acceptance_rate) / 100)
2857 + return 1; /* It can't pass ( It matches ) */
2860 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
2865 +ipt_fuzzy_checkentry(const char *tablename,
2866 + const struct ipt_ip *e,
2868 + unsigned int matchsize,
2869 + unsigned int hook_mask)
2872 + const struct ipt_fuzzy_info *info = matchinfo;
2874 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
2875 + printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
2876 + IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
2880 + if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
2881 + || (info->minimum_rate >= info->maximum_rate )) {
2882 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
2889 +static struct ipt_match ipt_fuzzy_reg = {
2891 + .match = ipt_fuzzy_match,
2892 + .checkentry = ipt_fuzzy_checkentry,
2896 +static int __init init(void)
2898 + return ipt_register_match(&ipt_fuzzy_reg);
2901 +static void __exit fini(void)
2903 + ipt_unregister_match(&ipt_fuzzy_reg);
2908 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_ipv4options.c
2909 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 00:00:00.000000000 +0000
2910 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_ipv4options.c 2004-03-04 08:39:31.000000000 +0000
2913 + This is a module which is used to match ipv4 options.
2914 + This file is distributed under the terms of the GNU General Public
2915 + License (GPL). Copies of the GPL can be obtained from:
2916 + ftp://prep.ai.mit.edu/pub/gnu/GPL
2918 + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
2919 + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
2920 + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
2921 + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
2922 + 19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
2925 +#include <linux/module.h>
2926 +#include <linux/skbuff.h>
2927 +#include <net/ip.h>
2929 +#include <linux/netfilter_ipv4/ip_tables.h>
2930 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
2932 +MODULE_LICENSE("GPL");
2933 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
2936 +match(const struct sk_buff *skb,
2937 + const struct net_device *in,
2938 + const struct net_device *out,
2939 + const void *matchinfo,
2943 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
2944 + const struct iphdr *iph = skb->nh.iph;
2945 + const struct ip_options *opt;
2947 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
2948 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
2950 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
2951 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
2952 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
2953 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
2954 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
2955 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
2960 + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
2961 + /* there are options, and we don't need to care which one */
2964 + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
2965 + /* there are options but we don't want any ! */
2970 + opt = &(IPCB(skb)->opt);
2972 + /* source routing */
2973 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
2974 + if (!((opt->srr) & (opt->is_strictroute)))
2977 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
2978 + if (!((opt->srr) & (!opt->is_strictroute)))
2981 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
2985 + /* record route */
2986 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
2990 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
2995 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
2999 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
3003 + /* router-alert option */
3004 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
3005 + if (!opt->router_alert)
3008 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
3009 + if (opt->router_alert)
3018 +checkentry(const char *tablename,
3019 + const struct ipt_ip *ip,
3021 + unsigned int matchsize,
3022 + unsigned int hook_mask)
3024 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
3025 + /* Check the size */
3026 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
3028 + /* Now check the coherence of the data ... */
3029 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
3030 + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
3031 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
3032 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
3033 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
3034 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
3035 + return 0; /* opposites */
3036 + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
3037 + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3038 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3039 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3040 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3041 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
3042 + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
3043 + return 0; /* opposites */
3044 + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
3045 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
3046 + return 0; /* cannot match in the same time loose and strict source routing */
3047 + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3048 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
3049 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
3050 + return 0; /* opposites */
3051 + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
3052 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
3053 + return 0; /* opposites */
3054 + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
3055 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
3056 + return 0; /* opposites */
3057 + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
3058 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
3059 + return 0; /* opposites */
3061 + /* everything looks ok. */
3065 +static struct ipt_match ipv4options_match = {
3066 + .name = "ipv4options",
3068 + .checkentry = checkentry,
3072 +static int __init init(void)
3074 + return ipt_register_match(&ipv4options_match);
3077 +static void __exit fini(void)
3079 + ipt_unregister_match(&ipv4options_match);
3084 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_mport.c
3085 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 00:00:00.000000000 +0000
3086 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_mport.c 2004-03-04 08:39:33.000000000 +0000
3088 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
3089 + the same place so we can treat them as equal. */
3090 +#include <linux/module.h>
3091 +#include <linux/types.h>
3092 +#include <linux/udp.h>
3093 +#include <linux/skbuff.h>
3095 +#include <linux/netfilter_ipv4/ipt_mport.h>
3096 +#include <linux/netfilter_ipv4/ip_tables.h>
3098 +MODULE_LICENSE("GPL");
3101 +#define duprintf(format, args...) printk(format , ## args)
3103 +#define duprintf(format, args...)
3106 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
3108 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
3112 + u_int16_t pflags = minfo->pflags;
3113 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
3117 + && minfo->ports[i] == 65535)
3120 + s = minfo->ports[i];
3123 + e = minfo->ports[++i];
3128 + if (minfo->flags & IPT_MPORT_SOURCE
3129 + && src >= s && src <= e)
3132 + if (minfo->flags & IPT_MPORT_DESTINATION
3133 + && dst >= s && dst <= e)
3141 +match(const struct sk_buff *skb,
3142 + const struct net_device *in,
3143 + const struct net_device *out,
3144 + const void *matchinfo,
3149 + const struct ipt_mport *minfo = matchinfo;
3154 + /* Must be big enough to read ports (both UDP and TCP have
3155 + them at the start). */
3156 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
3157 + /* We've been asked to examine this packet, and we
3158 + can't. Hence, no choice but to drop. */
3159 + duprintf("ipt_multiport:"
3160 + " Dropping evil offset=0 tinygram.\n");
3165 + return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
3168 +/* Called when user tries to insert an entry of this type. */
3170 +checkentry(const char *tablename,
3171 + const struct ipt_ip *ip,
3173 + unsigned int matchsize,
3174 + unsigned int hook_mask)
3176 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
3179 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
3180 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
3181 + && !(ip->invflags & IPT_INV_PROTO)
3182 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
3185 +static struct ipt_match mport_match = {
3188 + .checkentry = &checkentry,
3192 +static int __init init(void)
3194 + return ipt_register_match(&mport_match);
3197 +static void __exit fini(void)
3199 + ipt_unregister_match(&mport_match);
3204 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_nth.c
3205 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 00:00:00.000000000 +0000
3206 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_nth.c 2004-03-04 08:39:34.000000000 +0000
3209 + This is a module which is used for match support for every Nth packet
3210 + This file is distributed under the terms of the GNU General Public
3211 + License (GPL). Copies of the GPL can be obtained from:
3212 + ftp://prep.ai.mit.edu/pub/gnu/GPL
3214 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
3215 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
3216 + * added support for multiple counters
3217 + * added support for matching on individual packets
3218 + in the counter cycle
3219 + 2004-02-19 Harald Welte <laforge@netfilter.org>
3224 +#include <linux/module.h>
3225 +#include <linux/skbuff.h>
3226 +#include <linux/ip.h>
3227 +#include <net/tcp.h>
3228 +#include <linux/spinlock.h>
3229 +#include <linux/netfilter_ipv4/ip_tables.h>
3230 +#include <linux/netfilter_ipv4/ipt_nth.h>
3232 +MODULE_LICENSE("GPL");
3233 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
3236 + * State information.
3243 +static struct state states[IPT_NTH_NUM_COUNTERS];
3246 +ipt_nth_match(const struct sk_buff *pskb,
3247 + const struct net_device *in,
3248 + const struct net_device *out,
3249 + const void *matchinfo,
3253 + /* Parameters from userspace */
3254 + const struct ipt_nth_info *info = matchinfo;
3255 + unsigned counter = info->counter;
3256 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
3258 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3262 + spin_lock(&states[counter].lock);
3264 + /* Are we matching every nth packet?*/
3265 + if (info->packet == 0xFF)
3267 + /* We're matching every nth packet and only every nth packet*/
3268 + /* Do we match or invert match? */
3269 + if (info->not == 0)
3271 + if (states[counter].number == 0)
3273 + ++states[counter].number;
3276 + if (states[counter].number >= info->every)
3277 + states[counter].number = 0; /* reset the counter */
3279 + ++states[counter].number;
3284 + if (states[counter].number == 0)
3286 + ++states[counter].number;
3289 + if (states[counter].number >= info->every)
3290 + states[counter].number = 0;
3292 + ++states[counter].number;
3298 + /* We're using the --packet, so there must be a rule for every value */
3299 + if (states[counter].number == info->packet)
3301 + /* only increment the counter when a match happens */
3302 + if (states[counter].number >= info->every)
3303 + states[counter].number = 0; /* reset the counter */
3305 + ++states[counter].number;
3314 + spin_unlock(&states[counter].lock);
3318 + spin_unlock(&states[counter].lock);
3323 +ipt_nth_checkentry(const char *tablename,
3324 + const struct ipt_ip *e,
3326 + unsigned int matchsize,
3327 + unsigned int hook_mask)
3329 + /* Parameters from userspace */
3330 + const struct ipt_nth_info *info = matchinfo;
3331 + unsigned counter = info->counter;
3332 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
3334 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3338 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
3339 + printk("nth: matchsize %u != %u\n", matchsize,
3340 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
3344 + states[counter].number = info->startat;
3349 +static struct ipt_match ipt_nth_reg = {
3351 + .match = ipt_nth_match,
3352 + .checkentry = ipt_nth_checkentry,
3356 +static int __init init(void)
3360 + memset(&states, 0, sizeof(states));
3361 + for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
3362 + spin_lock_init(&(states[counter].lock));
3364 + return ipt_register_match(&ipt_nth_reg);
3367 +static void __exit fini(void)
3369 + ipt_unregister_match(&ipt_nth_reg);
3374 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_quota.c
3375 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_quota.c 1970-01-01 00:00:00.000000000 +0000
3376 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_quota.c 2004-03-04 08:39:36.000000000 +0000
3379 + * netfilter module to enforce network quotas
3381 + * Sam Johnston <samj@samj.net>
3383 +#include <linux/module.h>
3384 +#include <linux/skbuff.h>
3385 +#include <linux/spinlock.h>
3386 +#include <linux/interrupt.h>
3388 +#include <linux/netfilter_ipv4/ip_tables.h>
3389 +#include <linux/netfilter_ipv4/ipt_quota.h>
3391 +MODULE_LICENSE("GPL");
3392 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
3394 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
3397 +match(const struct sk_buff *skb,
3398 + const struct net_device *in,
3399 + const struct net_device *out,
3400 + const void *matchinfo,
3401 + int offset, int *hotdrop)
3403 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
3404 + unsigned int datalen;
3406 + if (skb->len < sizeof(struct iphdr))
3409 + datalen = skb->len - skb->nh.iph->ihl*4;
3411 + spin_lock_bh("a_lock);
3413 + if (q->quota >= datalen) {
3414 + /* we can afford this one */
3415 + q->quota -= datalen;
3416 + spin_unlock_bh("a_lock);
3418 +#ifdef DEBUG_IPT_QUOTA
3419 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
3424 + /* so we do not allow even small packets from now on */
3427 +#ifdef DEBUG_IPT_QUOTA
3428 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
3431 + spin_unlock_bh("a_lock);
3436 +checkentry(const char *tablename,
3437 + const struct ipt_ip *ip,
3438 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
3440 + /* TODO: spinlocks? sanity checks? */
3441 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
3447 +static struct ipt_match quota_match = {
3450 + .checkentry = checkentry,
3457 + return ipt_register_match("a_match);
3463 + ipt_unregister_match("a_match);
3469 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_realm.c
3470 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_realm.c 1970-01-01 00:00:00.000000000 +0000
3471 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_realm.c 2004-03-04 08:39:54.000000000 +0000
3473 +/* Kernel module to match realm from routing. */
3474 +#include <linux/module.h>
3475 +#include <linux/skbuff.h>
3476 +#include <linux/netdevice.h>
3477 +#include <net/route.h>
3479 +#include <linux/netfilter_ipv4/ipt_realm.h>
3480 +#include <linux/netfilter_ipv4/ip_tables.h>
3482 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
3483 +MODULE_LICENSE("GPL");
3486 +match(const struct sk_buff *skb,
3487 + const struct net_device *in,
3488 + const struct net_device *out,
3489 + const void *matchinfo,
3493 + const struct ipt_realm_info *info = matchinfo;
3494 + struct dst_entry *dst = skb->dst;
3499 + id = dst->tclassid;
3501 + return (info->id == (id & info->mask)) ^ info->invert;
3504 +static int check(const char *tablename,
3505 + const struct ipt_ip *ip,
3507 + unsigned int matchsize,
3508 + unsigned int hook_mask)
3511 + & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
3512 + (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
3513 + printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
3514 + "LOCAL_IN or FORWARD.\n");
3518 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
3524 +static struct ipt_match realm_match = {
3527 + .checkentry = check,
3531 +static int __init init(void)
3533 + return ipt_register_match(&realm_match);
3536 +static void __exit fini(void)
3538 + ipt_unregister_match(&realm_match);
3543 diff -Nur linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_sctp.c
3544 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 00:00:00.000000000 +0000
3545 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_sctp.c 2004-03-04 08:39:55.000000000 +0000
3547 +#include <linux/module.h>
3548 +#include <linux/skbuff.h>
3549 +#include <net/ip.h>
3550 +#include <linux/sctp.h>
3552 +#include <linux/netfilter_ipv4/ip_tables.h>
3553 +#include <linux/netfilter_ipv4/ipt_sctp.h>
3556 +#define duprintf(format, args...) printk(format , ## args)
3558 +#define duprintf(format, args...)
3561 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
3562 + || (!!((invflag) & (option)) ^ (cond)))
3565 +match_flags(const struct ipt_sctp_flag_info *flag_info,
3566 + const int flag_count,
3567 + u_int8_t chunktype,
3568 + u_int8_t chunkflags)
3572 + for (i = 0; i < flag_count; i++) {
3573 + if (flag_info[i].chunktype == chunktype) {
3574 + return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
3582 +match_packet(const struct sk_buff *skb,
3583 + const u_int32_t *chunkmap,
3584 + int chunk_match_type,
3585 + const struct ipt_sctp_flag_info *flag_info,
3586 + const int flag_count,
3590 + u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
3591 + sctp_chunkhdr_t sch;
3593 + if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
3594 + SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
3597 + offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
3599 + if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
3600 + duprintf("Dropping invalid SCTP packet.\n");
3605 + duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
3606 + ++i, offset, sch.type, htons(sch.length), sch.flags);
3608 + offset += (htons(sch.length) + 3) & ~3;
3610 + duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
3612 + if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
3613 + switch (chunk_match_type) {
3614 + case SCTP_CHUNK_MATCH_ANY:
3615 + if (match_flags(flag_info, flag_count,
3616 + sch.type, sch.flags)) {
3621 + case SCTP_CHUNK_MATCH_ALL:
3622 + if (match_flags(flag_info, flag_count,
3623 + sch.type, sch.flags)) {
3624 + SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
3628 + case SCTP_CHUNK_MATCH_ONLY:
3629 + if (!match_flags(flag_info, flag_count,
3630 + sch.type, sch.flags)) {
3636 + switch (chunk_match_type) {
3637 + case SCTP_CHUNK_MATCH_ONLY:
3641 + } while (offset < skb->len);
3643 + switch (chunk_match_type) {
3644 + case SCTP_CHUNK_MATCH_ALL:
3645 + return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
3646 + case SCTP_CHUNK_MATCH_ANY:
3648 + case SCTP_CHUNK_MATCH_ONLY:
3652 + /* This will never be reached, but required to stop compiler whine */
3657 +match(const struct sk_buff *skb,
3658 + const struct net_device *in,
3659 + const struct net_device *out,
3660 + const void *matchinfo,
3664 + const struct ipt_sctp_info *info;
3665 + sctp_sctphdr_t sh;
3667 + info = (const struct ipt_sctp_info *)matchinfo;
3670 + duprintf("Dropping non-first fragment.. FIXME\n");
3674 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
3675 + duprintf("Dropping evil TCP offset=0 tinygram.\n");
3679 + duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
3681 + return SCCHECK(((ntohs(sh.source) >= info->spts[0])
3682 + && (ntohs(sh.source) <= info->spts[1])),
3683 + IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
3684 + && SCCHECK(((ntohs(sh.dest) >= info->dpts[0])
3685 + && (ntohs(sh.dest) <= info->dpts[1])),
3686 + IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
3687 + && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
3688 + info->flag_info, info->flag_count,
3690 + IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
3694 +checkentry(const char *tablename,
3695 + const struct ipt_ip *ip,
3697 + unsigned int matchsize,
3698 + unsigned int hook_mask)
3700 + const struct ipt_sctp_info *info;
3702 + info = (const struct ipt_sctp_info *)matchinfo;
3704 + return ip->proto == IPPROTO_SCTP
3705 + && !(ip->invflags & IPT_INV_PROTO)
3706 + && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
3707 + && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
3708 + && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
3709 + && !(info->invflags & ~info->flags)
3710 + && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) ||
3711 + (info->chunk_match_type &
3712 + (SCTP_CHUNK_MATCH_ALL
3713 + | SCTP_CHUNK_MATCH_ANY
3714 + | SCTP_CHUNK_MATCH_ONLY)));
3717 +static struct ipt_match sctp_match =
3719 + .list = { NULL, NULL},
3722 + .checkentry = &checkentry,
3727 +static int __init init(void)
3729 + return ipt_register_match(&sctp_match);
3732 +static void __exit fini(void)
3734 + ipt_unregister_match(&sctp_match);
3740 +MODULE_LICENSE("GPL");
3741 +MODULE_AUTHOR("Kiran Kumar Immidi");
3742 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
3744 diff -Nur linux-2.6.4-rc2.org/net/ipv6/netfilter/Kconfig linux-2.6.4-rc2/net/ipv6/netfilter/Kconfig
3745 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/Kconfig 2004-03-04 06:17:03.000000000 +0000
3746 +++ linux-2.6.4-rc2/net/ipv6/netfilter/Kconfig 2004-03-04 08:39:34.000000000 +0000
3747 @@ -218,5 +218,25 @@
3748 To compile it as a module, choose M here. If unsure, say N.
3750 #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
3751 +config IP6_NF_TARGET_HOPLIMIT
3752 + tristate 'HOPLIMIT target support'
3753 + depends on IP6_NF_MANGLE
3756 +config IP6_NF_TARGET_REJECT
3757 + tristate 'REJECT target support'
3758 + depends on IP6_NF_FILTER
3761 +config IP6_NF_MATCH_FUZZY
3762 + tristate 'Fuzzy match support'
3763 + depends on IP6_NF_FILTER
3766 +config IP6_NF_MATCH_NTH
3767 + tristate 'Nth match support'
3768 + depends on IP6_NF_IPTABLES
3773 diff -Nur linux-2.6.4-rc2.org/net/ipv6/netfilter/Makefile linux-2.6.4-rc2/net/ipv6/netfilter/Makefile
3774 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/Makefile 2004-03-04 06:16:48.000000000 +0000
3775 +++ linux-2.6.4-rc2/net/ipv6/netfilter/Makefile 2004-03-04 08:39:34.000000000 +0000
3777 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
3778 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
3779 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
3780 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
3781 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
3782 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
3783 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
3785 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
3786 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
3787 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
3788 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
3789 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
3790 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
3792 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
3793 +obj-$(CONFIG_IP6_NF_TARGET_HOPLIMIT) += ip6t_HL.o
3794 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
3795 diff -Nur linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_HL.c
3796 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 00:00:00.000000000 +0000
3797 +++ linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_HL.c 2004-03-04 08:39:25.000000000 +0000
3800 + * Hop Limit modification target for ip6tables
3801 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
3802 + * Based on HW's TTL module
3804 + * This software is distributed under the terms of GNU GPL
3807 +#include <linux/module.h>
3808 +#include <linux/skbuff.h>
3809 +#include <linux/ip.h>
3811 +#include <linux/netfilter_ipv6/ip6_tables.h>
3812 +#include <linux/netfilter_ipv6/ip6t_HL.h>
3814 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
3815 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
3816 +MODULE_LICENSE("GPL");
3818 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
3819 + const struct net_device *in, const struct net_device *out,
3820 + const void *targinfo, void *userinfo)
3822 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
3823 + const struct ip6t_HOPLIMIT_info *info = targinfo;
3824 + u_int16_t diffs[2];
3827 + switch (info->mode) {
3828 + case IP6T_HOPLIMIT_SET:
3829 + new_hl = info->hop_limit;
3831 + case IP6T_HOPLIMIT_INC:
3832 + new_hl = ip6h->hop_limit + info->hop_limit;
3836 + case IP6T_HOPLIMIT_DEC:
3837 + new_hl = ip6h->hop_limit + info->hop_limit;
3842 + new_hl = ip6h->hop_limit;
3846 + if (new_hl != ip6h->hop_limit) {
3847 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
3848 + ip6h->hop_limit = new_hl;
3849 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
3852 + return IP6T_CONTINUE;
3855 +static int ip6t_hl_checkentry(const char *tablename,
3856 + const struct ip6t_entry *e,
3858 + unsigned int targinfosize,
3859 + unsigned int hook_mask)
3861 + struct ip6t_HOPLIMIT_info *info = targinfo;
3863 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HOPLIMIT_info))) {
3864 + printk(KERN_WARNING "HOPLIMIT: targinfosize %u != %Zu\n",
3866 + IP6T_ALIGN(sizeof(struct ip6t_HOPLIMIT_info)));
3870 + if (strcmp(tablename, "mangle")) {
3871 + printk(KERN_WARNING "HOPLIMIT: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
3875 + if (info->mode > IP6T_HOPLIMIT_MAXMODE) {
3876 + printk(KERN_WARNING "HOPLIMIT: invalid or unknown Mode %u\n",
3881 + if ((info->mode != IP6T_HOPLIMIT_SET) && (info->hop_limit == 0)) {
3882 + printk(KERN_WARNING "HOPLIMIT: increment/decrement doesn't make sense with value 0\n");
3889 +static struct ip6t_target ip6t_HOPLIMIT = { { NULL, NULL }, "HL",
3890 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
3892 +static int __init init(void)
3894 + return ip6t_register_target(&ip6t_HOPLIMIT);
3897 +static void __exit fini(void)
3899 + ip6t_unregister_target(&ip6t_HOPLIMIT);
3904 diff -Nur linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_REJECT.c
3905 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 00:00:00.000000000 +0000
3906 +++ linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_REJECT.c 2004-03-04 08:39:28.000000000 +0000
3909 + * This is a module which is used for rejecting packets.
3910 + * Added support for customized reject packets (Jozsef Kadlecsik).
3912 + * Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
3914 +#include <linux/config.h>
3915 +#include <linux/module.h>
3916 +#include <linux/skbuff.h>
3917 +#include <linux/icmpv6.h>
3918 +#include <net/tcp.h>
3919 +#include <linux/netfilter_ipv6/ip6_tables.h>
3920 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
3923 +#define DEBUGP printk
3925 +#define DEBUGP(format, args...)
3929 +/* Send RST reply */
3930 +static void send_reset(struct sk_buff *oldskb)
3932 + struct sk_buff *nskb;
3933 + struct tcphdr *otcph, *tcph;
3934 + struct rtable *rt;
3935 + unsigned int otcplen;
3938 + /* IP header checks: fragment, too short. */
3939 + if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
3940 + || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
3943 + otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
3944 + otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
3946 + /* No RST for RST. */
3950 + /* Check checksum. */
3951 + if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
3952 + oldskb->nh.iph->daddr,
3953 + csum_partial((char *)otcph, otcplen, 0)) != 0)
3956 + /* Copy skb (even if skb is about to be dropped, we can't just
3957 + clone it because there may be other things, such as tcpdump,
3958 + interested in it) */
3959 + nskb = skb_copy(oldskb, GFP_ATOMIC);
3963 + /* This packet will not be the same as the other: clear nf fields */
3964 + nf_conntrack_put(nskb->nfct);
3965 + nskb->nfct = NULL;
3966 + nskb->nfcache = 0;
3967 +#ifdef CONFIG_NETFILTER_DEBUG
3968 + nskb->nf_debug = 0;
3971 + tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
3973 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
3974 + tcph->source = xchg(&tcph->dest, tcph->source);
3976 + /* Truncate to length (no data) */
3977 + tcph->doff = sizeof(struct tcphdr)/4;
3978 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
3979 + nskb->nh.iph->tot_len = htons(nskb->len);
3983 + tcph->seq = otcph->ack_seq;
3984 + tcph->ack_seq = 0;
3987 + tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
3988 + + otcplen - (otcph->doff<<2));
3993 + ((u_int8_t *)tcph)[13] = 0;
3995 + tcph->ack = needs_ack;
3998 + tcph->urg_ptr = 0;
4000 + /* Adjust TCP checksum */
4002 + tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
4003 + nskb->nh.iph->saddr,
4004 + nskb->nh.iph->daddr,
4005 + csum_partial((char *)tcph,
4006 + sizeof(struct tcphdr), 0));
4008 + /* Adjust IP TTL, DF */
4009 + nskb->nh.iph->ttl = MAXTTL;
4010 + /* Set DF, id = 0 */
4011 + nskb->nh.iph->frag_off = htons(IP_DF);
4012 + nskb->nh.iph->id = 0;
4014 + /* Adjust IP checksum */
4015 + nskb->nh.iph->check = 0;
4016 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
4017 + nskb->nh.iph->ihl);
4020 + if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
4021 + RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
4025 + dst_release(nskb->dst);
4026 + nskb->dst = &rt->u.dst;
4028 + /* "Never happens" */
4029 + if (nskb->len > nskb->dst->pmtu)
4032 + NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
4033 + ip_finish_output);
4041 +static unsigned int reject6_target(struct sk_buff **pskb,
4042 + unsigned int hooknum,
4043 + const struct net_device *in,
4044 + const struct net_device *out,
4045 + const void *targinfo,
4048 + const struct ip6t_reject_info *reject = targinfo;
4050 + /* WARNING: This code causes reentry within ip6tables.
4051 + This means that the ip6tables jump stack is now crap. We
4052 + must return an absolute verdict. --RR */
4053 + DEBUGP("REJECTv6: calling icmpv6_send\n");
4054 + switch (reject->with) {
4055 + case IP6T_ICMP6_NO_ROUTE:
4056 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
4058 + case IP6T_ICMP6_ADM_PROHIBITED:
4059 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
4061 + case IP6T_ICMP6_NOT_NEIGHBOUR:
4062 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
4064 + case IP6T_ICMP6_ADDR_UNREACH:
4065 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
4067 + case IP6T_ICMP6_PORT_UNREACH:
4068 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
4071 + case IPT_ICMP_ECHOREPLY: {
4072 + struct icmp6hdr *icmph = (struct icmphdr *)
4073 + ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
4074 + unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
4076 + /* Not non-head frags, or truncated */
4077 + if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
4078 + && datalen >= 4) {
4079 + /* Usually I don't like cut & pasting code,
4080 + but dammit, my party is starting in 45
4082 + struct icmp_bxm icmp_param;
4084 + icmp_param.icmph=*icmph;
4085 + icmp_param.icmph.type=ICMP_ECHOREPLY;
4086 + icmp_param.data_ptr=(icmph+1);
4087 + icmp_param.data_len=datalen;
4088 + icmp_reply(&icmp_param, *pskb);
4092 + case IPT_TCP_RESET:
4093 + send_reset(*pskb);
4097 + printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
4104 +static inline int find_ping_match(const struct ip6t_entry_match *m)
4106 + const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
4108 + if (strcmp(m->u.kernel.match->name, "icmp6") == 0
4109 + && icmpinfo->type == ICMPV6_ECHO_REQUEST
4110 + && !(icmpinfo->invflags & IP6T_ICMP_INV))
4116 +static int check(const char *tablename,
4117 + const struct ip6t_entry *e,
4119 + unsigned int targinfosize,
4120 + unsigned int hook_mask)
4122 + const struct ip6t_reject_info *rejinfo = targinfo;
4124 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
4125 + DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
4129 + /* Only allow these for packet filtering. */
4130 + if (strcmp(tablename, "filter") != 0) {
4131 + DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
4134 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
4135 + | (1 << NF_IP6_FORWARD)
4136 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
4137 + DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
4141 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
4142 + /* Must specify that it's an ICMP ping packet. */
4143 + if (e->ipv6.proto != IPPROTO_ICMPV6
4144 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
4145 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
4148 + /* Must contain ICMP match. */
4149 + if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
4150 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
4153 + } else if (rejinfo->with == IP6T_TCP_RESET) {
4154 + /* Must specify that it's a TCP packet */
4155 + if (e->ipv6.proto != IPPROTO_TCP
4156 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
4157 + DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
4165 +static struct ip6t_target ip6t_reject_reg
4166 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
4168 +static int __init init(void)
4170 + if (ip6t_register_target(&ip6t_reject_reg))
4175 +static void __exit fini(void)
4177 + ip6t_unregister_target(&ip6t_reject_reg);
4182 diff -Nur linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_fuzzy.c
4183 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 00:00:00.000000000 +0000
4184 +++ linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_fuzzy.c 2004-03-04 08:39:30.000000000 +0000
4187 + * This module implements a simple TSK FLC
4188 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
4189 + * to limit , in an adaptive and flexible way , the packet rate crossing
4190 + * a given stream . It serves as an initial and very simple (but effective)
4191 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
4192 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
4193 + * into our code in a precise , adaptive and efficient manner.
4194 + * The goal is very similar to that of "limit" match , but using techniques of
4195 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
4196 + * avoiding over and undershoots - and stuff like that .
4199 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
4200 + * 2002-08-17 : Changed to eliminate floating point operations .
4201 + * 2002-08-23 : Coding style changes .
4202 + * 2003-04-08 Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
4205 +#include <linux/module.h>
4206 +#include <linux/skbuff.h>
4207 +#include <linux/ipv6.h>
4208 +#include <linux/random.h>
4209 +#include <net/tcp.h>
4210 +#include <linux/spinlock.h>
4211 +#include <linux/netfilter_ipv6/ip6_tables.h>
4212 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
4215 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
4216 + Expressed in percentage
4219 +#define PAR_LOW 1/100
4222 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
4224 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
4225 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
4226 +MODULE_LICENSE("GPL");
4228 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
4230 + if (tx >= maxi) return 100;
4232 + if (tx <= mini) return 0;
4234 + return ((100 * (tx-mini)) / (maxi-mini));
4237 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
4239 + if (tx <= mini) return 100;
4241 + if (tx >= maxi) return 0;
4243 + return ((100 * (maxi - tx)) / (maxi - mini));
4248 +ip6t_fuzzy_match(const struct sk_buff *pskb,
4249 + const struct net_device *in,
4250 + const struct net_device *out,
4251 + const void *matchinfo,
4254 + u_int16_t datalen,
4257 + /* From userspace */
4259 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
4261 + u_int8_t random_number;
4262 + unsigned long amount;
4263 + u_int8_t howhigh, howlow;
4266 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
4268 + info->bytes_total += pskb->len;
4269 + info->packets_total++;
4271 + info->present_time = jiffies;
4273 + if (info->present_time >= info->previous_time)
4274 + amount = info->present_time - info->previous_time;
4276 + /* There was a transition : I choose to re-sample
4277 + and keep the old acceptance rate...
4281 + info->previous_time = info->present_time;
4282 + info->bytes_total = info->packets_total = 0;
4285 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
4287 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
4290 + info->previous_time = info->present_time;
4291 + info->bytes_total = info->packets_total = 0;
4293 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
4294 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
4296 + info->acceptance_rate = (u_int8_t) \
4297 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
4299 + /* In fact, the above defuzzification would require a denominator
4300 + * proportional to (howhigh+howlow) but, in this particular case,
4301 + * that expression is constant.
4302 + * An imediate consequence is that it is not necessary to call
4303 + * both mf_high and mf_low - but to keep things understandable,
4309 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
4312 + if (info->acceptance_rate < 100)
4314 + get_random_bytes((void *)(&random_number), 1);
4316 + /* If within the acceptance , it can pass => don't match */
4317 + if (random_number <= (255 * info->acceptance_rate) / 100)
4320 + return 1; /* It can't pass (It matches) */
4323 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
4328 +ip6t_fuzzy_checkentry(const char *tablename,
4329 + const struct ip6t_ip6 *ip,
4331 + unsigned int matchsize,
4332 + unsigned int hook_mask)
4335 + const struct ip6t_fuzzy_info *info = matchinfo;
4337 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
4338 + printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
4339 + IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
4343 + if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
4344 + || (info->minimum_rate >= info->maximum_rate)) {
4345 + printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
4352 +static struct ip6t_match ip6t_fuzzy_reg = {
4356 + ip6t_fuzzy_checkentry,
4360 +static int __init init(void)
4362 + if (ip6t_register_match(&ip6t_fuzzy_reg))
4368 +static void __exit fini(void)
4370 + ip6t_unregister_match(&ip6t_fuzzy_reg);
4375 diff -Nur linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_nth.c
4376 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 00:00:00.000000000 +0000
4377 +++ linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_nth.c 2004-03-04 08:39:34.000000000 +0000
4380 + This is a module which is used for match support for every Nth packet
4381 + This file is distributed under the terms of the GNU General Public
4382 + License (GPL). Copies of the GPL can be obtained from:
4383 + ftp://prep.ai.mit.edu/pub/gnu/GPL
4385 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
4386 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
4387 + * added support for multiple counters
4388 + * added support for matching on individual packets
4389 + in the counter cycle
4390 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
4394 +#include <linux/module.h>
4395 +#include <linux/skbuff.h>
4396 +#include <linux/ip.h>
4397 +#include <net/tcp.h>
4398 +#include <linux/spinlock.h>
4399 +#include <linux/netfilter_ipv6/ip6_tables.h>
4400 +#include <linux/netfilter_ipv6/ip6t_nth.h>
4402 +MODULE_LICENSE("GPL");
4405 + * State information.
4412 +static struct state states[IP6T_NTH_NUM_COUNTERS];
4415 +ip6t_nth_match(const struct sk_buff *pskb,
4416 + const struct net_device *in,
4417 + const struct net_device *out,
4418 + const void *matchinfo,
4421 + u_int16_t datalen,
4424 + /* Parameters from userspace */
4425 + const struct ip6t_nth_info *info = matchinfo;
4426 + unsigned counter = info->counter;
4427 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
4429 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
4433 + spin_lock(&states[counter].lock);
4435 + /* Are we matching every nth packet?*/
4436 + if (info->packet == 0xFF)
4438 + /* We're matching every nth packet and only every nth packet*/
4439 + /* Do we match or invert match? */
4440 + if (info->not == 0)
4442 + if (states[counter].number == 0)
4444 + ++states[counter].number;
4447 + if (states[counter].number >= info->every)
4448 + states[counter].number = 0; /* reset the counter */
4450 + ++states[counter].number;
4455 + if (states[counter].number == 0)
4457 + ++states[counter].number;
4460 + if (states[counter].number >= info->every)
4461 + states[counter].number = 0;
4463 + ++states[counter].number;
4469 + /* We're using the --packet, so there must be a rule for every value */
4470 + if (states[counter].number == info->packet)
4472 + /* only increment the counter when a match happens */
4473 + if (states[counter].number >= info->every)
4474 + states[counter].number = 0; /* reset the counter */
4476 + ++states[counter].number;
4485 + spin_unlock(&states[counter].lock);
4489 + spin_unlock(&states[counter].lock);
4494 +ip6t_nth_checkentry(const char *tablename,
4495 + const struct ip6t_ip6 *e,
4497 + unsigned int matchsize,
4498 + unsigned int hook_mask)
4500 + /* Parameters from userspace */
4501 + const struct ip6t_nth_info *info = matchinfo;
4502 + unsigned counter = info->counter;
4503 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
4505 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
4509 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
4510 + printk("nth: matchsize %u != %u\n", matchsize,
4511 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
4515 + states[counter].number = info->startat;
4520 +static struct ip6t_match ip6t_nth_reg = {
4524 + ip6t_nth_checkentry,
4528 +static int __init init(void)
4531 + memset(&states, 0, sizeof(states));
4532 + if (ip6t_register_match(&ip6t_nth_reg))
4535 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
4537 + spin_lock_init(&(states[counter].lock));
4540 + printk("ip6t_nth match loaded\n");
4544 +static void __exit fini(void)
4546 + ip6t_unregister_match(&ip6t_nth_reg);
4547 + printk("ip6t_nth match unloaded\n");