]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.x-patch-o-matic-ng-base-20040304.patch
+CONFIG_IP_NF_MATCH_LAYER7=m
[packages/kernel.git] / 2.6.x-patch-o-matic-ng-base-20040304.patch
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
4 @@ -35,9 +35,13 @@
5  
6  extern struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple);
7  
8 +
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
23 @@ -0,0 +1,21 @@
24 +/* TTL modification module for IP tables
25 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
26 +
27 +#ifndef _IPT_TTL_H
28 +#define _IPT_TTL_H
29 +
30 +enum {
31 +       IPT_TTL_SET = 0,
32 +       IPT_TTL_INC,
33 +       IPT_TTL_DEC
34 +};
35 +
36 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
37 +
38 +struct ipt_TTL_info {
39 +       u_int8_t        mode;
40 +       u_int8_t        ttl;
41 +};
42 +
43 +
44 +#endif
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
48 @@ -0,0 +1,12 @@
49 +#ifndef _IPT_CONNLIMIT_H
50 +#define _IPT_CONNLIMIT_H
51 +
52 +struct ipt_connlimit_data;
53 +
54 +struct ipt_connlimit_info {
55 +       int limit;
56 +       int inverse;
57 +       u_int32_t mask;
58 +       struct ipt_connlimit_data *data;
59 +};
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
64 @@ -0,0 +1,39 @@
65 +#ifndef _IPT_DSTLIMIT_H
66 +#define _IPT_DSTLIMIT_H
67 +
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. */
72 +
73 +/* details of this structure hidden by the implementation */
74 +struct ipt_dstlimit_htable;
75 +
76 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
77 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
78 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
79 +
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. */
84 +
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? */
90 +};
91 +
92 +struct ipt_dstlimit_info {
93 +       char name [IFNAMSIZ];           /* name */
94 +       struct dstlimit_cfg cfg;
95 +       struct ipt_dstlimit_htable *hinfo;
96 +
97 +       /* Used internally by the kernel */
98 +       union {
99 +               void *ptr;
100 +               struct ipt_dstlimit_info *master;
101 +       } u;
102 +};
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
107 @@ -0,0 +1,21 @@
108 +#ifndef _IPT_FUZZY_H
109 +#define _IPT_FUZZY_H
110 +
111 +#include <linux/param.h>
112 +#include <linux/types.h>
113 +
114 +#define MAXFUZZYRATE 10000000
115 +#define MINFUZZYRATE 3
116 +
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;
126 +};
127 +
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
132 @@ -0,0 +1,21 @@
133 +#ifndef __ipt_ipv4options_h_included__
134 +#define __ipt_ipv4options_h_included__
135 +
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 */
147 +
148 +struct ipt_ipv4options_info {
149 +       u_int16_t options;
150 +};
151 +
152 +
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
157 @@ -0,0 +1,24 @@
158 +#ifndef _IPT_MPORT_H
159 +#define _IPT_MPORT_H
160 +#include <linux/netfilter_ipv4/ip_tables.h>
161 +
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)
165 +
166 +#define IPT_MULTI_PORTS        15
167 +
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[] */
175 +struct ipt_mport
176 +{
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 */
180 +};
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
185 @@ -0,0 +1,19 @@
186 +#ifndef _IPT_NTH_H
187 +#define _IPT_NTH_H
188 +
189 +#include <linux/param.h>
190 +#include <linux/types.h>
191 +
192 +#ifndef IPT_NTH_NUM_COUNTERS
193 +#define IPT_NTH_NUM_COUNTERS 16
194 +#endif
195 +
196 +struct ipt_nth_info {
197 +       u_int8_t every;
198 +       u_int8_t not;
199 +       u_int8_t startat;
200 +       u_int8_t counter;
201 +       u_int8_t packet;
202 +};
203 +
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
208 @@ -0,0 +1,11 @@
209 +#ifndef _IPT_QUOTA_H
210 +#define _IPT_QUOTA_H
211 +
212 +/* print debug info in both kernel/netfilter module & iptable library */
213 +//#define DEBUG_IPT_QUOTA
214 +
215 +struct ipt_quota_info {
216 +        u_int64_t quota;
217 +};
218 +
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
223 @@ -0,0 +1,9 @@
224 +#ifndef _IPT_REALM_H
225 +#define _IPT_REALM_H
226 +
227 +struct ipt_realm_info {
228 +       u_int32_t id;
229 +       u_int32_t mask;
230 +       u_int8_t invert;
231 +};
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
236 @@ -0,0 +1,107 @@
237 +#ifndef _IPT_SCTP_H_
238 +#define _IPT_SCTP_H_
239 +
240 +#define IPT_SCTP_SRC_PORTS             0x01
241 +#define IPT_SCTP_DEST_PORTS            0x02
242 +#define IPT_SCTP_CHUNK_TYPES           0x04
243 +
244 +#define IPT_SCTP_VALID_FLAGS           0x07
245 +
246 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
247 +
248 +
249 +struct ipt_sctp_flag_info {
250 +       u_int8_t chunktype;
251 +       u_int8_t flag;
252 +       u_int8_t flag_mask;
253 +};
254 +
255 +#define IPT_NUM_SCTP_FLAGS     4
256 +
257 +struct ipt_sctp_info {
258 +       u_int16_t dpts[2];  /* Min, Max */
259 +       u_int16_t spts[2];  /* Min, Max */
260 +
261 +       u_int32_t chunkmap[256 / sizeof (u_int32_t)];  /* Bit mask of chunks to be matched according to RFC 2960 */
262 +
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 */
266 +
267 +       u_int32_t chunk_match_type;
268 +       struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
269 +       int flag_count;
270 +
271 +       u_int32_t flags;
272 +       u_int32_t invflags;
273 +};
274 +
275 +#define bytes(type) (sizeof(type) * 8)
276 +
277 +#define SCTP_CHUNKMAP_SET(chunkmap, type)              \
278 +       do {                                            \
279 +               chunkmap[type / bytes(u_int32_t)] |=    \
280 +                       1 << (type % bytes(u_int32_t)); \
281 +       } while (0)
282 +
283 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type)                    \
284 +       do {                                                    \
285 +               chunkmap[type / bytes(u_int32_t)] &=            \
286 +                       ~(1 << (type % bytes(u_int32_t)));      \
287 +       } while (0)
288 +
289 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type)                   \
290 +({                                                             \
291 +       (chunkmap[type / bytes (u_int32_t)] &                   \
292 +               (1 << (type % bytes (u_int32_t)))) ? 1: 0;      \
293 +})
294 +
295 +#define SCTP_CHUNKMAP_RESET(chunkmap)                          \
296 +       do {                                                    \
297 +               int i;                                          \
298 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
299 +                       chunkmap[i] = 0;                        \
300 +       } while (0)
301 +
302 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap)                        \
303 +       do {                                                    \
304 +               int i;                                          \
305 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
306 +                       chunkmap[i] = ~0;                       \
307 +       } while (0)
308 +
309 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap)                    \
310 +       do {                                                    \
311 +               int i;                                          \
312 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
313 +                       destmap[i] = srcmap[i];                 \
314 +       } while (0)
315 +
316 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap)               \
317 +({                                                     \
318 +       int i;                                          \
319 +       int flag = 1;                                   \
320 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
321 +               if (chunkmap[i]) {                      \
322 +                       flag = 0;                       \
323 +                       break;                          \
324 +               }                                       \
325 +       }                                               \
326 +        flag;                                          \
327 +})
328 +
329 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)             \
330 +({                                                     \
331 +       int i;                                          \
332 +       int flag = 1;                                   \
333 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
334 +               if (chunkmap[i] != ~0) {                \
335 +                       flag = 0;                       \
336 +                               break;                  \
337 +               }                                       \
338 +       }                                               \
339 +        flag;                                          \
340 +})
341 +
342 +#endif /* _IPT_SCTP_H_ */
343 +
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
347 @@ -0,0 +1,22 @@
348 +/* Hop Limit modification module for ip6tables
349 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
350 + * Based on HW's TTL module */
351 +
352 +#ifndef _IP6T_HOPLIMIT_H
353 +#define _IP6T_HOPLIMIT_H
354 +
355 +enum {
356 +       IP6T_HOPLIMIT_SET = 0,
357 +       IP6T_HOPLIMIT_INC,
358 +       IP6T_HOPLIMIT_DEC
359 +};
360 +
361 +#define IP6T_HOPLIMIT_MAXMODE  IP6T_HOPLIMIT_DEC
362 +
363 +struct ip6t_HOPLIMIT_info {
364 +       u_int8_t        mode;
365 +       u_int8_t        hop_limit;
366 +};
367 +
368 +
369 +#endif
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
373 @@ -2,15 +2,17 @@
374  #define _IP6T_REJECT_H
375  
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,
388 +       IP6T_TCP_RESET
389  };
390  
391  struct ip6t_reject_info {
392         enum ip6t_reject_with with;      /* reject type */
393  };
394  
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
400 @@ -0,0 +1,21 @@
401 +#ifndef _IP6T_FUZZY_H
402 +#define _IP6T_FUZZY_H
403 +
404 +#include <linux/param.h>
405 +#include <linux/types.h>
406 +
407 +#define MAXFUZZYRATE 10000000
408 +#define MINFUZZYRATE 3
409 +
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;
419 +};
420 +
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
425 @@ -0,0 +1,19 @@
426 +#ifndef _IP6T_NTH_H
427 +#define _IP6T_NTH_H
428 +
429 +#include <linux/param.h>
430 +#include <linux/types.h>
431 +
432 +#ifndef IP6T_NTH_NUM_COUNTERS
433 +#define IP6T_NTH_NUM_COUNTERS 16
434 +#endif
435 +
436 +struct ip6t_nth_info {
437 +       u_int8_t every;
438 +       u_int8_t not;
439 +       u_int8_t startat;
440 +       u_int8_t counter;
441 +       u_int8_t packet;
442 +};
443 +
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
448 @@ -579,5 +579,60 @@
449  
450           To compile it as a module, choose M here.  If unsure, say N.
451  
452 +config IP_NF_TARGET_IPV4OPTSSTRIP
453 +       tristate  'IPV4OPTSSTRIP target support'
454 +       depends on IP_NF_MANGLE
455 +         help
456 +
457 +config IP_NF_TARGET_TTL
458 +       tristate  'TTL target support'
459 +       depends on IP_NF_MANGLE
460 +         help
461 +
462 +config IP_NF_MATCH_CONNLIMIT
463 +       tristate  'Connections/IP limit match support'
464 +       depends on IP_NF_IPTABLES
465 +         help
466 +
467 +config IP_NF_MATCH_DSTLIMIT
468 +       tristate  'dstlimit match support'
469 +       depends on IP_NF_IPTABLES
470 +         help
471 +
472 +config IP_NF_MATCH_FUZZY
473 +       tristate  'fuzzy match support'
474 +       depends on IP_NF_IPTABLES
475 +         help
476 +
477 +config IP_NF_MATCH_IPV4OPTIONS
478 +       tristate  'IPV4OPTIONS match support'
479 +       depends on IP_NF_IPTABLES
480 +         help
481 +
482 +config IP_NF_MATCH_MPORT
483 +       tristate  'Multiple port with ranges match support'
484 +       depends on IP_NF_IPTABLES
485 +         help
486 +
487 +config IP_NF_MATCH_NTH
488 +       tristate  'Nth match support'
489 +       depends on IP_NF_IPTABLES
490 +         help
491 +
492 +config IP_NF_MATCH_QUOTA
493 +       tristate  'quota match support'
494 +       depends on IP_NF_IPTABLES
495 +         help
496 +
497 +config IP_NF_MATCH_REALM
498 +       tristate  'realm match support'
499 +       depends on IP_NF_IPTABLES && NET_CLS_ROUTE
500 +         help
501 +
502 +config IP_NF_MATCH_SCTP
503 +       tristate  'SCTP protocol match support'
504 +       depends on IP_NF_IPTABLES
505 +         help
506 +
507  endmenu
508  
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
512 @@ -42,15 +42,28 @@
513  # matches
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
522  
523  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
524  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
525 +
526 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
527 +
528  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
529  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
530  
531 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
532 +
533 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
534 +
535 +
536 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
537 +
538  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
539  
540  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
541 @@ -61,8 +74,10 @@
542  
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
549  
550  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
551  
552 @@ -79,6 +94,8 @@
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
560  
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
564 @@ -46,7 +46,7 @@
565  static int help(struct sk_buff *skb,
566                  struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
567  {
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;
573 @@ -79,20 +79,22 @@
574                 goto out;
575         data += strlen("CONNECT ");
576  
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)
586 +               return -ENOMEM;
587 +       
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;
595  
596         /* Only search first line. */   
597         if ((tmp = strchr(data, '\n')))
598                 *tmp = '\0';
599  
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]);
604                 if (!match)
605 @@ -104,8 +106,8 @@
606                 if (exp_amanda_info->port == 0 || exp_amanda_info->len > 5)
607                         break;
608  
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);
613         }
614  
615  out:
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);
622  
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))
629 -               expected = NULL;
630 -
631 -       /* Look up the conntrack helper for master connections only */
632 -       if (!expected)
633 -               conntrack->helper = ip_ct_find_helper(&repl_tuple);
634 -
635 -       /* If the expectation is dying, then this is a loser. */
636 -       if (expected
637 -           && expected->expectant->helper->timeout
638 -           && ! del_timer(&expected->timeout))
639 -               expected = NULL;
640 -
641         if (expected) {
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]);
652 -       }
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)) {
660 +                       
661 +                       conntrack->helper = ip_ct_find_helper(&repl_tuple);
662 +                       goto end;
663 +               }
664 +
665 +               /* Expectation is dying... */
666 +               if (expected->expectant->helper->timeout
667 +                   && ! del_timer(&expected->timeout)) {
668 +                       goto end;       
669 +               }
670 +
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]);
681 +
682 +               /* this is a braindead... --pablo */
683 +               atomic_inc(&ip_conntrack_count);
684 +               WRITE_UNLOCK(&ip_conntrack_lock);
685 +
686 +               if (expected->expectfn)
687 +                       expected->expectfn(conntrack);
688 +
689 +               goto ret;
690 +        } else 
691 +                conntrack->helper = ip_ct_find_helper(&repl_tuple);
692 +
693 +end:   atomic_inc(&ip_conntrack_count);
694         WRITE_UNLOCK(&ip_conntrack_lock);
695  
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];
700  }
701  
702  /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
703 @@ -917,11 +925,53 @@
704         WRITE_UNLOCK(&ip_conntrack_lock);
705  }
706  
707 +int
708 +ip_conntrack_expect_alloc(struct ip_conntrack_expect **new)
709 +{
710 +       *new = (struct ip_conntrack_expect *)
711 +               kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
712 +       if (!*new) {
713 +               DEBUGP("expect_related: OOM allocating expect\n");
714 +               return -ENOMEM;
715 +       }
716 +
717 +       /* tuple_cmp compares whole union, we have to initialized cleanly */
718 +       memset(*new, 0, sizeof(struct ip_conntrack_expect));
719 +
720 +       return 1;
721 +}
722 +
723 +static void
724 +ip_conntrack_expect_insert(struct ip_conntrack_expect *new,
725 +                          struct ip_conntrack *related_to)
726 +{
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);
731 +
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 */
735 +
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);
745 +       }
746 +       related_to->expecting++;
747 +}
748 +
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)
754  {
755 -       struct ip_conntrack_expect *old, *new;
756 +       struct ip_conntrack_expect *old;
757         int ret = 0;
758  
759         WRITE_LOCK(&ip_conntrack_lock);
760 @@ -943,7 +993,7 @@
761                 if (related_to->helper->timeout) {
762                         if (!del_timer(&old->timeout)) {
763                                 /* expectation is dying. Fall through */
764 -                               old = NULL;
765 +                               goto out;
766                         } else {
767                                 old->timeout.expires = jiffies + 
768                                         related_to->helper->timeout * HZ;
769 @@ -951,10 +1001,10 @@
770                         }
771                 }
772  
773 -               if (old) {
774 -                       WRITE_UNLOCK(&ip_conntrack_lock);
775 -                       return -EEXIST;
776 -               }
777 +               WRITE_UNLOCK(&ip_conntrack_lock);
778 +               kfree(expect);
779 +               return -EEXIST;
780 +
781         } else if (related_to->helper->max_expected && 
782                    related_to->expecting >= related_to->helper->max_expected) {
783                 struct list_head *cur_item;
784 @@ -971,6 +1021,7 @@
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));
788 +                       kfree(expect);
789                         return -EPERM;
790                 }
791                 DEBUGP("ip_conntrack: max number of expected "
792 @@ -1010,37 +1061,12 @@
793                              &expect->mask)) {
794                 WRITE_UNLOCK(&ip_conntrack_lock);
795                 DEBUGP("expect_related: busy!\n");
796 +
797 +               kfree(expect);
798                 return -EBUSY;
799         }
800 -       
801 -       new = (struct ip_conntrack_expect *) 
802 -             kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
803 -       if (!new) {
804 -               WRITE_UNLOCK(&ip_conntrack_lock);
805 -               DEBUGP("expect_relaed: OOM allocating expect\n");
806 -               return -ENOMEM;
807 -       }
808 -       
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);
814 -       
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);
827 -       }
828 -       related_to->expecting++;
829 +
830 +out:   ip_conntrack_expect_insert(expect, related_to);
831  
832         WRITE_UNLOCK(&ip_conntrack_lock);
833  
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
837 @@ -256,8 +256,8 @@
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;
845  
846         unsigned int i;
847         int found = 0;
848 @@ -346,8 +346,12 @@
849         DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
850                (int)matchlen, data + matchoff,
851                matchlen, ntohl(tcph.seq) + matchoff);
852 -              
853 -       memset(&expect, 0, sizeof(expect));
854 +
855 +       /* Allocate expectation which will be inserted */
856 +       if (ip_conntrack_expect_alloc(&exp) < 0)
857 +               return -ENOMEM;
858 +
859 +       exp_ftp_info = &exp->help.exp_ftp_info;
860  
861         /* Update the ftp info */
862         if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3])
863 @@ -389,7 +393,7 @@
864         exp->expectfn = NULL;
865  
866         /* Ignore failure; should only happen with NAT */
867 -       ip_conntrack_expect_related(ct, &expect);
868 +       ip_conntrack_expect_related(exp, ct);
869         ret = NF_ACCEPT;
870   out:
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
875 @@ -106,8 +106,8 @@
876         struct tcphdr tcph;
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;
883  
884         u_int32_t dcc_ip;
885         u_int16_t dcc_port;
886 @@ -190,8 +190,11 @@
887  
888                                 continue;
889                         }
890 -                       
891 -                       memset(&expect, 0, sizeof(expect));
892 +
893 +                       if (ip_conntrack_expect_alloc(&exp) < 0)
894 +                               return -ENOMEM;
895 +
896 +                       exp_irc_info = &exp->help.exp_irc_info;
897  
898                         /* save position of address in dcc string,
899                          * necessary for NAT */
900 @@ -218,7 +221,7 @@
901                                 NIPQUAD(exp->tuple.dst.ip),
902                                 ntohs(exp->tuple.dst.u.tcp.port));
903  
904 -                       ip_conntrack_expect_related(ct, &expect);
905 +                       ip_conntrack_expect_related(exp, ct);
906  
907                         goto out;
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
912 @@ -591,6 +591,7 @@
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
923 @@ -0,0 +1,606 @@
924 +/* This file contains all the functions required for the standalone
925 +   ip_conntrack module.
926 +
927 +   These are not required by the compatibility layer.
928 +*/
929 +
930 +/* (C) 1999-2001 Paul `Rusty' Russell
931 + * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
932 + *
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.
936 + */
937 +
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>
948 +#endif
949 +#include <net/checksum.h>
950 +
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)
953 +
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>
959 +
960 +#if 0
961 +#define DEBUGP printk
962 +#else
963 +#define DEBUGP(format, args...)
964 +#endif
965 +
966 +MODULE_LICENSE("GPL");
967 +
968 +static int kill_proto(const struct ip_conntrack *i, void *data)
969 +{
970 +       return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == 
971 +                       *((u_int8_t *) data));
972 +}
973 +
974 +static unsigned int
975 +print_tuple(char *buffer, const struct ip_conntrack_tuple *tuple,
976 +           struct ip_conntrack_protocol *proto)
977 +{
978 +       int len;
979 +
980 +       len = sprintf(buffer, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
981 +                     NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
982 +
983 +       len += proto->print_tuple(buffer + len, tuple);
984 +
985 +       return len;
986 +}
987 +
988 +/* FIXME: Don't print source proto part. --RR */
989 +static unsigned int
990 +print_expect(char *buffer, const struct ip_conntrack_expect *expect)
991 +{
992 +       unsigned int len;
993 +
994 +       if (expect->expectant->helper->timeout)
995 +               len = sprintf(buffer, "EXPECTING: %lu ",
996 +                             timer_pending(&expect->timeout)
997 +                             ? (expect->timeout.expires - jiffies)/HZ : 0);
998 +       else
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");
1005 +       return len;
1006 +}
1007 +
1008 +static unsigned int
1009 +print_conntrack(char *buffer, struct ip_conntrack *conntrack)
1010 +{
1011 +       unsigned int len;
1012 +       struct ip_conntrack_protocol *proto
1013 +               = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
1014 +                              .tuple.dst.protonum);
1015 +
1016 +       len = sprintf(buffer, "%-8s %u %lu ",
1017 +                     proto->name,
1018 +                     conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
1019 +                     .tuple.dst.protonum,
1020 +                     timer_pending(&conntrack->timeout)
1021 +                     ? (conntrack->timeout.expires - jiffies)/HZ : 0);
1022 +
1023 +       len += proto->print_conntrack(buffer + len, conntrack);
1024 +       len += print_tuple(buffer + len,
1025 +                          &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
1026 +                          proto);
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,
1031 +                          proto);
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");
1037 +
1038 +       return len;
1039 +}
1040 +
1041 +/* Returns true when finished. */
1042 +static inline int
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)
1046 +{
1047 +       unsigned int newlen;
1048 +       IP_NF_ASSERT(hash->ctrack);
1049 +
1050 +       MUST_BE_READ_LOCKED(&ip_conntrack_lock);
1051 +
1052 +       /* Only count originals */
1053 +       if (DIRECTION(hash))
1054 +               return 0;
1055 +
1056 +       if ((*upto)++ < offset)
1057 +               return 0;
1058 +
1059 +       newlen = print_conntrack(buffer + *len, hash->ctrack);
1060 +       if (*len + newlen > maxlen)
1061 +               return 1;
1062 +       else *len += newlen;
1063 +
1064 +       return 0;
1065 +}
1066 +
1067 +static int
1068 +list_conntracks(char *buffer, char **start, off_t offset, int length)
1069 +{
1070 +       unsigned int i;
1071 +       unsigned int len = 0;
1072 +       off_t upto = 0;
1073 +       struct list_head *e;
1074 +
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))
1081 +                       goto finished;
1082 +       }
1083 +
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;
1091 +
1092 +               last_len = len;
1093 +               len += print_expect(buffer + len, expect);
1094 +               if (len > length) {
1095 +                       len = last_len;
1096 +                       goto finished_expects;
1097 +               }
1098 +       }
1099 +
1100 + finished_expects:
1101 +       READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
1102 + finished:
1103 +       READ_UNLOCK(&ip_conntrack_lock);
1104 +
1105 +       /* `start' hack - see fs/proc/generic.c line ~165 */
1106 +       *start = (char *)((unsigned int)upto - offset);
1107 +       return len;
1108 +}
1109 +
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 *))
1115 +{
1116 +       /* We've seen it coming out the other side: confirm it */
1117 +       return ip_conntrack_confirm(*pskb);
1118 +}
1119 +
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 *))
1125 +{
1126 +       struct rtable *rt = (struct rtable *)(*pskb)->dst;
1127 +
1128 +       /* We've seen it coming out the other side: confirm */
1129 +       if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
1130 +               return NF_DROP;
1131 +
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);
1139 +               return NF_STOLEN;
1140 +       }
1141 +       return NF_ACCEPT;
1142 +}
1143 +
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 *))
1149 +{
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");
1155 +               return NF_ACCEPT;
1156 +       }
1157 +       return ip_conntrack_in(hooknum, pskb, in, out, okfn);
1158 +}
1159 +
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,
1165 +       .pf             = PF_INET,
1166 +       .hooknum        = NF_IP_PRE_ROUTING,
1167 +       .priority       = NF_IP_PRI_CONNTRACK,
1168 +};
1169 +
1170 +static struct nf_hook_ops ip_conntrack_local_out_ops = {
1171 +       .hook           = ip_conntrack_local,
1172 +       .owner          = THIS_MODULE,
1173 +       .pf             = PF_INET,
1174 +       .hooknum        = NF_IP_LOCAL_OUT,
1175 +       .priority       = NF_IP_PRI_CONNTRACK,
1176 +};
1177 +
1178 +/* Refragmenter; last chance. */
1179 +static struct nf_hook_ops ip_conntrack_out_ops = {
1180 +       .hook           = ip_refrag,
1181 +       .owner          = THIS_MODULE,
1182 +       .pf             = PF_INET,
1183 +       .hooknum        = NF_IP_POST_ROUTING,
1184 +       .priority       = NF_IP_PRI_LAST,
1185 +};
1186 +
1187 +static struct nf_hook_ops ip_conntrack_local_in_ops = {
1188 +       .hook           = ip_confirm,
1189 +       .owner          = THIS_MODULE,
1190 +       .pf             = PF_INET,
1191 +       .hooknum        = NF_IP_LOCAL_IN,
1192 +       .priority       = NF_IP_PRI_LAST-1,
1193 +};
1194 +
1195 +/* Sysctl support */
1196 +
1197 +#ifdef CONFIG_SYSCTL
1198 +
1199 +/* From ip_conntrack_core.c */
1200 +extern int ip_conntrack_max;
1201 +extern unsigned int ip_conntrack_htable_size;
1202 +
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;
1212 +
1213 +/* From ip_conntrack_proto_udp.c */
1214 +extern unsigned long ip_ct_udp_timeout;
1215 +extern unsigned long ip_ct_udp_timeout_stream;
1216 +
1217 +/* From ip_conntrack_proto_icmp.c */
1218 +extern unsigned long ip_ct_icmp_timeout;
1219 +
1220 +/* From ip_conntrack_proto_icmp.c */
1221 +extern unsigned long ip_ct_generic_timeout;
1222 +
1223 +static struct ctl_table_header *ip_ct_sysctl_header;
1224 +
1225 +static ctl_table ip_ct_sysctl_table[] = {
1226 +       {
1227 +               .ctl_name       = NET_IPV4_NF_CONNTRACK_MAX,
1228 +               .procname       = "ip_conntrack_max",
1229 +               .data           = &ip_conntrack_max,
1230 +               .maxlen         = sizeof(int),
1231 +               .mode           = 0644,
1232 +               .proc_handler   = &proc_dointvec,
1233 +       },
1234 +       {
1235 +               .ctl_name       = NET_IPV4_NF_CONNTRACK_BUCKETS,
1236 +               .procname       = "ip_conntrack_buckets",
1237 +               .data           = &ip_conntrack_htable_size,
1238 +               .maxlen         = sizeof(unsigned int),
1239 +               .mode           = 0444,
1240 +               .proc_handler   = &proc_dointvec,
1241 +       },
1242 +       {
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),
1247 +               .mode           = 0644,
1248 +               .proc_handler   = &proc_dointvec_jiffies,
1249 +       },
1250 +       {
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),
1255 +               .mode           = 0644,
1256 +               .proc_handler   = &proc_dointvec_jiffies,
1257 +       },
1258 +       {
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),
1263 +               .mode           = 0644,
1264 +               .proc_handler   = &proc_dointvec_jiffies,
1265 +       },
1266 +       {
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),
1271 +               .mode           = 0644,
1272 +               .proc_handler   = &proc_dointvec_jiffies,
1273 +       },
1274 +       {
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),
1279 +               .mode           = 0644,
1280 +               .proc_handler   = &proc_dointvec_jiffies,
1281 +       },
1282 +       {
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),
1287 +               .mode           = 0644,
1288 +               .proc_handler   = &proc_dointvec_jiffies,
1289 +       },
1290 +       {
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),
1295 +               .mode           = 0644,
1296 +               .proc_handler   = &proc_dointvec_jiffies,
1297 +       },
1298 +       {
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),
1303 +               .mode           = 0644,
1304 +               .proc_handler   = &proc_dointvec_jiffies,
1305 +       },
1306 +       {
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),
1311 +               .mode           = 0644,
1312 +               .proc_handler   = &proc_dointvec_jiffies,
1313 +       },
1314 +       {
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),
1319 +               .mode           = 0644,
1320 +               .proc_handler   = &proc_dointvec_jiffies,
1321 +       },
1322 +       {
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),
1327 +               .mode           = 0644,
1328 +               .proc_handler   = &proc_dointvec_jiffies,
1329 +       },
1330 +       {
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),
1335 +               .mode           = 0644,
1336 +               .proc_handler   = &proc_dointvec_jiffies,
1337 +       },
1338 +       { .ctl_name = 0 }
1339 +};
1340 +
1341 +#define NET_IP_CONNTRACK_MAX 2089
1342 +
1343 +static ctl_table ip_ct_netfilter_table[] = {
1344 +       {
1345 +               .ctl_name       = NET_IPV4_NETFILTER,
1346 +               .procname       = "netfilter",
1347 +               .mode           = 0555,
1348 +               .child          = ip_ct_sysctl_table,
1349 +       },
1350 +       {
1351 +               .ctl_name       = NET_IP_CONNTRACK_MAX,
1352 +               .procname       = "ip_conntrack_max",
1353 +               .data           = &ip_conntrack_max,
1354 +               .maxlen         = sizeof(int),
1355 +               .mode           = 0644,
1356 +               .proc_handler   = &proc_dointvec
1357 +       },
1358 +       { .ctl_name = 0 }
1359 +};
1360 +
1361 +static ctl_table ip_ct_ipv4_table[] = {
1362 +       {
1363 +               .ctl_name       = NET_IPV4,
1364 +               .procname       = "ipv4",
1365 +               .mode           = 0555,
1366 +               .child          = ip_ct_netfilter_table,
1367 +       },
1368 +       { .ctl_name = 0 }
1369 +};
1370 +
1371 +static ctl_table ip_ct_net_table[] = {
1372 +       {
1373 +               .ctl_name       = CTL_NET,
1374 +               .procname       = "net",
1375 +               .mode           = 0555, 
1376 +               .child          = ip_ct_ipv4_table,
1377 +       },
1378 +       { .ctl_name = 0 }
1379 +};
1380 +#endif
1381 +static int init_or_cleanup(int init)
1382 +{
1383 +       struct proc_dir_entry *proc;
1384 +       int ret = 0;
1385 +
1386 +       if (!init) goto cleanup;
1387 +
1388 +       ret = ip_conntrack_init();
1389 +       if (ret < 0)
1390 +               goto cleanup_nothing;
1391 +
1392 +       proc = proc_net_create("ip_conntrack",0,list_conntracks);
1393 +       if (!proc) goto cleanup_init;
1394 +       proc->owner = THIS_MODULE;
1395 +
1396 +       ret = nf_register_hook(&ip_conntrack_in_ops);
1397 +       if (ret < 0) {
1398 +               printk("ip_conntrack: can't register pre-routing hook.\n");
1399 +               goto cleanup_proc;
1400 +       }
1401 +       ret = nf_register_hook(&ip_conntrack_local_out_ops);
1402 +       if (ret < 0) {
1403 +               printk("ip_conntrack: can't register local out hook.\n");
1404 +               goto cleanup_inops;
1405 +       }
1406 +       ret = nf_register_hook(&ip_conntrack_out_ops);
1407 +       if (ret < 0) {
1408 +               printk("ip_conntrack: can't register post-routing hook.\n");
1409 +               goto cleanup_inandlocalops;
1410 +       }
1411 +       ret = nf_register_hook(&ip_conntrack_local_in_ops);
1412 +       if (ret < 0) {
1413 +               printk("ip_conntrack: can't register local in hook.\n");
1414 +               goto cleanup_inoutandlocalops;
1415 +       }
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");
1420 +               goto cleanup;
1421 +       }
1422 +#endif
1423 +
1424 +       return ret;
1425 +
1426 + cleanup:
1427 +#ifdef CONFIG_SYSCTL
1428 +       unregister_sysctl_table(ip_ct_sysctl_header);
1429 +#endif
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);
1435 + cleanup_inops:
1436 +       nf_unregister_hook(&ip_conntrack_in_ops);
1437 + cleanup_proc:
1438 +       proc_net_remove("ip_conntrack");
1439 + cleanup_init:
1440 +       ip_conntrack_cleanup();
1441 + cleanup_nothing:
1442 +       return ret;
1443 +}
1444 +
1445 +/* FIXME: Allow NULL functions and sub in pointers to generic for
1446 +   them. --RR */
1447 +int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
1448 +{
1449 +       int ret = 0;
1450 +       struct list_head *i;
1451 +
1452 +       WRITE_LOCK(&ip_conntrack_lock);
1453 +       list_for_each(i, &protocol_list) {
1454 +               if (((struct ip_conntrack_protocol *)i)->proto
1455 +                   == proto->proto) {
1456 +                       ret = -EBUSY;
1457 +                       goto out;
1458 +               }
1459 +       }
1460 +
1461 +       list_prepend(&protocol_list, proto);
1462 +
1463 + out:
1464 +       WRITE_UNLOCK(&ip_conntrack_lock);
1465 +       return ret;
1466 +}
1467 +
1468 +void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
1469 +{
1470 +       WRITE_LOCK(&ip_conntrack_lock);
1471 +
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);
1476 +       
1477 +       /* Somebody could be still looking at the proto in bh. */
1478 +       synchronize_net();
1479 +
1480 +       /* Remove all contrack entries for this protocol */
1481 +       ip_ct_selective_cleanup(kill_proto, &proto->proto);
1482 +}
1483 +
1484 +static int __init init(void)
1485 +{
1486 +       return init_or_cleanup(1);
1487 +}
1488 +
1489 +static void __exit fini(void)
1490 +{
1491 +       init_or_cleanup(0);
1492 +}
1493 +
1494 +module_init(init);
1495 +module_exit(fini);
1496 +
1497 +/* Some modules need us, but don't depend directly on any symbol.
1498 +   They should call this. */
1499 +void need_ip_conntrack(void)
1500 +{
1501 +}
1502 +
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
1533 @@ -44,7 +44,7 @@
1534                      enum ip_conntrack_info ctinfo)
1535  {
1536         struct tftphdr tftph;
1537 -       struct ip_conntrack_expect exp;
1538 +       struct ip_conntrack_expect *exp;
1539  
1540         if (skb_copy_bits(skb, skb->nh.iph->ihl * 4 + sizeof(struct udphdr),
1541                           &tftph, sizeof(tftph)) != 0)
1542 @@ -57,19 +57,21 @@
1543                 DEBUGP("");
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));
1547  
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)
1555 +                       return -ENOMEM;
1556 +
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;
1563  
1564                 DEBUGP("expect: ");
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);
1571                 break;
1572         default:
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
1577 @@ -0,0 +1,89 @@
1578 +/**
1579 + * Strip all IP options in the IP packet header.
1580 + *
1581 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
1582 + * This software is distributed under GNU GPL v2, 1991
1583 + */
1584 +
1585 +#include <linux/module.h>
1586 +#include <linux/skbuff.h>
1587 +#include <linux/ip.h>
1588 +#include <net/checksum.h>
1589 +
1590 +#include <linux/netfilter_ipv4/ip_tables.h>
1591 +
1592 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
1593 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
1594 +MODULE_LICENSE("GPL");
1595 +
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,
1602 +       void *userinfo)
1603 +{
1604 +       struct iphdr *iph;
1605 +       struct sk_buff *skb;
1606 +       struct ip_options *opt;
1607 +       unsigned char *optiph;
1608 +       int l;
1609 +       
1610 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
1611 +               return NF_DROP;
1612
1613 +       skb = (*pskb);
1614 +       iph = (*pskb)->nh.iph;
1615 +       optiph = skb->nh.raw;
1616 +       l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
1617 +
1618 +       /* if no options in packet then nothing to clear. */
1619 +       if (iph->ihl * 4 == sizeof(struct iphdr))
1620 +               return IPT_CONTINUE;
1621 +
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);
1626 +       opt->is_data = 0;
1627 +       opt->optlen = l;
1628 +
1629 +       skb->nfcache |= NFC_ALTERED;
1630 +
1631 +        return IPT_CONTINUE;
1632 +}
1633 +
1634 +static int
1635 +checkentry(const char *tablename,
1636 +          const struct ipt_entry *e,
1637 +           void *targinfo,
1638 +           unsigned int targinfosize,
1639 +           unsigned int hook_mask)
1640 +{
1641 +       if (strcmp(tablename, "mangle")) {
1642 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1643 +               return 0;
1644 +       }
1645 +       /* nothing else to check because no parameters */
1646 +       return 1;
1647 +}
1648 +
1649 +static struct ipt_target ipt_ipv4optsstrip_reg = { 
1650 +       .name = "IPV4OPTSSTRIP",
1651 +       .target = target,
1652 +       .checkentry = checkentry,
1653 +       .me = THIS_MODULE };
1654 +
1655 +static int __init init(void)
1656 +{
1657 +       return ipt_register_target(&ipt_ipv4optsstrip_reg);
1658 +}
1659 +
1660 +static void __exit fini(void)
1661 +{
1662 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
1663 +}
1664 +
1665 +module_init(init);
1666 +module_exit(fini);
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
1670 @@ -0,0 +1,120 @@
1671 +/* TTL modification target for IP tables
1672 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
1673 + *
1674 + * Version: $Revision$
1675 + *
1676 + * This software is distributed under the terms of GNU GPL
1677 + */
1678 +
1679 +#include <linux/module.h>
1680 +#include <linux/skbuff.h>
1681 +#include <linux/ip.h>
1682 +#include <net/checksum.h>
1683 +
1684 +#include <linux/netfilter_ipv4/ip_tables.h>
1685 +#include <linux/netfilter_ipv4/ipt_TTL.h>
1686 +
1687 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
1688 +MODULE_DESCRIPTION("IP tables TTL modification module");
1689 +MODULE_LICENSE("GPL");
1690 +
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)
1695 +{
1696 +       struct iphdr *iph;
1697 +       const struct ipt_TTL_info *info = targinfo;
1698 +       u_int16_t diffs[2];
1699 +       int new_ttl;
1700 +
1701 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
1702 +               return NF_DROP;
1703 +
1704 +       iph = (*pskb)->nh.iph;
1705 +                        
1706 +       switch (info->mode) {
1707 +               case IPT_TTL_SET:
1708 +                       new_ttl = info->ttl;
1709 +                       break;
1710 +               case IPT_TTL_INC:
1711 +                       new_ttl = iph->ttl + info->ttl;
1712 +                       if (new_ttl > 255)
1713 +                               new_ttl = 255;
1714 +                       break;
1715 +               case IPT_TTL_DEC:
1716 +                       new_ttl = iph->ttl + info->ttl;
1717 +                       if (new_ttl < 0)
1718 +                               new_ttl = 0;
1719 +                       break;
1720 +               default:
1721 +                       new_ttl = iph->ttl;
1722 +                       break;
1723 +       }
1724 +
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,
1730 +                                                   sizeof(diffs),
1731 +                                                   iph->check^0xFFFF));
1732 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
1733 +       }
1734 +
1735 +       return IPT_CONTINUE;
1736 +}
1737 +
1738 +static int ipt_ttl_checkentry(const char *tablename,
1739 +               const struct ipt_entry *e,
1740 +               void *targinfo,
1741 +               unsigned int targinfosize,
1742 +               unsigned int hook_mask)
1743 +{
1744 +       struct ipt_TTL_info *info = targinfo;
1745 +
1746 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
1747 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
1748 +                               targinfosize,
1749 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
1750 +               return 0;       
1751 +       }       
1752 +
1753 +       if (strcmp(tablename, "mangle")) {
1754 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1755 +               return 0;
1756 +       }
1757 +
1758 +       if (info->mode > IPT_TTL_MAXMODE) {
1759 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
1760 +                       info->mode);
1761 +               return 0;
1762 +       }
1763 +
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");
1766 +               return 0;
1767 +       }
1768 +       
1769 +       return 1;
1770 +}
1771 +
1772 +static struct ipt_target ipt_TTL = { 
1773 +       .name = "TTL",
1774 +       .target = ipt_ttl_target, 
1775 +       .checkentry = ipt_ttl_checkentry, 
1776 +       .me = THIS_MODULE 
1777 +};
1778 +
1779 +static int __init init(void)
1780 +{
1781 +       return ipt_register_target(&ipt_TTL);
1782 +}
1783 +
1784 +static void __exit fini(void)
1785 +{
1786 +       ipt_unregister_target(&ipt_TTL);
1787 +}
1788 +
1789 +module_init(init);
1790 +module_exit(fini);
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
1794 @@ -0,0 +1,230 @@
1795 +/*
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
1801 + *
1802 + * based on ...
1803 + *
1804 + * Kernel module to match connection tracking information.
1805 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
1806 + */
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>
1815 +
1816 +#define DEBUG 0
1817 +
1818 +MODULE_LICENSE("GPL");
1819 +
1820 +/* we'll save the tuples of all connections we care about */
1821 +struct ipt_connlimit_conn
1822 +{
1823 +        struct list_head list;
1824 +       struct ip_conntrack_tuple tuple;
1825 +};
1826 +
1827 +struct ipt_connlimit_data {
1828 +       spinlock_t lock;
1829 +       struct list_head iphash[256];
1830 +};
1831 +
1832 +static int ipt_iphash(u_int32_t addr)
1833 +{
1834 +       int hash;
1835 +
1836 +       hash  =  addr        & 0xff;
1837 +       hash ^= (addr >>  8) & 0xff;
1838 +       hash ^= (addr >> 16) & 0xff;
1839 +       hash ^= (addr >> 24) & 0xff;
1840 +       return hash;
1841 +}
1842 +
1843 +static int count_them(struct ipt_connlimit_data *data,
1844 +                     u_int32_t addr, u_int32_t mask,
1845 +                     struct ip_conntrack *ct)
1846 +{
1847 +#if DEBUG
1848 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
1849 +                                    "fin_wait", "time_wait", "close", "close_wait",
1850 +                                    "last_ack", "listen" };
1851 +#endif
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;
1857 +
1858 +       spin_lock(&data->lock);
1859 +       tuple = ct->tuplehash[0].tuple;
1860 +       hash = &data->iphash[ipt_iphash(addr & mask)];
1861 +
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)) &&
1867 +                   found != NULL &&
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" */
1872 +                       addit = 0;
1873 +               }
1874 +#if DEBUG
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");
1880 +#endif
1881 +               if (NULL == found) {
1882 +                       /* this one is gone */
1883 +                       lh = lh->prev;
1884 +                       list_del(lh->next);
1885 +                       kfree(conn);
1886 +                       continue;
1887 +               }
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 */
1891 +                       lh = lh->prev;
1892 +                       list_del(lh->next);
1893 +                       kfree(conn);
1894 +                       nf_conntrack_put(&found->ctrack->infos[0]);
1895 +                       continue;
1896 +               }
1897 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
1898 +                       /* same source IP address -> be counted! */
1899 +                       matches++;
1900 +               }
1901 +               nf_conntrack_put(&found->ctrack->infos[0]);
1902 +       }
1903 +       if (addit) {
1904 +               /* save the new connection in our list */
1905 +#if DEBUG
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));
1910 +#endif
1911 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
1912 +               if (NULL == conn)
1913 +                       return -1;
1914 +               memset(conn,0,sizeof(*conn));
1915 +               INIT_LIST_HEAD(&conn->list);
1916 +               conn->tuple = tuple;
1917 +               list_add(&conn->list,hash);
1918 +               matches++;
1919 +       }
1920 +       spin_unlock(&data->lock);
1921 +       return matches;
1922 +}
1923 +
1924 +static int
1925 +match(const struct sk_buff *skb,
1926 +      const struct net_device *in,
1927 +      const struct net_device *out,
1928 +      const void *matchinfo,
1929 +      int offset,
1930 +      int *hotdrop)
1931 +{
1932 +       const struct ipt_connlimit_info *info = matchinfo;
1933 +       int connections, match;
1934 +       struct ip_conntrack *ct;
1935 +       enum ip_conntrack_info ctinfo;
1936 +
1937 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
1938 +       if (NULL == ct) {
1939 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
1940 +               *hotdrop = 1;
1941 +               return 0;
1942 +       }
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 :-) */
1947 +               return 0;
1948 +       }
1949 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
1950 +#if DEBUG
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");
1955 +#endif
1956 +
1957 +       return match;
1958 +}
1959 +
1960 +static int check(const char *tablename,
1961 +                const struct ipt_ip *ip,
1962 +                void *matchinfo,
1963 +                unsigned int matchsize,
1964 +                unsigned int hook_mask)
1965 +{
1966 +       struct ipt_connlimit_info *info = matchinfo;
1967 +       int i;
1968 +
1969 +       /* verify size */
1970 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
1971 +               return 0;
1972 +
1973 +       /* refuse anything but tcp */
1974 +       if (ip->proto != IPPROTO_TCP)
1975 +               return 0;
1976 +
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]));
1982 +       
1983 +       return 1;
1984 +}
1985 +
1986 +static void destroy(void *matchinfo, unsigned int matchinfosize)
1987 +{
1988 +       struct ipt_connlimit_info *info = matchinfo;
1989 +       struct ipt_connlimit_conn *conn;
1990 +       struct list_head *hash;
1991 +       int i;
1992 +
1993 +       /* cleanup */
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);
1999 +                       kfree(conn);
2000 +               }
2001 +       }
2002 +       kfree(info->data);
2003 +}
2004 +
2005 +static struct ipt_match connlimit_match = { 
2006 +       .name = "connlimit",
2007 +       .match = &match,
2008 +       .checkentry = &check,
2009 +       .destroy = &destroy,
2010 +       .me = THIS_MODULE
2011 +};
2012 +
2013 +static int __init init(void)
2014 +{
2015 +       return ipt_register_match(&connlimit_match);
2016 +}
2017 +
2018 +static void __exit fini(void)
2019 +{
2020 +       ipt_unregister_match(&connlimit_match);
2021 +}
2022 +
2023 +module_init(init);
2024 +module_exit(fini);
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
2028 @@ -0,0 +1,690 @@
2029 +/* iptables match extension to limit the number of packets per second
2030 + * seperately for each destination.
2031 + *
2032 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
2033 + *
2034 + * $Id$
2035 + *
2036 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
2037 + *
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>
2042 + *
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.
2046 + *
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 ;)
2051 + */
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>
2063 +
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>
2068 +
2069 +#include <linux/netfilter_ipv4/ip_tables.h>
2070 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
2071 +
2072 +/* FIXME: this is just for IP_NF_ASSERRT */
2073 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2074 +
2075 +#define MS2JIFFIES(x) ((x*HZ)/1000)
2076 +
2077 +MODULE_LICENSE("GPL");
2078 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2079 +MODULE_DESCRIPTION("iptables match for limiting per destination");
2080 +
2081 +/* need to declare this at the top */
2082 +static struct proc_dir_entry *dstlimit_procdir;
2083 +static struct file_operations dl_file_ops;
2084 +
2085 +/* hash table crap */
2086 +
2087 +struct dsthash_dst {
2088 +       u_int32_t src_ip;
2089 +       u_int32_t dst_ip;
2090 +       u_int16_t port;
2091 +};
2092 +
2093 +struct dsthash_ent {
2094 +       /* static / read-only parts in the beginning */
2095 +       struct list_head list;
2096 +       struct dsthash_dst dst;
2097 +
2098 +       /* modified structure members in the end */
2099 +       unsigned long expires;          /* precalculated expiry time */
2100 +       struct {
2101 +               unsigned long prev;     /* last modification */
2102 +               u_int32_t credit;
2103 +               u_int32_t credit_cap, cost;
2104 +       } rateinfo;
2105 +};
2106 +
2107 +struct ipt_dstlimit_htable {
2108 +       struct list_head list;          /* global list of all htables */
2109 +       atomic_t use;
2110 +
2111 +       struct dstlimit_cfg cfg;        /* config */
2112 +
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 */
2118 +
2119 +       /* seq_file stuff */
2120 +       struct proc_dir_entry *pde;
2121 +
2122 +       struct list_head hash[0];       /* hashtable itself */
2123 +};
2124 +
2125 +DECLARE_RWLOCK(dstlimit_lock);         /* protects htables list */
2126 +static LIST_HEAD(dstlimit_htables);
2127 +static kmem_cache_t *dstlimit_cachep;
2128 +
2129 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
2130 +{
2131 +       return (ent->dst.dst_ip == b->dst_ip 
2132 +               && ent->dst.port == b->port
2133 +               && ent->dst.src_ip == b->src_ip);
2134 +}
2135 +
2136 +static inline u_int32_t
2137 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
2138 +{
2139 +       return (jhash_3words(dst->dst_ip, dst->port, 
2140 +                            dst->src_ip, ht->rnd) % ht->cfg.size);
2141 +}
2142 +
2143 +static inline struct dsthash_ent *
2144 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2145 +{
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);
2150 +       return ent;
2151 +}
2152 +
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)
2156 +{
2157 +       struct dsthash_ent *ent;
2158 +
2159 +       /* initialize hash with random val at the time we allocate
2160 +        * the first hashtable entry */
2161 +       if (!ht->rnd)
2162 +               get_random_bytes(&ht->rnd, 4);
2163 +
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", 
2170 +                               ht->cfg.max);
2171 +               return NULL;
2172 +       }
2173 +
2174 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
2175 +       if (!ent) {
2176 +               if (net_ratelimit())
2177 +                       printk(KERN_ERR 
2178 +                               "ipt_dstlimit: can't allocate dsthash_ent\n");
2179 +               return NULL;
2180 +       }
2181 +
2182 +       atomic_inc(&ht->count);
2183 +
2184 +       ent->dst.dst_ip = dst->dst_ip;
2185 +       ent->dst.port = dst->port;
2186 +       ent->dst.src_ip = dst->src_ip;
2187 +
2188 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
2189 +
2190 +       return ent;
2191 +}
2192 +
2193 +static inline void 
2194 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
2195 +{
2196 +       MUST_BE_LOCKED(&ht->lock);
2197 +
2198 +       list_del(&ent->list);
2199 +       kmem_cache_free(dstlimit_cachep, ent);
2200 +       atomic_dec(&ht->count);
2201 +}
2202 +static void htable_gc(unsigned long htlong);
2203 +
2204 +static int htable_create(struct ipt_dstlimit_info *minfo)
2205 +{
2206 +       int i;
2207 +       unsigned int size;
2208 +       struct ipt_dstlimit_htable *hinfo;
2209 +
2210 +       if (minfo->cfg.size)
2211 +               size = minfo->cfg.size;
2212 +       else {
2213 +               size = (((num_physpages << PAGE_SHIFT) / 16384)
2214 +                        / sizeof(struct list_head));
2215 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
2216 +                       size = 8192;
2217 +               if (size < 16)
2218 +                       size = 16;
2219 +       }
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));
2223 +       if (!hinfo) {
2224 +               printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
2225 +               return -1;
2226 +       }
2227 +       minfo->hinfo = hinfo;
2228 +
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;
2236 +
2237 +       for (i = 0; i < hinfo->cfg.size; i++)
2238 +               INIT_LIST_HEAD(&hinfo->hash[i]);
2239 +
2240 +       atomic_set(&hinfo->count, 0);
2241 +       atomic_set(&hinfo->use, 1);
2242 +       hinfo->rnd = 0;
2243 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
2244 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
2245 +       if (!hinfo->pde) {
2246 +               vfree(hinfo);
2247 +               return -1;
2248 +       }
2249 +       hinfo->pde->proc_fops = &dl_file_ops;
2250 +       hinfo->pde->data = hinfo;
2251 +
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);
2257 +
2258 +       WRITE_LOCK(&dstlimit_lock);
2259 +       list_add(&hinfo->list, &dstlimit_htables);
2260 +       WRITE_UNLOCK(&dstlimit_lock);
2261 +
2262 +       return 0;
2263 +}
2264 +
2265 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
2266 +{
2267 +       return 1;
2268 +}
2269 +
2270 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
2271 +{
2272 +       return (jiffies >= he->expires);
2273 +}
2274 +
2275 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
2276 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
2277 +                                             struct dsthash_ent *he))
2278 +{
2279 +       int i;
2280 +
2281 +       IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
2282 +
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);
2290 +               }
2291 +       }
2292 +       UNLOCK_BH(&ht->lock);
2293 +}
2294 +
2295 +/* hash table garbage collector, run by timer */
2296 +static void htable_gc(unsigned long htlong)
2297 +{
2298 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
2299 +
2300 +       htable_selective_cleanup(ht, select_gc);
2301 +
2302 +       /* re-add the timer accordingly */
2303 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
2304 +       add_timer(&ht->timer);
2305 +}
2306 +
2307 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
2308 +{
2309 +       /* remove timer, if it is pending */
2310 +       if (timer_pending(&hinfo->timer))
2311 +               del_timer(&hinfo->timer);
2312 +
2313 +       /* remove proc entry */
2314 +       remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
2315 +
2316 +       htable_selective_cleanup(hinfo, select_all);
2317 +       vfree(hinfo);
2318 +}
2319 +
2320 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
2321 +{
2322 +       struct ipt_dstlimit_htable *hinfo;
2323 +
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);
2329 +                       return hinfo;
2330 +               }
2331 +       }
2332 +       READ_UNLOCK(&dstlimit_lock);
2333 +
2334 +       return NULL;
2335 +}
2336 +
2337 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
2338 +{
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);
2344 +       }
2345 +}
2346 +
2347 +
2348 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
2349 + * see net/sched/sch_tbf.c in the linux source tree
2350 + */
2351 +
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
2356 +   test, `cost'.
2357 +
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.
2362 +
2363 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
2364 +
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.
2369 +*/
2370 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
2371 +
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
2374 + * shift. */
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)
2381 +
2382 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
2383 +
2384 +/* Precision saver. */
2385 +static inline u_int32_t
2386 +user2credits(u_int32_t user)
2387 +{
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;
2392 +
2393 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
2394 +}
2395 +
2396 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
2397 +{
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;
2402 +}
2403 +
2404 +static int
2405 +dstlimit_match(const struct sk_buff *skb,
2406 +               const struct net_device *in,
2407 +               const struct net_device *out,
2408 +               const void *matchinfo,
2409 +               int offset,
2410 +               int *hotdrop)
2411 +{
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;
2418 +
2419 +       memset(&dst, 0, sizeof(dst));
2420 +
2421 +       /* dest ip is always in hash */
2422 +       dst.dst_ip = skb->nh.iph->daddr;
2423 +
2424 +       /* source ip only if respective hashmode, otherwise set to
2425 +        * zero */
2426 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
2427 +               dst.src_ip = skb->nh.iph->saddr;
2428 +
2429 +       /* dest port only if respective mode */
2430 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
2431 +               u16 ports[2];
2432 +
2433 +               /* Must not be a fragment. */
2434 +               if (offset)
2435 +                       return 0;
2436 +
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. */
2442 +                       *hotdrop = 1;
2443 +                       return 0;
2444 +               }
2445 +
2446 +               switch (skb->nh.iph->protocol) {
2447 +                       struct tcphdr *th;
2448 +                       struct udphdr *uh;
2449 +               case IPPROTO_TCP:
2450 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
2451 +                       dst.port = th->dest;
2452 +                       break;
2453 +               case IPPROTO_UDP:
2454 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
2455 +                       dst.port = uh->dest;
2456 +                       break;
2457 +               default:
2458 +                       break;
2459 +               }
2460 +       } 
2461 +
2462 +       LOCK_BH(&hinfo->lock);
2463 +       dh = __dsthash_find(hinfo, &dst);
2464 +       if (!dh) {
2465 +               dh = __dsthash_alloc_init(hinfo, &dst);
2466 +
2467 +               if (!dh) {
2468 +                       /* enomem... don't match == DROP */
2469 +                       if (net_ratelimit())
2470 +                               printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
2471 +                       UNLOCK_BH(&hinfo->lock);
2472 +                       return 0;
2473 +               }
2474 +
2475 +               dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
2476 +
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);
2483 +
2484 +               UNLOCK_BH(&hinfo->lock);
2485 +               return 1;
2486 +       }
2487 +
2488 +       /* update expiration timeout */
2489 +       dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
2490 +
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);
2496 +               return 1;
2497 +       }
2498 +
2499 +               UNLOCK_BH(&hinfo->lock);
2500 +
2501 +       /* default case: we're overlimit, thus don't match */
2502 +       return 0;
2503 +}
2504 +
2505 +static int
2506 +dstlimit_checkentry(const char *tablename,
2507 +                    const struct ipt_ip *ip,
2508 +                    void *matchinfo,
2509 +                    unsigned int matchsize,
2510 +                    unsigned int hook_mask)
2511 +{
2512 +       struct ipt_dstlimit_info *r = matchinfo;
2513 +
2514 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
2515 +               return 0;
2516 +
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);
2523 +               return 0;
2524 +       }
2525 +
2526 +       if (r->cfg.mode == 0 
2527 +           || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
2528 +                         |IPT_DSTLIMIT_HASH_DIP
2529 +                         |IPT_DSTLIMIT_HASH_SIP))
2530 +               return 0;
2531 +
2532 +       if (!r->cfg.gc_interval)
2533 +               return 0;
2534 +       
2535 +       if (!r->cfg.expire)
2536 +               return 0;
2537 +
2538 +       r->hinfo = htable_find_get(r->name);
2539 +       if (!r->hinfo && (htable_create(r) != 0)) {
2540 +               return 0;
2541 +       }
2542 +
2543 +       /* Ugly hack: For SMP, we only want to use one set */
2544 +       r->u.master = r;
2545 +
2546 +       return 1;
2547 +}
2548 +
2549 +static void
2550 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
2551 +{
2552 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
2553 +
2554 +       htable_put(r->hinfo);
2555 +}
2556 +
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,
2563 +       .me = THIS_MODULE 
2564 +};
2565 +
2566 +/* PROC stuff */
2567 +
2568 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
2569 +{
2570 +       struct proc_dir_entry *pde = s->private;
2571 +       struct ipt_dstlimit_htable *htable = pde->data;
2572 +       unsigned int *bucket;
2573 +
2574 +       LOCK_BH(&htable->lock);
2575 +       if (*pos >= htable->cfg.size)
2576 +               return NULL;
2577 +
2578 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
2579 +       if (!bucket)
2580 +               return ERR_PTR(-ENOMEM);
2581 +
2582 +       *bucket = *pos;
2583 +       return bucket;
2584 +}
2585 +
2586 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
2587 +{
2588 +       struct proc_dir_entry *pde = s->private;
2589 +       struct ipt_dstlimit_htable *htable = pde->data;
2590 +       unsigned int *bucket = (unsigned int *)v;
2591 +
2592 +       *pos = ++(*bucket);
2593 +       if (*pos >= htable->cfg.size) {
2594 +               kfree(v);
2595 +               return NULL;
2596 +       }
2597 +       return bucket;
2598 +}
2599 +
2600 +static void dl_seq_stop(struct seq_file *s, void *v)
2601 +{
2602 +       struct proc_dir_entry *pde = s->private;
2603 +       struct ipt_dstlimit_htable *htable = pde->data;
2604 +       unsigned int *bucket = (unsigned int *)v;
2605 +
2606 +       kfree(bucket);
2607 +
2608 +       UNLOCK_BH(&htable->lock);
2609 +}
2610 +
2611 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
2612 +{
2613 +       /* recalculate to show accurate numbers */
2614 +       rateinfo_recalc(ent, jiffies);
2615 +
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);
2622 +}
2623 +
2624 +static int dl_seq_show(struct seq_file *s, void *v)
2625 +{
2626 +       struct proc_dir_entry *pde = s->private;
2627 +       struct ipt_dstlimit_htable *htable = pde->data;
2628 +       unsigned int *bucket = (unsigned int *)v;
2629 +
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 */
2633 +               return 1;
2634 +       }
2635 +       return 0;
2636 +}
2637 +
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
2643 +};
2644 +
2645 +static int dl_proc_open(struct inode *inode, struct file *file)
2646 +{
2647 +       int ret = seq_open(file, &dl_seq_ops);
2648 +
2649 +       if (!ret) {
2650 +               struct seq_file *sf = file->private_data;
2651 +               sf->private = PDE(inode);
2652 +       }
2653 +       return ret;
2654 +}
2655 +
2656 +static struct file_operations dl_file_ops = {
2657 +       .owner   = THIS_MODULE,
2658 +       .open    = dl_proc_open,
2659 +       .read    = seq_read,
2660 +       .llseek  = seq_lseek,
2661 +       .release = seq_release
2662 +};
2663 +
2664 +static int init_or_fini(int fini)
2665 +{
2666 +       int ret = 0;
2667 +
2668 +       if (fini)
2669 +               goto cleanup;
2670 +
2671 +       if (ipt_register_match(&ipt_dstlimit)) {
2672 +               ret = -EINVAL;
2673 +               goto cleanup_nothing;
2674 +       }
2675 +
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");
2683 +               ret = -ENOMEM;
2684 +               goto cleanup_unreg_match;
2685 +       }
2686 +
2687 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
2688 +       if (!dstlimit_procdir) {
2689 +               printk(KERN_ERR "Unable to create proc dir entry\n");
2690 +               ret = -ENOMEM;
2691 +               goto cleanup_free_slab;
2692 +       }
2693 +
2694 +       return ret;
2695 +
2696 +cleanup:
2697 +       remove_proc_entry("ipt_dstlimit", proc_net);
2698 +cleanup_free_slab:
2699 +       kmem_cache_destroy(dstlimit_cachep);
2700 +cleanup_unreg_match:
2701 +       ipt_unregister_match(&ipt_dstlimit);
2702 +cleanup_nothing:
2703 +       return ret;
2704 +       
2705 +}
2706 +
2707 +static int __init init(void)
2708 +{
2709 +       return init_or_fini(0);
2710 +}
2711 +
2712 +static void __exit fini(void)
2713 +{
2714 +       init_or_fini(1);
2715 +}
2716 +
2717 +module_init(init);
2718 +module_exit(fini);
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
2722 @@ -0,0 +1,185 @@
2723 +/*
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 .
2734 + *
2735 + *
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 .
2739 +*/
2740 +
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>
2749 +
2750 +/*
2751 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
2752 + Expressed in percentage
2753 +*/
2754 +
2755 +#define PAR_LOW                1/100
2756 +#define PAR_HIGH       1
2757 +
2758 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
2759 +
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");
2763 +
2764 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
2765 +{
2766 +       if (tx >= maxi)
2767 +               return 100;
2768 +
2769 +       if (tx <= mini)
2770 +               return 0;
2771 +
2772 +       return ( (100*(tx-mini)) / (maxi-mini) );
2773 +}
2774 +
2775 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
2776 +{
2777 +       if (tx <= mini)
2778 +               return 100;
2779 +
2780 +       if (tx >= maxi)
2781 +               return 0;
2782 +
2783 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) );
2784 +}
2785 +
2786 +static int
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,
2791 +              int offset,
2792 +              int *hotdrop)
2793 +{
2794 +       /* From userspace */
2795 +       
2796 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
2797 +
2798 +       u_int8_t random_number;
2799 +       unsigned long amount;
2800 +       u_int8_t howhigh, howlow;
2801 +       
2802 +
2803 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
2804 +
2805 +       info->bytes_total += pskb->len;
2806 +       info->packets_total++;
2807 +
2808 +       info->present_time = jiffies;
2809 +       
2810 +       if (info->present_time >= info->previous_time)
2811 +               amount = info->present_time - info->previous_time;
2812 +       else { 
2813 +               /* There was a transition : I choose to re-sample 
2814 +                  and keep the old acceptance rate...
2815 +               */
2816 +
2817 +               amount = 0;
2818 +               info->previous_time = info->present_time;
2819 +               info->bytes_total = info->packets_total = 0;
2820 +       };
2821 +       
2822 +       if (amount > HZ/10) /* More than 100 ms elapsed ... */
2823 +       {
2824 +
2825 +               info->mean_rate = (u_int32_t) ((HZ*info->packets_total)  \
2826 +                                       / amount );
2827 +
2828 +               info->previous_time = info->present_time;
2829 +               info->bytes_total = info->packets_total = 0;
2830 +
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);
2833 +
2834 +               info->acceptance_rate = (u_int8_t) \
2835 +                          (howhigh*PAR_LOW + PAR_HIGH*howlow);
2836 +
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 ,
2842 +                  I did so .  */ 
2843 +
2844 +       }
2845 +       
2846 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
2847 +
2848 +
2849 +       if ( info->acceptance_rate < 100 )
2850 +       {                
2851 +               get_random_bytes((void *)(&random_number), 1);
2852 +
2853 +               /*  If within the acceptance , it can pass => don't match */
2854 +               if (random_number <= (255 * info->acceptance_rate) / 100)
2855 +                       return 0;
2856 +               else
2857 +                       return 1; /* It can't pass ( It matches ) */
2858 +       } ;
2859 +
2860 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
2861 +       
2862 +}
2863 +
2864 +static int
2865 +ipt_fuzzy_checkentry(const char *tablename,
2866 +                  const struct ipt_ip *e,
2867 +                  void *matchinfo,
2868 +                  unsigned int matchsize,
2869 +                  unsigned int hook_mask)
2870 +{
2871 +       
2872 +       const struct ipt_fuzzy_info *info = matchinfo;
2873 +
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)));
2877 +               return 0;
2878 +       }
2879 +
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");
2883 +               return 0;
2884 +       }
2885 +
2886 +       return 1;
2887 +}
2888 +
2889 +static struct ipt_match ipt_fuzzy_reg = { 
2890 +       .name = "fuzzy",
2891 +       .match = ipt_fuzzy_match,
2892 +       .checkentry = ipt_fuzzy_checkentry,
2893 +       .me = THIS_MODULE
2894 +};
2895 +
2896 +static int __init init(void)
2897 +{
2898 +       return ipt_register_match(&ipt_fuzzy_reg);
2899 +}
2900 +
2901 +static void __exit fini(void)
2902 +{
2903 +       ipt_unregister_match(&ipt_fuzzy_reg);
2904 +}
2905 +
2906 +module_init(init);
2907 +module_exit(fini);
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
2911 @@ -0,0 +1,172 @@
2912 +/*
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
2917 +
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
2923 +*/
2924 +
2925 +#include <linux/module.h>
2926 +#include <linux/skbuff.h>
2927 +#include <net/ip.h>
2928 +
2929 +#include <linux/netfilter_ipv4/ip_tables.h>
2930 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
2931 +
2932 +MODULE_LICENSE("GPL");
2933 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
2934 +
2935 +static int
2936 +match(const struct sk_buff *skb,
2937 +      const struct net_device *in,
2938 +      const struct net_device *out,
2939 +      const void *matchinfo,
2940 +      int offset,
2941 +      int *hotdrop)
2942 +{
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;
2946 +
2947 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
2948 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
2949 +
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))
2956 +                       return 0;
2957 +               return 1;
2958 +       }
2959 +       else {
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 */
2962 +                       return 1;
2963 +               else {
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 ! */
2966 +                               return 0;
2967 +               }
2968 +       }
2969 +
2970 +       opt = &(IPCB(skb)->opt);
2971 +
2972 +       /* source routing */
2973 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
2974 +               if (!((opt->srr) & (opt->is_strictroute)))
2975 +                       return 0;
2976 +       }
2977 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
2978 +               if (!((opt->srr) & (!opt->is_strictroute)))
2979 +                       return 0;
2980 +       }
2981 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
2982 +               if (opt->srr)
2983 +                       return 0;
2984 +       }
2985 +       /* record route */
2986 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
2987 +               if (!opt->rr)
2988 +                       return 0;
2989 +       }
2990 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
2991 +               if (opt->rr)
2992 +                       return 0;
2993 +       }
2994 +       /* timestamp */
2995 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
2996 +               if (!opt->ts)
2997 +                       return 0;
2998 +       }
2999 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
3000 +               if (opt->ts)
3001 +                       return 0;
3002 +       }
3003 +       /* router-alert option  */
3004 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
3005 +               if (!opt->router_alert)
3006 +                       return 0;
3007 +       }
3008 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
3009 +               if (opt->router_alert)
3010 +                       return 0;
3011 +       }
3012 +
3013 +       /* we match ! */
3014 +       return 1;
3015 +}
3016 +
3017 +static int
3018 +checkentry(const char *tablename,
3019 +          const struct ipt_ip *ip,
3020 +          void *matchinfo,
3021 +          unsigned int matchsize,
3022 +          unsigned int hook_mask)
3023 +{
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)))
3027 +               return 0;
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 */
3060 +
3061 +       /* everything looks ok. */
3062 +       return 1;
3063 +}
3064 +
3065 +static struct ipt_match ipv4options_match = { 
3066 +       .name = "ipv4options",
3067 +       .match = match,
3068 +       .checkentry = checkentry,
3069 +       .me = THIS_MODULE
3070 +};
3071 +
3072 +static int __init init(void)
3073 +{
3074 +       return ipt_register_match(&ipv4options_match);
3075 +}
3076 +
3077 +static void __exit fini(void)
3078 +{
3079 +       ipt_unregister_match(&ipv4options_match);
3080 +}
3081 +
3082 +module_init(init);
3083 +module_exit(fini);
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
3087 @@ -0,0 +1,116 @@
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>
3094 +
3095 +#include <linux/netfilter_ipv4/ipt_mport.h>
3096 +#include <linux/netfilter_ipv4/ip_tables.h>
3097 +
3098 +MODULE_LICENSE("GPL");
3099 +
3100 +#if 0
3101 +#define duprintf(format, args...) printk(format , ## args)
3102 +#else
3103 +#define duprintf(format, args...)
3104 +#endif
3105 +
3106 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
3107 +static inline int
3108 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
3109 +{
3110 +       unsigned int i;
3111 +        unsigned int m;
3112 +        u_int16_t pflags = minfo->pflags;
3113 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
3114 +                u_int16_t s, e;
3115 +
3116 +                if (pflags & m
3117 +                    && minfo->ports[i] == 65535)
3118 +                        return 0;
3119 +
3120 +                s = minfo->ports[i];
3121 +
3122 +                if (pflags & m) {
3123 +                        e = minfo->ports[++i];
3124 +                        m <<= 1;
3125 +                } else
3126 +                        e = s;
3127 +
3128 +                if (minfo->flags & IPT_MPORT_SOURCE
3129 +                    && src >= s && src <= e)
3130 +                        return 1;
3131 +
3132 +               if (minfo->flags & IPT_MPORT_DESTINATION
3133 +                   && dst >= s && dst <= e)
3134 +                       return 1;
3135 +       }
3136 +
3137 +       return 0;
3138 +}
3139 +
3140 +static int
3141 +match(const struct sk_buff *skb,
3142 +      const struct net_device *in,
3143 +      const struct net_device *out,
3144 +      const void *matchinfo,
3145 +      int offset,
3146 +      int *hotdrop)
3147 +{
3148 +       u16 ports[2];
3149 +       const struct ipt_mport *minfo = matchinfo;
3150 +
3151 +       if (offset)
3152 +               return 0;
3153 +
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");
3161 +                       *hotdrop = 1;
3162 +                       return 0;
3163 +       }
3164 +
3165 +       return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
3166 +}
3167 +
3168 +/* Called when user tries to insert an entry of this type. */
3169 +static int
3170 +checkentry(const char *tablename,
3171 +          const struct ipt_ip *ip,
3172 +          void *matchinfo,
3173 +          unsigned int matchsize,
3174 +          unsigned int hook_mask)
3175 +{
3176 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
3177 +               return 0;
3178 +
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));
3183 +}
3184 +
3185 +static struct ipt_match mport_match = { 
3186 +       .name = "mport",
3187 +       .match = &match,
3188 +       .checkentry = &checkentry,
3189 +       .me = THIS_MODULE
3190 +};
3191 +
3192 +static int __init init(void)
3193 +{
3194 +       return ipt_register_match(&mport_match);
3195 +}
3196 +
3197 +static void __exit fini(void)
3198 +{
3199 +       ipt_unregister_match(&mport_match);
3200 +}
3201 +
3202 +module_init(init);
3203 +module_exit(fini);
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
3207 @@ -0,0 +1,166 @@
3208 +/*
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
3213 +
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>
3220 +       * port to 2.6.x
3221 +
3222 +*/
3223 +
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>
3231 +
3232 +MODULE_LICENSE("GPL");
3233 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
3234 +
3235 +/*
3236 + * State information.
3237 + */
3238 +struct state {
3239 +       spinlock_t lock;
3240 +       u_int16_t number;
3241 +};
3242 +
3243 +static struct state states[IPT_NTH_NUM_COUNTERS];
3244 +
3245 +static int
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,
3250 +             int offset,
3251 +             int *hotdrop)
3252 +{
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)) 
3257 +       {
3258 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3259 +               return 0;
3260 +        };
3261 +
3262 +        spin_lock(&states[counter].lock);
3263 +
3264 +        /* Are we matching every nth packet?*/
3265 +        if (info->packet == 0xFF)
3266 +        {
3267 +               /* We're matching every nth packet and only every nth packet*/
3268 +               /* Do we match or invert match? */
3269 +               if (info->not == 0)
3270 +               {
3271 +                       if (states[counter].number == 0)
3272 +                       {
3273 +                               ++states[counter].number;
3274 +                               goto match;
3275 +                       }
3276 +                       if (states[counter].number >= info->every)
3277 +                               states[counter].number = 0; /* reset the counter */
3278 +                       else
3279 +                               ++states[counter].number;
3280 +                       goto dontmatch;
3281 +               }
3282 +               else
3283 +               {
3284 +                       if (states[counter].number == 0)
3285 +                       {
3286 +                               ++states[counter].number;
3287 +                               goto dontmatch;
3288 +                       }
3289 +                       if (states[counter].number >= info->every)
3290 +                               states[counter].number = 0;
3291 +                       else
3292 +                               ++states[counter].number;
3293 +                       goto match;
3294 +               }
3295 +        }
3296 +        else
3297 +        {
3298 +               /* We're using the --packet, so there must be a rule for every value */
3299 +               if (states[counter].number == info->packet)
3300 +               {
3301 +                       /* only increment the counter when a match happens */
3302 +                       if (states[counter].number >= info->every)
3303 +                               states[counter].number = 0; /* reset the counter */
3304 +                       else
3305 +                               ++states[counter].number;
3306 +                       goto match;
3307 +               }
3308 +               else
3309 +                       goto dontmatch;
3310 +       }
3311 +
3312 + dontmatch:
3313 +       /* don't match */
3314 +       spin_unlock(&states[counter].lock);
3315 +       return 0;
3316 +
3317 + match:
3318 +       spin_unlock(&states[counter].lock);
3319 +       return 1;
3320 +}
3321 +
3322 +static int
3323 +ipt_nth_checkentry(const char *tablename,
3324 +                  const struct ipt_ip *e,
3325 +                  void *matchinfo,
3326 +                  unsigned int matchsize,
3327 +                  unsigned int hook_mask)
3328 +{
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)) 
3333 +       {
3334 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3335 +                       return 0;
3336 +               };
3337 +
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)));
3341 +               return 0;
3342 +       }
3343 +
3344 +       states[counter].number = info->startat;
3345 +
3346 +       return 1;
3347 +}
3348 +
3349 +static struct ipt_match ipt_nth_reg = { 
3350 +       .name = "nth",
3351 +       .match = ipt_nth_match,
3352 +       .checkentry = ipt_nth_checkentry,
3353 +       .me = THIS_MODULE
3354 +};
3355 +
3356 +static int __init init(void)
3357 +{
3358 +       unsigned counter;
3359 +
3360 +       memset(&states, 0, sizeof(states));
3361 +        for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
3362 +               spin_lock_init(&(states[counter].lock));
3363 +
3364 +       return ipt_register_match(&ipt_nth_reg);
3365 +}
3366 +
3367 +static void __exit fini(void)
3368 +{
3369 +       ipt_unregister_match(&ipt_nth_reg);
3370 +}
3371 +
3372 +module_init(init);
3373 +module_exit(fini);
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
3377 @@ -0,0 +1,91 @@
3378 +/* 
3379 + * netfilter module to enforce network quotas
3380 + *
3381 + * Sam Johnston <samj@samj.net>
3382 + */
3383 +#include <linux/module.h>
3384 +#include <linux/skbuff.h>
3385 +#include <linux/spinlock.h>
3386 +#include <linux/interrupt.h>
3387 +
3388 +#include <linux/netfilter_ipv4/ip_tables.h>
3389 +#include <linux/netfilter_ipv4/ipt_quota.h>
3390 +
3391 +MODULE_LICENSE("GPL");
3392 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
3393 +
3394 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
3395 +
3396 +static int
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)
3402 +{
3403 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
3404 +       unsigned int datalen;
3405 +
3406 +       if (skb->len < sizeof(struct iphdr))
3407 +               return NF_ACCEPT;
3408 +       
3409 +       datalen = skb->len - skb->nh.iph->ihl*4;
3410 +
3411 +        spin_lock_bh(&quota_lock);
3412 +
3413 +        if (q->quota >= datalen) {
3414 +                /* we can afford this one */
3415 +                q->quota -= datalen;
3416 +                spin_unlock_bh(&quota_lock);
3417 +
3418 +#ifdef DEBUG_IPT_QUOTA
3419 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
3420 +#endif
3421 +                return 1;
3422 +        }
3423 +
3424 +        /* so we do not allow even small packets from now on */
3425 +        q->quota = 0;
3426 +
3427 +#ifdef DEBUG_IPT_QUOTA
3428 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
3429 +#endif
3430 +
3431 +        spin_unlock_bh(&quota_lock);
3432 +        return 0;
3433 +}
3434 +
3435 +static int
3436 +checkentry(const char *tablename,
3437 +           const struct ipt_ip *ip,
3438 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
3439 +{
3440 +        /* TODO: spinlocks? sanity checks? */
3441 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
3442 +                return 0;
3443 +
3444 +        return 1;
3445 +}
3446 +
3447 +static struct ipt_match quota_match = {
3448 +       .name = "quota",
3449 +       .match = match,
3450 +       .checkentry = checkentry,
3451 +       .me = THIS_MODULE
3452 +};
3453 +
3454 +static int __init
3455 +init(void)
3456 +{
3457 +        return ipt_register_match(&quota_match);
3458 +}
3459 +
3460 +static void __exit
3461 +fini(void)
3462 +{
3463 +        ipt_unregister_match(&quota_match);
3464 +}
3465 +
3466 +module_init(init);
3467 +module_exit(fini);
3468 +
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
3472 @@ -0,0 +1,70 @@
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>
3478 +
3479 +#include <linux/netfilter_ipv4/ipt_realm.h>
3480 +#include <linux/netfilter_ipv4/ip_tables.h>
3481 +
3482 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
3483 +MODULE_LICENSE("GPL");
3484 +
3485 +static int
3486 +match(const struct sk_buff *skb,
3487 +      const struct net_device *in,
3488 +      const struct net_device *out,
3489 +      const void *matchinfo,
3490 +      int offset,
3491 +      int *hotdrop)
3492 +{
3493 +       const struct ipt_realm_info *info = matchinfo;
3494 +       struct dst_entry *dst = skb->dst;
3495 +       u32 id;
3496 +    
3497 +       if(dst == NULL)
3498 +               return 0;
3499 +       id = dst->tclassid;
3500 +
3501 +       return (info->id == (id & info->mask)) ^ info->invert;
3502 +}
3503 +
3504 +static int check(const char *tablename,
3505 +                 const struct ipt_ip *ip,
3506 +                 void *matchinfo,
3507 +                 unsigned int matchsize,
3508 +                 unsigned int hook_mask)
3509 +{
3510 +       if (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");
3515 +               return 0;
3516 +       }
3517 +
3518 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
3519 +               return 0;
3520 +
3521 +       return 1;
3522 +}
3523 +
3524 +static struct ipt_match realm_match = {
3525 +       .name = "realm",
3526 +       .match = match, 
3527 +       .checkentry = check,
3528 +       .me = THIS_MODULE
3529 +};
3530 +
3531 +static int __init init(void)
3532 +{
3533 +       return ipt_register_match(&realm_match);
3534 +}
3535 +
3536 +static void __exit fini(void)
3537 +{
3538 +       ipt_unregister_match(&realm_match);
3539 +}
3540 +
3541 +module_init(init);
3542 +module_exit(fini);
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
3546 @@ -0,0 +1,197 @@
3547 +#include <linux/module.h>
3548 +#include <linux/skbuff.h>
3549 +#include <net/ip.h>
3550 +#include <linux/sctp.h>
3551 +
3552 +#include <linux/netfilter_ipv4/ip_tables.h>
3553 +#include <linux/netfilter_ipv4/ipt_sctp.h>
3554 +
3555 +#if 1
3556 +#define duprintf(format, args...) printk(format , ## args)
3557 +#else
3558 +#define duprintf(format, args...)
3559 +#endif
3560 +
3561 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
3562 +                                             || (!!((invflag) & (option)) ^ (cond)))
3563 +
3564 +static int
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)
3569 +{
3570 +       int i;
3571 +
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;
3575 +               }
3576 +       }
3577 +
3578 +       return 1;
3579 +}
3580 +
3581 +static int
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,
3587 +            int *hotdrop)
3588 +{
3589 +       int offset;
3590 +       u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
3591 +       sctp_chunkhdr_t sch;
3592 +
3593 +       if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
3594 +               SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
3595 +       }
3596 +
3597 +       offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
3598 +       do {
3599 +               if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
3600 +                       duprintf("Dropping invalid SCTP packet.\n");
3601 +                       *hotdrop = 1;
3602 +                       return 0;
3603 +               }
3604 +
3605 +               duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", 
3606 +                               ++i, offset, sch.type, htons(sch.length), sch.flags);
3607 +
3608 +               offset += (htons(sch.length) + 3) & ~3;
3609 +
3610 +               duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
3611 +
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)) {
3617 +                                       return 1;
3618 +                               }
3619 +                               break;
3620 +
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);
3625 +                               }
3626 +                               break;
3627 +
3628 +                       case SCTP_CHUNK_MATCH_ONLY:
3629 +                               if (!match_flags(flag_info, flag_count, 
3630 +                                       sch.type, sch.flags)) {
3631 +                                       return 0;
3632 +                               }
3633 +                               break;
3634 +                       }
3635 +               } else {
3636 +                       switch (chunk_match_type) {
3637 +                       case SCTP_CHUNK_MATCH_ONLY:
3638 +                               return 0;
3639 +                       }
3640 +               }
3641 +       } while (offset < skb->len);
3642 +
3643 +       switch (chunk_match_type) {
3644 +       case SCTP_CHUNK_MATCH_ALL:
3645 +               return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
3646 +       case SCTP_CHUNK_MATCH_ANY:
3647 +               return 0;
3648 +       case SCTP_CHUNK_MATCH_ONLY:
3649 +               return 1;
3650 +       }
3651 +
3652 +       /* This will never be reached, but required to stop compiler whine */
3653 +       return 0;
3654 +}
3655 +
3656 +static int
3657 +match(const struct sk_buff *skb,
3658 +      const struct net_device *in,
3659 +      const struct net_device *out,
3660 +      const void *matchinfo,
3661 +      int offset,
3662 +      int *hotdrop)
3663 +{
3664 +       const struct ipt_sctp_info *info;
3665 +       sctp_sctphdr_t sh;
3666 +
3667 +       info = (const struct ipt_sctp_info *)matchinfo;
3668 +
3669 +       if (offset) {
3670 +               duprintf("Dropping non-first fragment.. FIXME\n");
3671 +               return 0;
3672 +       }
3673 +       
3674 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
3675 +               duprintf("Dropping evil TCP offset=0 tinygram.\n");
3676 +               *hotdrop = 1;
3677 +               return 0;
3678 +               }
3679 +       duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
3680 +
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, 
3689 +                                       hotdrop),
3690 +                          IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
3691 +}
3692 +
3693 +static int
3694 +checkentry(const char *tablename,
3695 +          const struct ipt_ip *ip,
3696 +          void *matchinfo,
3697 +          unsigned int matchsize,
3698 +          unsigned int hook_mask)
3699 +{
3700 +       const struct ipt_sctp_info *info;
3701 +
3702 +       info = (const struct ipt_sctp_info *)matchinfo;
3703 +
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)));
3715 +}
3716 +
3717 +static struct ipt_match sctp_match = 
3718 +{ 
3719 +       .list = { NULL, NULL},
3720 +       .name = "sctp",
3721 +       .match = &match,
3722 +       .checkentry = &checkentry,
3723 +       .destroy = NULL,
3724 +       .me = THIS_MODULE
3725 +};
3726 +
3727 +static int __init init(void)
3728 +{
3729 +       return ipt_register_match(&sctp_match);
3730 +}
3731 +
3732 +static void __exit fini(void)
3733 +{
3734 +       ipt_unregister_match(&sctp_match);
3735 +}
3736 +
3737 +module_init(init);
3738 +module_exit(fini);
3739 +
3740 +MODULE_LICENSE("GPL");
3741 +MODULE_AUTHOR("Kiran Kumar Immidi");
3742 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
3743 +
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.
3749  
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
3754 +         help
3755 +
3756 +config IP6_NF_TARGET_REJECT
3757 +       tristate  'REJECT target support'
3758 +       depends on IP6_NF_FILTER
3759 +         help
3760 +
3761 +config IP6_NF_MATCH_FUZZY
3762 +       tristate  'Fuzzy match support'
3763 +       depends on IP6_NF_FILTER
3764 +         help
3765 +
3766 +config IP6_NF_MATCH_NTH
3767 +       tristate  'Nth match support'
3768 +       depends on IP6_NF_IPTABLES
3769 +         help
3770 +
3771  endmenu
3772  
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
3776 @@ -8,6 +8,7 @@
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
3784 @@ -19,6 +20,10 @@
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
3791 +
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
3798 @@ -0,0 +1,105 @@
3799 +/* 
3800 + * Hop Limit modification target for ip6tables
3801 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
3802 + * Based on HW's TTL module
3803 + *
3804 + * This software is distributed under the terms of GNU GPL
3805 + */
3806 +
3807 +#include <linux/module.h>
3808 +#include <linux/skbuff.h>
3809 +#include <linux/ip.h>
3810 +
3811 +#include <linux/netfilter_ipv6/ip6_tables.h>
3812 +#include <linux/netfilter_ipv6/ip6t_HL.h>
3813 +
3814 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
3815 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
3816 +MODULE_LICENSE("GPL");
3817 +
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)
3821 +{
3822 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
3823 +       const struct ip6t_HOPLIMIT_info *info = targinfo;
3824 +       u_int16_t diffs[2];
3825 +       int new_hl;
3826 +                        
3827 +       switch (info->mode) {
3828 +               case IP6T_HOPLIMIT_SET:
3829 +                       new_hl = info->hop_limit;
3830 +                       break;
3831 +               case IP6T_HOPLIMIT_INC:
3832 +                       new_hl = ip6h->hop_limit + info->hop_limit;
3833 +                       if (new_hl > 255)
3834 +                               new_hl = 255;
3835 +                       break;
3836 +               case IP6T_HOPLIMIT_DEC:
3837 +                       new_hl = ip6h->hop_limit + info->hop_limit;
3838 +                       if (new_hl < 0)
3839 +                               new_hl = 0;
3840 +                       break;
3841 +               default:
3842 +                       new_hl = ip6h->hop_limit;
3843 +                       break;
3844 +       }
3845 +
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);
3850 +       }
3851 +
3852 +       return IP6T_CONTINUE;
3853 +}
3854 +
3855 +static int ip6t_hl_checkentry(const char *tablename,
3856 +               const struct ip6t_entry *e,
3857 +               void *targinfo,
3858 +               unsigned int targinfosize,
3859 +               unsigned int hook_mask)
3860 +{
3861 +       struct ip6t_HOPLIMIT_info *info = targinfo;
3862 +
3863 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HOPLIMIT_info))) {
3864 +               printk(KERN_WARNING "HOPLIMIT: targinfosize %u != %Zu\n",
3865 +                               targinfosize,
3866 +                               IP6T_ALIGN(sizeof(struct ip6t_HOPLIMIT_info)));
3867 +               return 0;       
3868 +       }       
3869 +
3870 +       if (strcmp(tablename, "mangle")) {
3871 +               printk(KERN_WARNING "HOPLIMIT: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
3872 +               return 0;
3873 +       }
3874 +
3875 +       if (info->mode > IP6T_HOPLIMIT_MAXMODE) {
3876 +               printk(KERN_WARNING "HOPLIMIT: invalid or unknown Mode %u\n", 
3877 +                       info->mode);
3878 +               return 0;
3879 +       }
3880 +
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");
3883 +               return 0;
3884 +       }
3885 +       
3886 +       return 1;
3887 +}
3888 +
3889 +static struct ip6t_target ip6t_HOPLIMIT = { { NULL, NULL }, "HL", 
3890 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
3891 +
3892 +static int __init init(void)
3893 +{
3894 +       return ip6t_register_target(&ip6t_HOPLIMIT);
3895 +}
3896 +
3897 +static void __exit fini(void)
3898 +{
3899 +       ip6t_unregister_target(&ip6t_HOPLIMIT);
3900 +}
3901 +
3902 +module_init(init);
3903 +module_exit(fini);
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
3907 @@ -0,0 +1,274 @@
3908 +/*
3909 + * This is a module which is used for rejecting packets.
3910 + *     Added support for customized reject packets (Jozsef Kadlecsik).
3911 + * Sun 12 Nov 2000
3912 + *     Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
3913 + */
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>
3921 +
3922 +#if 1
3923 +#define DEBUGP printk
3924 +#else
3925 +#define DEBUGP(format, args...)
3926 +#endif
3927 +
3928 +#if 0
3929 +/* Send RST reply */
3930 +static void send_reset(struct sk_buff *oldskb)
3931 +{
3932 +       struct sk_buff *nskb;
3933 +       struct tcphdr *otcph, *tcph;
3934 +       struct rtable *rt;
3935 +       unsigned int otcplen;
3936 +       int needs_ack;
3937 +
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))
3941 +               return;
3942 +
3943 +       otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
3944 +       otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
3945 +
3946 +       /* No RST for RST. */
3947 +       if (otcph->rst)
3948 +               return;
3949 +
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)
3954 +               return;
3955 +
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);
3960 +       if (!nskb)
3961 +               return;
3962 +
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;
3969 +#endif
3970 +
3971 +       tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
3972 +
3973 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
3974 +       tcph->source = xchg(&tcph->dest, tcph->source);
3975 +
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);
3980 +
3981 +       if (tcph->ack) {
3982 +               needs_ack = 0;
3983 +               tcph->seq = otcph->ack_seq;
3984 +               tcph->ack_seq = 0;
3985 +       } else {
3986 +               needs_ack = 1;
3987 +               tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
3988 +                                     + otcplen - (otcph->doff<<2));
3989 +               tcph->seq = 0;
3990 +       }
3991 +
3992 +       /* Reset flags */
3993 +       ((u_int8_t *)tcph)[13] = 0;
3994 +       tcph->rst = 1;
3995 +       tcph->ack = needs_ack;
3996 +
3997 +       tcph->window = 0;
3998 +       tcph->urg_ptr = 0;
3999 +
4000 +       /* Adjust TCP checksum */
4001 +       tcph->check = 0;
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));
4007 +
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;
4013 +
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);
4018 +
4019 +       /* Routing */
4020 +       if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
4021 +                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
4022 +                           0) != 0)
4023 +               goto free_nskb;
4024 +
4025 +       dst_release(nskb->dst);
4026 +       nskb->dst = &rt->u.dst;
4027 +
4028 +       /* "Never happens" */
4029 +       if (nskb->len > nskb->dst->pmtu)
4030 +               goto free_nskb;
4031 +
4032 +       NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
4033 +               ip_finish_output);
4034 +       return;
4035 +
4036 + free_nskb:
4037 +       kfree_skb(nskb);
4038 +}
4039 +#endif
4040 +
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,
4046 +                          void *userinfo)
4047 +{
4048 +       const struct ip6t_reject_info *reject = targinfo;
4049 +
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);
4057 +               break;
4058 +       case IP6T_ICMP6_ADM_PROHIBITED:
4059 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
4060 +               break;
4061 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
4062 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
4063 +               break;
4064 +       case IP6T_ICMP6_ADDR_UNREACH:
4065 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
4066 +               break;
4067 +       case IP6T_ICMP6_PORT_UNREACH:
4068 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
4069 +               break;
4070 +#if 0
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;
4075 +
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
4081 +                           mins! --RR */
4082 +                       struct icmp_bxm icmp_param;
4083 +
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);
4089 +               }
4090 +       }
4091 +       break;
4092 +       case IPT_TCP_RESET:
4093 +               send_reset(*pskb);
4094 +               break;
4095 +#endif
4096 +       default:
4097 +               printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
4098 +               break;
4099 +       }
4100 +
4101 +       return NF_DROP;
4102 +}
4103 +
4104 +static inline int find_ping_match(const struct ip6t_entry_match *m)
4105 +{
4106 +       const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
4107 +
4108 +       if (strcmp(m->u.kernel.match->name, "icmp6") == 0
4109 +           && icmpinfo->type == ICMPV6_ECHO_REQUEST
4110 +           && !(icmpinfo->invflags & IP6T_ICMP_INV))
4111 +               return 1;
4112 +
4113 +       return 0;
4114 +}
4115 +
4116 +static int check(const char *tablename,
4117 +                const struct ip6t_entry *e,
4118 +                void *targinfo,
4119 +                unsigned int targinfosize,
4120 +                unsigned int hook_mask)
4121 +{
4122 +       const struct ip6t_reject_info *rejinfo = targinfo;
4123 +
4124 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
4125 +               DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
4126 +               return 0;
4127 +       }
4128 +
4129 +       /* Only allow these for packet filtering. */
4130 +       if (strcmp(tablename, "filter") != 0) {
4131 +               DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
4132 +               return 0;
4133 +       }
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);
4138 +               return 0;
4139 +       }
4140 +
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");
4146 +                       return 0;
4147 +               }
4148 +               /* Must contain ICMP match. */
4149 +               if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
4150 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
4151 +                       return 0;
4152 +               }
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");
4158 +                       return 0;
4159 +               }
4160 +       }
4161 +
4162 +       return 1;
4163 +}
4164 +
4165 +static struct ip6t_target ip6t_reject_reg
4166 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
4167 +
4168 +static int __init init(void)
4169 +{
4170 +       if (ip6t_register_target(&ip6t_reject_reg))
4171 +               return -EINVAL;
4172 +       return 0;
4173 +}
4174 +
4175 +static void __exit fini(void)
4176 +{
4177 +       ip6t_unregister_target(&ip6t_reject_reg);
4178 +}
4179 +
4180 +module_init(init);
4181 +module_exit(fini);
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
4185 @@ -0,0 +1,189 @@
4186 +/*
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 .
4197 + *
4198 + *
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
4203 + */
4204 +
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>
4213 +
4214 +/*
4215 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
4216 + Expressed in percentage
4217 +*/
4218 +
4219 +#define PAR_LOW                1/100
4220 +#define PAR_HIGH       1
4221 +
4222 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
4223 +
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");
4227 +
4228 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
4229 +{
4230 +       if (tx >= maxi) return 100;
4231 +
4232 +       if (tx <= mini) return 0;
4233 +
4234 +       return ((100 * (tx-mini)) / (maxi-mini));
4235 +}
4236 +
4237 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
4238 +{
4239 +       if (tx <= mini) return 100;
4240 +
4241 +       if (tx >= maxi) return 0;
4242 +
4243 +       return ((100 * (maxi - tx)) / (maxi - mini));
4244 +
4245 +}
4246 +
4247 +static int
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,
4252 +              int offset,
4253 +              const void *hdr,
4254 +              u_int16_t datalen,
4255 +              int *hotdrop)
4256 +{
4257 +       /* From userspace */
4258 +
4259 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
4260 +
4261 +       u_int8_t random_number;
4262 +       unsigned long amount;
4263 +       u_int8_t howhigh, howlow;
4264 +
4265 +
4266 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
4267 +
4268 +       info->bytes_total += pskb->len;
4269 +       info->packets_total++;
4270 +
4271 +       info->present_time = jiffies;
4272 +
4273 +       if (info->present_time >= info->previous_time)
4274 +               amount = info->present_time - info->previous_time;
4275 +       else {
4276 +               /* There was a transition : I choose to re-sample
4277 +                  and keep the old acceptance rate...
4278 +               */
4279 +
4280 +               amount = 0;
4281 +               info->previous_time = info->present_time;
4282 +               info->bytes_total = info->packets_total = 0;
4283 +            };
4284 +
4285 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
4286 +
4287 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
4288 +                                       / amount);
4289 +
4290 +               info->previous_time = info->present_time;
4291 +               info->bytes_total = info->packets_total = 0;
4292 +
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);
4295 +
4296 +               info->acceptance_rate = (u_int8_t) \
4297 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
4298 +
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,
4304 +        * I did so.
4305 +        */
4306 +
4307 +       }
4308 +
4309 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
4310 +
4311 +
4312 +       if (info->acceptance_rate < 100)
4313 +       {
4314 +               get_random_bytes((void *)(&random_number), 1);
4315 +
4316 +               /*  If within the acceptance , it can pass => don't match */
4317 +               if (random_number <= (255 * info->acceptance_rate) / 100)
4318 +                       return 0;
4319 +               else
4320 +                       return 1; /* It can't pass (It matches) */
4321 +       };
4322 +
4323 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
4324 +
4325 +}
4326 +
4327 +static int
4328 +ip6t_fuzzy_checkentry(const char *tablename,
4329 +                  const struct ip6t_ip6 *ip,
4330 +                  void *matchinfo,
4331 +                  unsigned int matchsize,
4332 +                  unsigned int hook_mask)
4333 +{
4334 +
4335 +       const struct ip6t_fuzzy_info *info = matchinfo;
4336 +
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)));
4340 +               return 0;
4341 +       }
4342 +
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");
4346 +               return 0;
4347 +       }
4348 +
4349 +       return 1;
4350 +}
4351 +
4352 +static struct ip6t_match ip6t_fuzzy_reg = {
4353 +       {NULL, NULL},
4354 +       "fuzzy",
4355 +       ip6t_fuzzy_match,
4356 +       ip6t_fuzzy_checkentry,
4357 +       NULL,
4358 +       THIS_MODULE };
4359 +
4360 +static int __init init(void)
4361 +{
4362 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
4363 +               return -EINVAL;
4364 +
4365 +       return 0;
4366 +}
4367 +
4368 +static void __exit fini(void)
4369 +{
4370 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
4371 +}
4372 +
4373 +module_init(init);
4374 +module_exit(fini);
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
4378 @@ -0,0 +1,173 @@
4379 +/*
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
4384 +
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
4391 +
4392 +*/
4393 +
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>
4401 +
4402 +MODULE_LICENSE("GPL");
4403 +
4404 +/*
4405 + * State information.
4406 + */
4407 +struct state {
4408 +       spinlock_t lock;
4409 +       u_int16_t number;
4410 +};
4411 +
4412 +static struct state states[IP6T_NTH_NUM_COUNTERS];
4413 +
4414 +static int
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,
4419 +             int offset,
4420 +             const void *hdr,
4421 +             u_int16_t datalen,
4422 +             int *hotdrop)
4423 +{
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)) 
4428 +       {
4429 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
4430 +               return 0;
4431 +        };
4432 +
4433 +        spin_lock(&states[counter].lock);
4434 +
4435 +        /* Are we matching every nth packet?*/
4436 +        if (info->packet == 0xFF)
4437 +        {
4438 +               /* We're matching every nth packet and only every nth packet*/
4439 +               /* Do we match or invert match? */
4440 +               if (info->not == 0)
4441 +               {
4442 +                       if (states[counter].number == 0)
4443 +                       {
4444 +                               ++states[counter].number;
4445 +                               goto match;
4446 +                       }
4447 +                       if (states[counter].number >= info->every)
4448 +                               states[counter].number = 0; /* reset the counter */
4449 +                       else
4450 +                               ++states[counter].number;
4451 +                       goto dontmatch;
4452 +               }
4453 +               else
4454 +               {
4455 +                       if (states[counter].number == 0)
4456 +                       {
4457 +                               ++states[counter].number;
4458 +                               goto dontmatch;
4459 +                       }
4460 +                       if (states[counter].number >= info->every)
4461 +                               states[counter].number = 0;
4462 +                       else
4463 +                               ++states[counter].number;
4464 +                       goto match;
4465 +               }
4466 +        }
4467 +        else
4468 +        {
4469 +               /* We're using the --packet, so there must be a rule for every value */
4470 +               if (states[counter].number == info->packet)
4471 +               {
4472 +                       /* only increment the counter when a match happens */
4473 +                       if (states[counter].number >= info->every)
4474 +                               states[counter].number = 0; /* reset the counter */
4475 +                       else
4476 +                               ++states[counter].number;
4477 +                       goto match;
4478 +               }
4479 +               else
4480 +                       goto dontmatch;
4481 +       }
4482 +
4483 + dontmatch:
4484 +       /* don't match */
4485 +       spin_unlock(&states[counter].lock);
4486 +       return 0;
4487 +
4488 + match:
4489 +       spin_unlock(&states[counter].lock);
4490 +       return 1;
4491 +}
4492 +
4493 +static int
4494 +ip6t_nth_checkentry(const char *tablename,
4495 +                  const struct ip6t_ip6 *e,
4496 +                  void *matchinfo,
4497 +                  unsigned int matchsize,
4498 +                  unsigned int hook_mask)
4499 +{
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)) 
4504 +       {
4505 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
4506 +                       return 0;
4507 +               };
4508 +
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)));
4512 +               return 0;
4513 +       }
4514 +
4515 +       states[counter].number = info->startat;
4516 +
4517 +       return 1;
4518 +}
4519 +
4520 +static struct ip6t_match ip6t_nth_reg = { 
4521 +       {NULL, NULL},
4522 +       "nth",
4523 +       ip6t_nth_match,
4524 +       ip6t_nth_checkentry,
4525 +       NULL,
4526 +       THIS_MODULE };
4527 +
4528 +static int __init init(void)
4529 +{
4530 +       unsigned counter;
4531 +        memset(&states, 0, sizeof(states));
4532 +       if (ip6t_register_match(&ip6t_nth_reg))
4533 +               return -EINVAL;
4534 +
4535 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
4536 +       {
4537 +               spin_lock_init(&(states[counter].lock));
4538 +        };
4539 +
4540 +       printk("ip6t_nth match loaded\n");
4541 +       return 0;
4542 +}
4543 +
4544 +static void __exit fini(void)
4545 +{
4546 +       ip6t_unregister_match(&ip6t_nth_reg);
4547 +       printk("ip6t_nth match unloaded\n");
4548 +}
4549 +
4550 +module_init(init);
4551 +module_exit(fini);
This page took 0.413889 seconds and 3 git commands to generate.