]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.x-patch-o-matic-ng-base-20040307.patch
- fix unresolved symbols in ipv6 netfilter
[packages/kernel.git] / 2.6.x-patch-o-matic-ng-base-20040307.patch
1 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/include/linux/netfilter.h linux-2.6.4-rc2/include/linux/netfilter.h
2 --- linux-2.6.4-rc2.org/include/linux/netfilter.h       2004-03-04 06:16:47.000000000 +0000
3 +++ linux-2.6.4-rc2/include/linux/netfilter.h   2004-03-07 08:43:12.000000000 +0000
4 @@ -99,6 +99,24 @@
5  
6  extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
7  
8 +typedef void nf_logfn(unsigned int hooknum,
9 +                     const struct sk_buff *skb,
10 +                     const struct net_device *in,
11 +                     const struct net_device *out,
12 +                     const char *prefix);
13 +
14 +/* Function to register/unregister log function. */
15 +int nf_log_register(int pf, nf_logfn *logfn);
16 +void nf_log_unregister(int pf, nf_logfn *logfn);
17 +
18 +/* Calls the registered backend logging function */
19 +void nf_log_packet(int pf,
20 +                  unsigned int hooknum,
21 +                  const struct sk_buff *skb,
22 +                  const struct net_device *in,
23 +                  const struct net_device *out,
24 +                  const char *fmt, ...);
25 +                   
26  /* Activate hook; either okfn or kfree_skb called, unless a hook
27     returns NF_STOLEN (in which case, it's up to the hook to deal with
28     the consequences).
29 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ip_conntrack.h
30 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ip_conntrack.h     2004-03-04 06:17:04.000000000 +0000
31 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ip_conntrack.h 2004-03-07 08:43:29.000000000 +0000
32 @@ -251,6 +251,9 @@
33  /* Call me when a conntrack is destroyed. */
34  extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
35  
36 +/* Fake conntrack entry for untracked connections */
37 +extern struct ip_conntrack ip_conntrack_untracked;
38 +
39  /* Returns new sk_buff, or NULL */
40  struct sk_buff *
41  ip_ct_gather_frags(struct sk_buff *skb);
42 diff -Nur --exclude '*.orig' 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
43 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_TTL.h  1970-01-01 00:00:00.000000000 +0000
44 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_TTL.h      2004-03-07 08:43:16.000000000 +0000
45 @@ -0,0 +1,21 @@
46 +/* TTL modification module for IP tables
47 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
48 +
49 +#ifndef _IPT_TTL_H
50 +#define _IPT_TTL_H
51 +
52 +enum {
53 +       IPT_TTL_SET = 0,
54 +       IPT_TTL_INC,
55 +       IPT_TTL_DEC
56 +};
57 +
58 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
59 +
60 +struct ipt_TTL_info {
61 +       u_int8_t        mode;
62 +       u_int8_t        ttl;
63 +};
64 +
65 +
66 +#endif
67 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_ULOG.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_ULOG.h
68 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_ULOG.h 2004-03-04 06:16:43.000000000 +0000
69 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_ULOG.h     2004-03-07 08:43:12.000000000 +0000
70 @@ -11,6 +11,9 @@
71  #define NETLINK_NFLOG  5
72  #endif
73  
74 +#define ULOG_DEFAULT_NLGROUP   1
75 +#define ULOG_DEFAULT_QTHRESHOLD        1
76 +
77  #define ULOG_MAC_LEN   80
78  #define ULOG_PREFIX_LEN        32
79  
80 diff -Nur --exclude '*.orig' 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
81 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_connlimit.h    1970-01-01 00:00:00.000000000 +0000
82 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_connlimit.h        2004-03-07 08:43:18.000000000 +0000
83 @@ -0,0 +1,12 @@
84 +#ifndef _IPT_CONNLIMIT_H
85 +#define _IPT_CONNLIMIT_H
86 +
87 +struct ipt_connlimit_data;
88 +
89 +struct ipt_connlimit_info {
90 +       int limit;
91 +       int inverse;
92 +       u_int32_t mask;
93 +       struct ipt_connlimit_data *data;
94 +};
95 +#endif /* _IPT_CONNLIMIT_H */
96 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_conntrack.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_conntrack.h
97 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_conntrack.h    2004-03-04 06:16:55.000000000 +0000
98 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_conntrack.h        2004-03-07 08:43:29.000000000 +0000
99 @@ -10,6 +10,7 @@
100  
101  #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
102  #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
103 +#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
104  
105  /* flags, invflags: */
106  #define IPT_CONNTRACK_STATE    0x01
107 diff -Nur --exclude '*.orig' 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
108 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_dstlimit.h     1970-01-01 00:00:00.000000000 +0000
109 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-03-07 08:43:19.000000000 +0000
110 @@ -0,0 +1,39 @@
111 +#ifndef _IPT_DSTLIMIT_H
112 +#define _IPT_DSTLIMIT_H
113 +
114 +/* timings are in milliseconds. */
115 +#define IPT_DSTLIMIT_SCALE 10000
116 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
117 +   seconds, or one every 59 hours. */
118 +
119 +/* details of this structure hidden by the implementation */
120 +struct ipt_dstlimit_htable;
121 +
122 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
123 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
124 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
125 +
126 +struct dstlimit_cfg {
127 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
128 +       u_int32_t avg;    /* Average secs between packets * scale */
129 +       u_int32_t burst;  /* Period multiplier for upper limit. */
130 +
131 +       /* user specified */
132 +       u_int32_t size;         /* how many buckets */
133 +       u_int32_t max;          /* max number of entries */
134 +       u_int32_t gc_interval;  /* gc interval */
135 +       u_int32_t expire;       /* when do entries expire? */
136 +};
137 +
138 +struct ipt_dstlimit_info {
139 +       char name [IFNAMSIZ];           /* name */
140 +       struct dstlimit_cfg cfg;
141 +       struct ipt_dstlimit_htable *hinfo;
142 +
143 +       /* Used internally by the kernel */
144 +       union {
145 +               void *ptr;
146 +               struct ipt_dstlimit_info *master;
147 +       } u;
148 +};
149 +#endif /*_IPT_DSTLIMIT_H*/
150 diff -Nur --exclude '*.orig' 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
151 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_fuzzy.h        1970-01-01 00:00:00.000000000 +0000
152 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_fuzzy.h    2004-03-07 08:43:19.000000000 +0000
153 @@ -0,0 +1,21 @@
154 +#ifndef _IPT_FUZZY_H
155 +#define _IPT_FUZZY_H
156 +
157 +#include <linux/param.h>
158 +#include <linux/types.h>
159 +
160 +#define MAXFUZZYRATE 10000000
161 +#define MINFUZZYRATE 3
162 +
163 +struct ipt_fuzzy_info {
164 +       u_int32_t minimum_rate;
165 +       u_int32_t maximum_rate;
166 +       u_int32_t packets_total;
167 +       u_int32_t bytes_total;
168 +       u_int32_t previous_time;
169 +       u_int32_t present_time;
170 +       u_int32_t mean_rate;
171 +       u_int8_t acceptance_rate;
172 +};
173 +
174 +#endif /*_IPT_FUZZY_H*/
175 diff -Nur --exclude '*.orig' 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
176 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_ipv4options.h  1970-01-01 00:00:00.000000000 +0000
177 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_ipv4options.h      2004-03-07 08:43:20.000000000 +0000
178 @@ -0,0 +1,21 @@
179 +#ifndef __ipt_ipv4options_h_included__
180 +#define __ipt_ipv4options_h_included__
181 +
182 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
183 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
184 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
185 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
186 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
187 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
188 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
189 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
190 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
191 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
192 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
193 +
194 +struct ipt_ipv4options_info {
195 +       u_int16_t options;
196 +};
197 +
198 +
199 +#endif /* __ipt_ipv4options_h_included__ */
200 diff -Nur --exclude '*.orig' 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
201 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_mport.h        1970-01-01 00:00:00.000000000 +0000
202 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_mport.h    2004-03-07 08:43:23.000000000 +0000
203 @@ -0,0 +1,24 @@
204 +#ifndef _IPT_MPORT_H
205 +#define _IPT_MPORT_H
206 +#include <linux/netfilter_ipv4/ip_tables.h>
207 +
208 +#define IPT_MPORT_SOURCE (1<<0)
209 +#define IPT_MPORT_DESTINATION (1<<1)
210 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
211 +
212 +#define IPT_MULTI_PORTS        15
213 +
214 +/* Must fit inside union ipt_matchinfo: 32 bytes */
215 +/* every entry in ports[] except for the last one has one bit in pflags
216 + * associated with it. If this bit is set, the port is the first port of
217 + * a portrange, with the next entry being the last.
218 + * End of list is marked with pflags bit set and port=65535.
219 + * If 14 ports are used (last one does not have a pflag), the last port
220 + * is repeated to fill the last entry in ports[] */
221 +struct ipt_mport
222 +{
223 +       u_int8_t flags:2;                       /* Type of comparison */
224 +       u_int16_t pflags:14;                    /* Port flags */
225 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
226 +};
227 +#endif /*_IPT_MPORT_H*/
228 diff -Nur --exclude '*.orig' 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
229 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_nth.h  1970-01-01 00:00:00.000000000 +0000
230 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_nth.h      2004-03-07 08:43:24.000000000 +0000
231 @@ -0,0 +1,19 @@
232 +#ifndef _IPT_NTH_H
233 +#define _IPT_NTH_H
234 +
235 +#include <linux/param.h>
236 +#include <linux/types.h>
237 +
238 +#ifndef IPT_NTH_NUM_COUNTERS
239 +#define IPT_NTH_NUM_COUNTERS 16
240 +#endif
241 +
242 +struct ipt_nth_info {
243 +       u_int8_t every;
244 +       u_int8_t not;
245 +       u_int8_t startat;
246 +       u_int8_t counter;
247 +       u_int8_t packet;
248 +};
249 +
250 +#endif /*_IPT_NTH_H*/
251 diff -Nur --exclude '*.orig' 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
252 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_quota.h        1970-01-01 00:00:00.000000000 +0000
253 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_quota.h    2004-03-07 08:43:28.000000000 +0000
254 @@ -0,0 +1,11 @@
255 +#ifndef _IPT_QUOTA_H
256 +#define _IPT_QUOTA_H
257 +
258 +/* print debug info in both kernel/netfilter module & iptable library */
259 +//#define DEBUG_IPT_QUOTA
260 +
261 +struct ipt_quota_info {
262 +        u_int64_t quota;
263 +};
264 +
265 +#endif /*_IPT_QUOTA_H*/
266 diff -Nur --exclude '*.orig' 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
267 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_realm.h        1970-01-01 00:00:00.000000000 +0000
268 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_realm.h    2004-03-07 08:43:30.000000000 +0000
269 @@ -0,0 +1,9 @@
270 +#ifndef _IPT_REALM_H
271 +#define _IPT_REALM_H
272 +
273 +struct ipt_realm_info {
274 +       u_int32_t id;
275 +       u_int32_t mask;
276 +       u_int8_t invert;
277 +};
278 +#endif /*_IPT_REALM_H*/
279 diff -Nur --exclude '*.orig' 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
280 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 00:00:00.000000000 +0000
281 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_sctp.h     2004-03-07 08:43:31.000000000 +0000
282 @@ -0,0 +1,107 @@
283 +#ifndef _IPT_SCTP_H_
284 +#define _IPT_SCTP_H_
285 +
286 +#define IPT_SCTP_SRC_PORTS             0x01
287 +#define IPT_SCTP_DEST_PORTS            0x02
288 +#define IPT_SCTP_CHUNK_TYPES           0x04
289 +
290 +#define IPT_SCTP_VALID_FLAGS           0x07
291 +
292 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
293 +
294 +
295 +struct ipt_sctp_flag_info {
296 +       u_int8_t chunktype;
297 +       u_int8_t flag;
298 +       u_int8_t flag_mask;
299 +};
300 +
301 +#define IPT_NUM_SCTP_FLAGS     4
302 +
303 +struct ipt_sctp_info {
304 +       u_int16_t dpts[2];  /* Min, Max */
305 +       u_int16_t spts[2];  /* Min, Max */
306 +
307 +       u_int32_t chunkmap[256 / sizeof (u_int32_t)];  /* Bit mask of chunks to be matched according to RFC 2960 */
308 +
309 +#define SCTP_CHUNK_MATCH_ANY   0x01  /* Match if any of the chunk types are present */
310 +#define SCTP_CHUNK_MATCH_ALL   0x02  /* Match if all of the chunk types are present */
311 +#define SCTP_CHUNK_MATCH_ONLY  0x04  /* Match if these are the only chunk types present */
312 +
313 +       u_int32_t chunk_match_type;
314 +       struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
315 +       int flag_count;
316 +
317 +       u_int32_t flags;
318 +       u_int32_t invflags;
319 +};
320 +
321 +#define bytes(type) (sizeof(type) * 8)
322 +
323 +#define SCTP_CHUNKMAP_SET(chunkmap, type)              \
324 +       do {                                            \
325 +               chunkmap[type / bytes(u_int32_t)] |=    \
326 +                       1 << (type % bytes(u_int32_t)); \
327 +       } while (0)
328 +
329 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type)                    \
330 +       do {                                                    \
331 +               chunkmap[type / bytes(u_int32_t)] &=            \
332 +                       ~(1 << (type % bytes(u_int32_t)));      \
333 +       } while (0)
334 +
335 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type)                   \
336 +({                                                             \
337 +       (chunkmap[type / bytes (u_int32_t)] &                   \
338 +               (1 << (type % bytes (u_int32_t)))) ? 1: 0;      \
339 +})
340 +
341 +#define SCTP_CHUNKMAP_RESET(chunkmap)                          \
342 +       do {                                                    \
343 +               int i;                                          \
344 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
345 +                       chunkmap[i] = 0;                        \
346 +       } while (0)
347 +
348 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap)                        \
349 +       do {                                                    \
350 +               int i;                                          \
351 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
352 +                       chunkmap[i] = ~0;                       \
353 +       } while (0)
354 +
355 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap)                    \
356 +       do {                                                    \
357 +               int i;                                          \
358 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
359 +                       destmap[i] = srcmap[i];                 \
360 +       } while (0)
361 +
362 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap)               \
363 +({                                                     \
364 +       int i;                                          \
365 +       int flag = 1;                                   \
366 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
367 +               if (chunkmap[i]) {                      \
368 +                       flag = 0;                       \
369 +                       break;                          \
370 +               }                                       \
371 +       }                                               \
372 +        flag;                                          \
373 +})
374 +
375 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)             \
376 +({                                                     \
377 +       int i;                                          \
378 +       int flag = 1;                                   \
379 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
380 +               if (chunkmap[i] != ~0) {                \
381 +                       flag = 0;                       \
382 +                               break;                  \
383 +               }                                       \
384 +       }                                               \
385 +        flag;                                          \
386 +})
387 +
388 +#endif /* _IPT_SCTP_H_ */
389 +
390 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_state.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_state.h
391 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_state.h        2004-03-04 06:17:00.000000000 +0000
392 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_state.h    2004-03-07 08:43:29.000000000 +0000
393 @@ -4,6 +4,8 @@
394  #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
395  #define IPT_STATE_INVALID (1 << 0)
396  
397 +#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
398 +
399  struct ipt_state_info
400  {
401         unsigned int statemask;
402 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_u32.h
403 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4/ipt_u32.h  1970-01-01 00:00:00.000000000 +0000
404 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4/ipt_u32.h      2004-03-07 08:44:17.000000000 +0000
405 @@ -0,0 +1,40 @@
406 +#ifndef _IPT_U32_H
407 +#define _IPT_U32_H
408 +#include <linux/netfilter_ipv4/ip_tables.h>
409 +
410 +enum ipt_u32_ops
411 +{
412 +       IPT_U32_AND,
413 +       IPT_U32_LEFTSH,
414 +       IPT_U32_RIGHTSH,
415 +       IPT_U32_AT
416 +};
417 +
418 +struct ipt_u32_location_element
419 +{
420 +       u_int32_t number;
421 +       u_int8_t nextop;
422 +};
423 +struct ipt_u32_value_element
424 +{
425 +       u_int32_t min;
426 +       u_int32_t max;
427 +};
428 +/* *** any way to allow for an arbitrary number of elements?
429 +   for now I settle for a limit of 10 of each */
430 +#define U32MAXSIZE 10
431 +struct ipt_u32_test
432 +{
433 +       u_int8_t nnums;
434 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
435 +       u_int8_t nvalues;
436 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
437 +};
438 +
439 +struct ipt_u32
440 +{
441 +       u_int8_t ntests;
442 +       struct ipt_u32_test tests[U32MAXSIZE+1];
443 +};
444 +
445 +#endif /*_IPT_U32_H*/
446 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/include/linux/netfilter_ipv4.h linux-2.6.4-rc2/include/linux/netfilter_ipv4.h
447 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv4.h  2004-03-04 06:16:58.000000000 +0000
448 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv4.h      2004-03-07 08:43:29.000000000 +0000
449 @@ -51,6 +51,8 @@
450  
451  enum nf_ip_hook_priorities {
452         NF_IP_PRI_FIRST = INT_MIN,
453 +       NF_IP_PRI_CONNTRACK_DEFRAG = -400,
454 +       NF_IP_PRI_RAW = -300,
455         NF_IP_PRI_SELINUX_FIRST = -225,
456         NF_IP_PRI_CONNTRACK = -200,
457         NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
458 diff -Nur --exclude '*.orig' 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
459 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_HL.h  1970-01-01 00:00:00.000000000 +0000
460 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_HL.h      2004-03-07 08:43:13.000000000 +0000
461 @@ -0,0 +1,22 @@
462 +/* Hop Limit modification module for ip6tables
463 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
464 + * Based on HW's TTL module */
465 +
466 +#ifndef _IP6T_HL_H
467 +#define _IP6T_HL_H
468 +
469 +enum {
470 +       IP6T_HL_SET = 0,
471 +       IP6T_HL_INC,
472 +       IP6T_HL_DEC
473 +};
474 +
475 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
476 +
477 +struct ip6t_HL_info {
478 +       u_int8_t        mode;
479 +       u_int8_t        hop_limit;
480 +};
481 +
482 +
483 +#endif
484 diff -Nur --exclude '*.orig' 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
485 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_REJECT.h      2004-03-04 06:16:34.000000000 +0000
486 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_REJECT.h  2004-03-07 08:43:15.000000000 +0000
487 @@ -2,15 +2,17 @@
488  #define _IP6T_REJECT_H
489  
490  enum ip6t_reject_with {
491 -       IP6T_ICMP_NET_UNREACHABLE,
492 -       IP6T_ICMP_HOST_UNREACHABLE,
493 -       IP6T_ICMP_PROT_UNREACHABLE,
494 -       IP6T_ICMP_PORT_UNREACHABLE,
495 -       IP6T_ICMP_ECHOREPLY
496 +       IP6T_ICMP6_NO_ROUTE,
497 +       IP6T_ICMP6_ADM_PROHIBITED,
498 +       IP6T_ICMP6_NOT_NEIGHBOUR,
499 +       IP6T_ICMP6_ADDR_UNREACH,
500 +       IP6T_ICMP6_PORT_UNREACH,
501 +       IP6T_ICMP6_ECHOREPLY,
502 +       IP6T_TCP_RESET
503  };
504  
505  struct ip6t_reject_info {
506         enum ip6t_reject_with with;      /* reject type */
507  };
508  
509 -#endif /*_IPT_REJECT_H*/
510 +#endif /*_IP6T_REJECT_H*/
511 diff -Nur --exclude '*.orig' 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
512 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h       1970-01-01 00:00:00.000000000 +0000
513 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_fuzzy.h   2004-03-07 08:43:19.000000000 +0000
514 @@ -0,0 +1,21 @@
515 +#ifndef _IP6T_FUZZY_H
516 +#define _IP6T_FUZZY_H
517 +
518 +#include <linux/param.h>
519 +#include <linux/types.h>
520 +
521 +#define MAXFUZZYRATE 10000000
522 +#define MINFUZZYRATE 3
523 +
524 +struct ip6t_fuzzy_info {
525 +       u_int32_t minimum_rate;
526 +       u_int32_t maximum_rate;
527 +       u_int32_t packets_total;
528 +       u_int32_t bytes_total;
529 +       u_int32_t previous_time;
530 +       u_int32_t present_time;
531 +       u_int32_t mean_rate;
532 +       u_int8_t acceptance_rate;
533 +};
534 +
535 +#endif /*_IP6T_FUZZY_H*/
536 diff -Nur --exclude '*.orig' 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
537 --- linux-2.6.4-rc2.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 00:00:00.000000000 +0000
538 +++ linux-2.6.4-rc2/include/linux/netfilter_ipv6/ip6t_nth.h     2004-03-07 08:43:24.000000000 +0000
539 @@ -0,0 +1,19 @@
540 +#ifndef _IP6T_NTH_H
541 +#define _IP6T_NTH_H
542 +
543 +#include <linux/param.h>
544 +#include <linux/types.h>
545 +
546 +#ifndef IP6T_NTH_NUM_COUNTERS
547 +#define IP6T_NTH_NUM_COUNTERS 16
548 +#endif
549 +
550 +struct ip6t_nth_info {
551 +       u_int8_t every;
552 +       u_int8_t not;
553 +       u_int8_t startat;
554 +       u_int8_t counter;
555 +       u_int8_t packet;
556 +};
557 +
558 +#endif /*_IP6T_NTH_H*/
559 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/core/netfilter.c linux-2.6.4-rc2/net/core/netfilter.c
560 --- linux-2.6.4-rc2.org/net/core/netfilter.c    2004-03-04 06:16:45.000000000 +0000
561 +++ linux-2.6.4-rc2/net/core/netfilter.c        2004-03-07 08:43:12.000000000 +0000
562 @@ -8,8 +8,10 @@
563   *
564   * February 2000: Modified by James Morris to have 1 queue per protocol.
565   * 15-Mar-2000:   Added NF_REPEAT --RR.
566 + * 08-May-2003:          Internal logging interface added by Jozsef Kadlecsik.
567   */
568  #include <linux/config.h>
569 +#include <linux/kernel.h>
570  #include <linux/netfilter.h>
571  #include <net/protocol.h>
572  #include <linux/init.h>
573 @@ -58,6 +60,10 @@
574  } queue_handler[NPROTO];
575  static rwlock_t queue_handler_lock = RW_LOCK_UNLOCKED;
576  
577 +/**
578 + * nf_register_hook - Register with a netfilter hook
579 + * @reg: Hook operations to be registered
580 + */
581  int nf_register_hook(struct nf_hook_ops *reg)
582  {
583         struct list_head *i;
584 @@ -74,6 +80,10 @@
585         return 0;
586  }
587  
588 +/**
589 + * nf_unregister_hook - Unregister from a netfilter hook
590 + * @reg: hook operations to be unregistered
591 + */
592  void nf_unregister_hook(struct nf_hook_ops *reg)
593  {
594         spin_lock_bh(&nf_hook_lock);
595 @@ -386,6 +396,18 @@
596         return NF_ACCEPT;
597  }
598  
599 +/**
600 + * nf_register_queue_handler - Registere a queue handler with netfilter
601 + * @pf: protocol family
602 + * @outfn: function called by core to enqueue a packet
603 + * @data: opaque parameter, passed through
604 + *
605 + * This function registers a queue handler with netfilter.  There can only
606 + * be one queue handler for every protocol family.
607 + *
608 + * A queue handler _must_ reinject every packet via nf_reinject, no
609 + * matter what.
610 + */
611  int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
612  {      
613         int ret;
614 @@ -403,7 +425,12 @@
615         return ret;
616  }
617  
618 -/* The caller must flush their queue before this */
619 +/**
620 + * nf_unregister_queue_handler - Unregister queue handler from netfilter
621 + * @pf: protocol family
622 + *
623 + * The caller must flush their queue before unregistering
624 + */
625  int nf_unregister_queue_handler(int pf)
626  {
627         write_lock_bh(&queue_handler_lock);
628 @@ -546,6 +573,15 @@
629         return ret;
630  }
631  
632 +/**
633 + * nf_reinject - Reinject a packet from a queue handler
634 + * @skb: the packet to be reinjected
635 + * @info: info which was passed to the outfn() of the queue handler
636 + * @verdict: verdict (NF_ACCEPT, ...) for this packet
637 + *
638 + * This is the function called by a queue handler to reinject a
639 + * packet.
640 + */
641  void nf_reinject(struct sk_buff *skb, struct nf_info *info,
642                  unsigned int verdict)
643  {
644 @@ -740,6 +776,72 @@
645  EXPORT_SYMBOL(skb_ip_make_writable);
646  #endif /*CONFIG_INET*/
647  
648 +/* Internal logging interface, which relies on the real 
649 +   LOG target modules */
650 +
651 +#define NF_LOG_PREFIXLEN               128
652 +
653 +static nf_logfn *nf_logging[NPROTO]; /* = NULL */
654 +static int reported = 0;
655 +static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;
656 +
657 +int nf_log_register(int pf, nf_logfn *logfn)
658 +{
659 +       int ret = -EBUSY;
660 +
661 +       /* Any setup of logging members must be done before
662 +        * substituting pointer. */
663 +       smp_wmb();
664 +       spin_lock(&nf_log_lock);
665 +       if (!nf_logging[pf]) {
666 +               nf_logging[pf] = logfn;
667 +               ret = 0;
668 +       }
669 +       spin_unlock(&nf_log_lock);
670 +       return ret;
671 +}              
672 +
673 +void nf_log_unregister(int pf, nf_logfn *logfn)
674 +{
675 +       spin_lock(&nf_log_lock);
676 +       if (nf_logging[pf] == logfn)
677 +               nf_logging[pf] = NULL;
678 +       spin_unlock(&nf_log_lock);
679 +
680 +       /* Give time to concurrent readers. */
681 +       synchronize_net();
682 +}              
683 +
684 +void nf_log_packet(int pf,
685 +                  unsigned int hooknum,
686 +                  const struct sk_buff *skb,
687 +                  const struct net_device *in,
688 +                  const struct net_device *out,
689 +                  const char *fmt, ...)
690 +{
691 +       va_list args;
692 +       char prefix[NF_LOG_PREFIXLEN];
693 +       nf_logfn *logfn;
694 +       
695 +       rcu_read_lock();
696 +       logfn = nf_logging[pf];
697 +       if (logfn) {
698 +               va_start(args, fmt);
699 +               vsnprintf(prefix, sizeof(prefix), fmt, args);
700 +               va_end(args);
701 +               /* We must read logging before nf_logfn[pf] */
702 +               smp_read_barrier_depends();
703 +               logfn(hooknum, skb, in, out, prefix);
704 +       } else if (!reported) {
705 +               printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
706 +                      "no backend logging module loaded in!\n");
707 +               reported++;
708 +       }
709 +       rcu_read_unlock();
710 +}
711 +EXPORT_SYMBOL(nf_log_register);
712 +EXPORT_SYMBOL(nf_log_unregister);
713 +EXPORT_SYMBOL(nf_log_packet);
714  
715  /* This does not belong here, but ipt_REJECT needs it if connection
716     tracking in use: without this, connection may not be in hash table,
717 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/Kconfig linux-2.6.4-rc2/net/ipv4/netfilter/Kconfig
718 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/Kconfig      2004-03-04 06:16:58.000000000 +0000
719 +++ linux-2.6.4-rc2/net/ipv4/netfilter/Kconfig  2004-03-07 08:44:17.000000000 +0000
720 @@ -579,5 +579,89 @@
721  
722           To compile it as a module, choose M here.  If unsure, say N.
723  
724 +config IP_NF_TARGET_IPV4OPTSSTRIP
725 +       tristate  'IPV4OPTSSTRIP target support'
726 +       depends on IP_NF_MANGLE
727 +         help
728 +
729 +config IP_NF_TARGET_TTL
730 +       tristate  'TTL target support'
731 +       depends on IP_NF_MANGLE
732 +         help
733 +
734 +config IP_NF_MATCH_CONNLIMIT
735 +       tristate  'Connections/IP limit match support'
736 +       depends on IP_NF_IPTABLES
737 +         help
738 +
739 +config IP_NF_MATCH_DSTLIMIT
740 +       tristate  'dstlimit match support'
741 +       depends on IP_NF_IPTABLES
742 +         help
743 +
744 +config IP_NF_MATCH_FUZZY
745 +       tristate  'fuzzy match support'
746 +       depends on IP_NF_IPTABLES
747 +         help
748 +
749 +config IP_NF_MATCH_IPV4OPTIONS
750 +       tristate  'IPV4OPTIONS match support'
751 +       depends on IP_NF_IPTABLES
752 +         help
753 +
754 +config IP_NF_MATCH_MPORT
755 +       tristate  'Multiple port with ranges match support'
756 +       depends on IP_NF_IPTABLES
757 +         help
758 +
759 +config IP_NF_MATCH_NTH
760 +       tristate  'Nth match support'
761 +       depends on IP_NF_IPTABLES
762 +         help
763 +
764 +config IP_NF_MATCH_QUOTA
765 +       tristate  'quota match support'
766 +       depends on IP_NF_IPTABLES
767 +         help
768 +
769 +config IP_NF_TARGET_NOTRACK
770 +       tristate  'NOTRACK target support'
771 +       depends on IP_NF_RAW
772 +       help
773 +         The NOTRACK target allows a select rule to specify
774 +         which packets *not* to enter the conntrack/NAT
775 +         subsystem with all the consequences (no ICMP error tracking,
776 +         no protocol helpers for the selected packets).
777 +       
778 +         If you want to compile it as a module, say M here and read
779 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
780 +
781 +config IP_NF_RAW
782 +       tristate  'raw table support (required for NOTRACK/TRACE)'
783 +       depends on IP_NF_IPTABLES
784 +       help
785 +         This option adds a `raw' table to iptables. This table is the very
786 +         first in the netfilter framework and hooks in at the PREROUTING
787 +         and OUTPUT chains.
788 +       
789 +         If you want to compile it as a module, say M here and read
790 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
791 +         help
792 +
793 +config IP_NF_MATCH_REALM
794 +       tristate  'realm match support'
795 +       depends on IP_NF_IPTABLES && NET_CLS_ROUTE
796 +         help
797 +
798 +config IP_NF_MATCH_SCTP
799 +       tristate  'SCTP protocol match support'
800 +       depends on IP_NF_IPTABLES
801 +         help
802 +
803 +config IP_NF_MATCH_U32
804 +       tristate  'U32 match support'
805 +       depends on IP_NF_IPTABLES
806 +         help
807 +
808  endmenu
809  
810 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/Makefile linux-2.6.4-rc2/net/ipv4/netfilter/Makefile
811 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/Makefile     2004-03-04 06:16:38.000000000 +0000
812 +++ linux-2.6.4-rc2/net/ipv4/netfilter/Makefile 2004-03-07 08:44:17.000000000 +0000
813 @@ -38,19 +38,33 @@
814  obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
815  obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
816  obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
817 +obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
818  
819  # matches
820  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
821  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
822 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
823 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
824 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
825  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
826  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
827  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
828  
829  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
830  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
831 +
832 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
833 +
834  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
835  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
836  
837 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
838 +
839 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
840 +
841 +
842 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
843 +
844  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
845  
846  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
847 @@ -59,10 +73,15 @@
848  
849  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
850  
851 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
852 +
853 +
854  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
855  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
856 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
857  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
858  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
859 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
860  
861  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
862  
863 @@ -79,8 +98,11 @@
864  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
865  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
866  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
867 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
868 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
869  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
870  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
871 +obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
872  
873  # generic ARP tables
874  obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
875 diff -Nur --exclude '*.orig' 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
876 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_core.c  2004-03-04 06:16:34.000000000 +0000
877 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_core.c      2004-03-07 08:43:29.000000000 +0000
878 @@ -15,6 +15,8 @@
879   * 16 Jul 2002: Harald Welte <laforge@gnumonks.org>
880   *     - add usage/reference counts to ip_conntrack_expect
881   *     - export ip_conntrack[_expect]_{find_get,put} functions
882 + * 05 Aug 2002: Harald Welte <laforge@gnumonks.org>
883 + *     - added DocBook-style comments for public API
884   * */
885  
886  #include <linux/config.h>
887 @@ -67,6 +69,7 @@
888  static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
889  struct list_head *ip_conntrack_hash;
890  static kmem_cache_t *ip_conntrack_cachep;
891 +struct ip_conntrack ip_conntrack_untracked;
892  
893  extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
894  
895 @@ -89,6 +92,10 @@
896         return p;
897  }
898  
899 +/**
900 + * ip_ct_find_proto - Find layer 4 protocol helper for given protocol number
901 + * @protocol: protocol number
902 + */
903  struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
904  {
905         struct ip_conntrack_protocol *p;
906 @@ -112,6 +119,11 @@
907  static int ip_conntrack_hash_rnd_initted;
908  static unsigned int ip_conntrack_hash_rnd;
909  
910 +/**
911 + * hash_conntrack - Calculate the position of an entry in the connection 
912 + * tracking table.
913 + * @tuple: conntrack tuple which we want to calculate the hash position
914 + */
915  static u_int32_t
916  hash_conntrack(const struct ip_conntrack_tuple *tuple)
917  {
918 @@ -124,6 +136,19 @@
919                              ip_conntrack_hash_rnd) % ip_conntrack_htable_size);
920  }
921  
922 +/**
923 + * get_tuple - set all the fields of a tuple which is passed as parameter
924 + * given a network buffer.
925 + * @iph:pointer an IP header. 
926 + * @skb:network buffer for which we want to generate the tuple
927 + * @dataoff: FIXME: Deprecated?
928 + * @tuple: tuple which will be generate. Used as return parameter.
929 + * @protocol: structure which contains pointer to protocol specific functions.
930 + *
931 + * Note: This function doesn't allocate space for the tuple passed as 
932 + * parameter. The function pkt_to_packet which set all the protocol specific
933 + * fields of a given tuple.
934 + */
935  int
936  get_tuple(const struct iphdr *iph,
937           const struct sk_buff *skb,
938 @@ -145,6 +170,15 @@
939         return protocol->pkt_to_tuple(skb, dataoff, tuple);
940  }
941  
942 +/**
943 + * invert_tuple - Returns the inverse of a given tuple. It is used to 
944 + * calculate the tuple which represents the other sense of the flow
945 + * of a connection.
946 + * @inverse: the inverted tuple. Use as return value.
947 + * @orig: the original tuple which will be inverted.
948 + * @protocol: a pointer to the protocol structure which contains all the
949 + * specifical functions available for this tuple.
950 + */
951  static int
952  invert_tuple(struct ip_conntrack_tuple *inverse,
953              const struct ip_conntrack_tuple *orig,
954 @@ -160,7 +194,15 @@
955  
956  /* ip_conntrack_expect helper functions */
957  
958 -/* Compare tuple parts depending on mask. */
959 +/**
960 + * expect_cmp - compare a tuple with a expectation depending on a mask
961 + * @i: pointer to an expectation.
962 + * @tuple: tuple which will be compared with the expectation tuple.
963 + *
964 + * Actually the tuple field of an expectation is compared with a tuple
965 + * This function is used by LIST_FIND to find a expectation which match a te
966 + * given tuple.
967 + */
968  static inline int expect_cmp(const struct ip_conntrack_expect *i,
969                              const struct ip_conntrack_tuple *tuple)
970  {
971 @@ -168,6 +210,10 @@
972         return ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask);
973  }
974  
975 +/**
976 + * destroy_expect - Release all the resources allocated by an expectation.
977 + * @exp: pointer to the expectation which we want to release.
978 + */
979  static void
980  destroy_expect(struct ip_conntrack_expect *exp)
981  {
982 @@ -178,7 +224,11 @@
983         kfree(exp);
984  }
985  
986 -
987 +/**
988 + * ip_conntrack_expect_put - it decrements the counter of use related 
989 + * associated to an expectation and it calls destroy_expect.
990 + * @exp: pointer to the expectation which we want to release.
991 + */
992  inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
993  {
994         IP_NF_ASSERT(exp);
995 @@ -198,7 +248,14 @@
996                          struct ip_conntrack_expect *, tuple);
997  }
998  
999 -/* Find a expectation corresponding to a tuple. */
1000 +/**
1001 + * ip_conntrack_find_get - find conntrack according to tuple
1002 + * @tuple: conntrack tuple for which we search conntrack
1003 + * @ignored_conntrack: ignore this conntrack during search
1004 + *
1005 + * This function increments the reference count of the found
1006 + * conntrack (if any).
1007 + */
1008  struct ip_conntrack_expect *
1009  ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
1010  {
1011 @@ -381,7 +438,14 @@
1012         return h;
1013  }
1014  
1015 -/* Find a connection corresponding to a tuple. */
1016 +/**
1017 + * ip_conntrack_find_get - find conntrack according to tuple
1018 + * @tuple: conntrack tuple for which we search conntrack
1019 + * @ignored_conntrack: ignore this conntrack during search
1020 + *
1021 + * This function increments the reference count of the found
1022 + * conntrack (if any).
1023 + */
1024  struct ip_conntrack_tuple_hash *
1025  ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
1026                       const struct ip_conntrack *ignored_conntrack)
1027 @@ -409,7 +473,14 @@
1028         return ct;
1029  }
1030  
1031 -/* Return conntrack and conntrack_info given skb->nfct->master */
1032 +/**
1033 + * ip_conntrack_get - Return conntrack and conntrack_info for given skb
1034 + * @skb: skb for which we want to find conntrack and conntrack_info
1035 + * @ctinfo: pointer to ctinfo, used as return value
1036 + *
1037 + * This function resolves the respective conntrack and conntrack_info
1038 + * structures for the connection this packet (skb) is part of.
1039 + */
1040  struct ip_conntrack *
1041  ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
1042  {
1043 @@ -479,8 +550,14 @@
1044         return NF_DROP;
1045  }
1046  
1047 -/* Returns true if a connection correspondings to the tuple (required
1048 -   for NAT). */
1049 +/**
1050 + * ip_conntrack_tuple_taken - Find out if tuple is already in use
1051 + * @tuple: tuple to be used for this test
1052 + * @ignored_conntrack: conntrack which is excluded from result
1053 + *
1054 + * This function is called by the NAT code in order to find out if
1055 + * a particular tuple is already in use by some connection.
1056 + */
1057  int
1058  ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
1059                          const struct ip_conntrack *ignored_conntrack)
1060 @@ -606,7 +683,13 @@
1061  {
1062         return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
1063  }
1064 -
1065 +/**
1066 + * ip_ct_find_helper - Find application helper according to tuple
1067 + * @tuple: tuple for which helper needs to be found
1068 + *
1069 + * This function is used to determine if any registered conntrack helper
1070 + * is to be used for the given tuple.
1071 + */
1072  struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
1073  {
1074         return LIST_FIND(&helpers, helper_cmp,
1075 @@ -691,42 +774,50 @@
1076                              struct ip_conntrack_expect *, tuple);
1077         READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
1078  
1079 -       /* If master is not in hash table yet (ie. packet hasn't left
1080 -          this machine yet), how can other end know about expected?
1081 -          Hence these are not the droids you are looking for (if
1082 -          master ct never got confirmed, we'd hold a reference to it
1083 -          and weird things would happen to future packets). */
1084 -       if (expected && !is_confirmed(expected->expectant))
1085 -               expected = NULL;
1086 -
1087 -       /* Look up the conntrack helper for master connections only */
1088 -       if (!expected)
1089 -               conntrack->helper = ip_ct_find_helper(&repl_tuple);
1090 -
1091 -       /* If the expectation is dying, then this is a loser. */
1092 -       if (expected
1093 -           && expected->expectant->helper->timeout
1094 -           && ! del_timer(&expected->timeout))
1095 -               expected = NULL;
1096 -
1097         if (expected) {
1098 -               DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
1099 -                       conntrack, expected);
1100 -               /* Welcome, Mr. Bond.  We've been expecting you... */
1101 -               IP_NF_ASSERT(master_ct(conntrack));
1102 -               __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1103 -               conntrack->master = expected;
1104 -               expected->sibling = conntrack;
1105 -               LIST_DELETE(&ip_conntrack_expect_list, expected);
1106 -               expected->expectant->expecting--;
1107 -               nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1108 -       }
1109 -       atomic_inc(&ip_conntrack_count);
1110 +               /* If master is not in hash table yet (ie. packet hasn't left
1111 +                  this machine yet), how can other end know about expected?
1112 +                  Hence these are not the droids you are looking for (if
1113 +                  master ct never got confirmed, we'd hold a reference to it
1114 +                  and weird things would happen to future packets). */
1115 +               if (!is_confirmed(expected->expectant)) {
1116 +                       
1117 +                       conntrack->helper = ip_ct_find_helper(&repl_tuple);
1118 +                       goto end;
1119 +               }
1120 +
1121 +               /* Expectation is dying... */
1122 +               if (expected->expectant->helper->timeout
1123 +                   && ! del_timer(&expected->timeout)) {
1124 +                       goto end;       
1125 +               }
1126 +
1127 +                DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
1128 +                       conntrack, expected);
1129 +                /* Welcome, Mr. Bond.  We've been expecting you... */
1130 +                IP_NF_ASSERT(master_ct(conntrack));
1131 +                __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1132 +                conntrack->master = expected;
1133 +                expected->sibling = conntrack;
1134 +                LIST_DELETE(&ip_conntrack_expect_list, expected);
1135 +                expected->expectant->expecting--;
1136 +                nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1137 +
1138 +               /* this is a braindead... --pablo */
1139 +               atomic_inc(&ip_conntrack_count);
1140 +               WRITE_UNLOCK(&ip_conntrack_lock);
1141 +
1142 +               if (expected->expectfn)
1143 +                       expected->expectfn(conntrack);
1144 +
1145 +               goto ret;
1146 +        } else 
1147 +                conntrack->helper = ip_ct_find_helper(&repl_tuple);
1148 +
1149 +end:   atomic_inc(&ip_conntrack_count);
1150         WRITE_UNLOCK(&ip_conntrack_lock);
1151  
1152 -       if (expected && expected->expectfn)
1153 -               expected->expectfn(conntrack);
1154 -       return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
1155 +ret:   return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
1156  }
1157  
1158  /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
1159 @@ -794,6 +885,15 @@
1160         int set_reply;
1161         int ret;
1162  
1163 +       /* Never happen */
1164 +       if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
1165 +               if (net_ratelimit()) {
1166 +               printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n",
1167 +                      (*pskb)->nh.iph->protocol, hooknum);
1168 +               }
1169 +               return NF_DROP;
1170 +       }
1171 +
1172         /* FIXME: Do this right please. --RR */
1173         (*pskb)->nfcache |= NFC_UNKNOWN;
1174  
1175 @@ -812,18 +912,10 @@
1176         }
1177  #endif
1178  
1179 -       /* Previously seen (loopback)?  Ignore.  Do this before
1180 -           fragment check. */
1181 +       /* Previously seen (loopback or untracked)?  Ignore. */
1182         if ((*pskb)->nfct)
1183                 return NF_ACCEPT;
1184  
1185 -       /* Gather fragments. */
1186 -       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
1187 -               *pskb = ip_ct_gather_frags(*pskb);
1188 -               if (!*pskb)
1189 -                       return NF_STOLEN;
1190 -       }
1191 -
1192         proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
1193  
1194         /* It may be an icmp error... */
1195 @@ -900,6 +992,14 @@
1196         return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
1197  }
1198  
1199 +/**
1200 + * ip_conntrack_unexpect_related - Unexpect a related connection
1201 + * @expect: expecattin to be removed
1202 + *
1203 + * This function removes an existing expectation, that has not yet been
1204 + * confirmed (i.e. expectation was issued, but expected connection didn't
1205 + * arrive yet)
1206 + */
1207  inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
1208  {
1209         WRITE_LOCK(&ip_conntrack_lock);
1210 @@ -917,7 +1017,20 @@
1211         WRITE_UNLOCK(&ip_conntrack_lock);
1212  }
1213  
1214 -/* Add a related connection. */
1215 +/**
1216 + * ip_conntrack_expect_related - Expect a related connection
1217 + * @related_to: master conntrack
1218 + * @expect: expectation with all values filled in
1219 + *
1220 + * This function is called by conntrack application helpers who
1221 + * have detected that the control (master) connection is just about
1222 + * to negotiate a related slave connection. 
1223 + *
1224 + * Note: This function allocates it's own struct ip_conntrack_expect,
1225 + * copying the values from the 'expect' parameter.  Thus, 'expect' can
1226 + * be allocated on the stack and does not need to be valid after this
1227 + * function returns.
1228 + */
1229  int ip_conntrack_expect_related(struct ip_conntrack *related_to,
1230                                 struct ip_conntrack_expect *expect)
1231  {
1232 @@ -1047,7 +1160,15 @@
1233         return ret;
1234  }
1235  
1236 -/* Change tuple in an existing expectation */
1237 +/**
1238 + * ip_conntrack_change_expect - Change tuple in existing expectation
1239 + * @expect: expectation which is to be changed
1240 + * @newtuple: new tuple for expect
1241 + *
1242 + * This function is mostly called by NAT application helpers, who want to
1243 + * change an expectation issued by their respective conntrack application
1244 + * helper counterpart.
1245 + */
1246  int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
1247                                struct ip_conntrack_tuple *newtuple)
1248  {
1249 @@ -1088,8 +1209,15 @@
1250         return ret;
1251  }
1252  
1253 -/* Alter reply tuple (maybe alter helper).  If it's already taken,
1254 -   return 0 and don't do alteration. */
1255 +/**
1256 + * ip_conntrack_alter_reply - Alter reply tuple of conntrack
1257 + * @conntrack: conntrack whose reply tuple we want to alter
1258 + * @newreply: designated reply tuple for this conntrack
1259 + *
1260 + * This function alters the reply tuple of a conntrack to the given
1261 + * newreply tuple.  If this newreply tuple is already taken, return 0
1262 + * and don't do alteration
1263 + */
1264  int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
1265                              const struct ip_conntrack_tuple *newreply)
1266  {
1267 @@ -1114,6 +1242,13 @@
1268         return 1;
1269  }
1270  
1271 +/**
1272 + * ip_conntrack_helper_register - Register a conntrack application helper
1273 + * @me: structure describing the helper
1274 + *
1275 + * This function is called by conntrack application helpers to register
1276 + * themselves with the conntrack core.
1277 + */
1278  int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
1279  {
1280         WRITE_LOCK(&ip_conntrack_lock);
1281 @@ -1135,6 +1270,13 @@
1282         return 0;
1283  }
1284  
1285 +/**
1286 + * ip_conntrack_helper_unregister - Unregister a conntrack application helper
1287 + * @me: structure describing the helper
1288 + *
1289 + * This function is called by conntrack application helpers to unregister
1290 + * themselvers from the conntrack core.
1291 + */
1292  void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
1293  {
1294         unsigned int i;
1295 @@ -1153,7 +1295,14 @@
1296         synchronize_net();
1297  }
1298  
1299 -/* Refresh conntrack for this many jiffies. */
1300 +/**
1301 + * ip_ct_refresh - Refresh conntrack timer for given conntrack
1302 + * @ct: conntrack which we want to refresh
1303 + * @extra_jiffies: number of jiffies to add
1304 + *
1305 + * This function is called by protocol helpers and application helpers in
1306 + * order to change the expiration timer of a conntrack entry.
1307 + */
1308  void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
1309  {
1310         IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
1311 @@ -1172,7 +1321,16 @@
1312         WRITE_UNLOCK(&ip_conntrack_lock);
1313  }
1314  
1315 -/* Returns new sk_buff, or NULL */
1316 +
1317 +/**
1318 + * ip_ct_gather_frags - Gather fragments of a particular skb
1319 + * @skb: pointer to sk_buff of fragmented IP packet
1320 + *
1321 + * This code is just a wrapper around the defragmentation code in the core IPv4
1322 + * stack.  It also takes care of nonlinear skb's.
1323 + *
1324 + * Returns new sk_buff, or NULL
1325 + */
1326  struct sk_buff *
1327  ip_ct_gather_frags(struct sk_buff *skb)
1328  {
1329 @@ -1256,6 +1414,16 @@
1330         return h;
1331  }
1332  
1333 +/**
1334 + * ip_ct_selective_cleanup - Selectively delete a set of conntrack entries
1335 + * @kill: callback function selecting which entries to delete
1336 + * @data: opaque data pointer, becomes 2nd argument for kill function
1337 + *
1338 + * This function can be used to selectively delete elements of the conntrack
1339 + * hashtable.  The function iterates over the list of conntrack entries and
1340 + * calls the 'kill' function for every entry.  If the return value is true,
1341 + * the connection is deleted (death_by_timeout).
1342 + */
1343  void
1344  ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
1345                         void *data)
1346 @@ -1422,6 +1590,18 @@
1347  
1348         /* For use by ipt_REJECT */
1349         ip_ct_attach = ip_conntrack_attach;
1350 +
1351 +       /* Set up fake conntrack:
1352 +           - to never be deleted, not in any hashes */
1353 +       atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
1354 +       /*  - and look it like as a confirmed connection */
1355 +       set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
1356 +       /*  - and prepare the ctinfo field for REJECT & NAT. */
1357 +       ip_conntrack_untracked.infos[IP_CT_NEW].master =
1358 +       ip_conntrack_untracked.infos[IP_CT_RELATED].master =
1359 +       ip_conntrack_untracked.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master = 
1360 +                       &ip_conntrack_untracked.ct_general;
1361 +
1362         return ret;
1363  
1364  err_free_hash:
1365 diff -Nur --exclude '*.orig' 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
1366 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-03-04 06:16:44.000000000 +0000
1367 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-03-07 08:43:29.000000000 +0000
1368 @@ -194,6 +194,26 @@
1369         return ip_conntrack_confirm(*pskb);
1370  }
1371  
1372 +static unsigned int ip_conntrack_defrag(unsigned int hooknum,
1373 +                                       struct sk_buff **pskb,
1374 +                                       const struct net_device *in,
1375 +                                       const struct net_device *out,
1376 +                                       int (*okfn)(struct sk_buff *))
1377 +{
1378 +       /* Previously seen (loopback)?  Ignore.  Do this before
1379 +           fragment check. */
1380 +       if ((*pskb)->nfct)
1381 +               return NF_ACCEPT;
1382 +
1383 +       /* Gather fragments. */
1384 +       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
1385 +               *pskb = ip_ct_gather_frags(*pskb);
1386 +               if (!*pskb)
1387 +                       return NF_STOLEN;
1388 +       }
1389 +       return NF_ACCEPT;
1390 +}
1391 +
1392  static unsigned int ip_refrag(unsigned int hooknum,
1393                               struct sk_buff **pskb,
1394                               const struct net_device *in,
1395 @@ -236,6 +256,14 @@
1396  
1397  /* Connection tracking may drop packets, but never alters them, so
1398     make it the first hook. */
1399 +static struct nf_hook_ops ip_conntrack_defrag_ops = {
1400 +       .hook           = ip_conntrack_defrag,
1401 +       .owner          = THIS_MODULE,
1402 +       .pf             = PF_INET,
1403 +       .hooknum        = NF_IP_PRE_ROUTING,
1404 +       .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
1405 +};
1406 +
1407  static struct nf_hook_ops ip_conntrack_in_ops = {
1408         .hook           = ip_conntrack_in,
1409         .owner          = THIS_MODULE,
1410 @@ -244,6 +272,14 @@
1411         .priority       = NF_IP_PRI_CONNTRACK,
1412  };
1413  
1414 +static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
1415 +       .hook           = ip_conntrack_defrag,
1416 +       .owner          = THIS_MODULE,
1417 +       .pf             = PF_INET,
1418 +       .hooknum        = NF_IP_LOCAL_OUT,
1419 +       .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
1420 +};
1421 +
1422  static struct nf_hook_ops ip_conntrack_local_out_ops = {
1423         .hook           = ip_conntrack_local,
1424         .owner          = THIS_MODULE,
1425 @@ -470,10 +506,20 @@
1426         if (!proc) goto cleanup_init;
1427         proc->owner = THIS_MODULE;
1428  
1429 +       ret = nf_register_hook(&ip_conntrack_defrag_ops);
1430 +       if (ret < 0) {
1431 +               printk("ip_conntrack: can't register pre-routing defrag hook.\n");
1432 +               goto cleanup_proc;
1433 +       }
1434 +       ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
1435 +       if (ret < 0) {
1436 +               printk("ip_conntrack: can't register local_out defrag hook.\n");
1437 +               goto cleanup_defragops;
1438 +       }
1439         ret = nf_register_hook(&ip_conntrack_in_ops);
1440         if (ret < 0) {
1441                 printk("ip_conntrack: can't register pre-routing hook.\n");
1442 -               goto cleanup_proc;
1443 +               goto cleanup_defraglocalops;
1444         }
1445         ret = nf_register_hook(&ip_conntrack_local_out_ops);
1446         if (ret < 0) {
1447 @@ -511,6 +557,10 @@
1448         nf_unregister_hook(&ip_conntrack_local_out_ops);
1449   cleanup_inops:
1450         nf_unregister_hook(&ip_conntrack_in_ops);
1451 + cleanup_defraglocalops:
1452 +       nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
1453 + cleanup_defragops:
1454 +       nf_unregister_hook(&ip_conntrack_defrag_ops);
1455   cleanup_proc:
1456         proc_net_remove("ip_conntrack");
1457   cleanup_init:
1458 @@ -519,13 +569,20 @@
1459         return ret;
1460  }
1461  
1462 -/* FIXME: Allow NULL functions and sub in pointers to generic for
1463 -   them. --RR */
1464 +/**
1465 + * ip_conntrack_protocol_register - Register layer 4 protocol helper
1466 + * @proto: structure describing this layer 4 protocol helper
1467 + *
1468 + * This function is called by layer 4 protocol helpers to register 
1469 + * themselves with the conntrack core.
1470 + */
1471  int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
1472  {
1473         int ret = 0;
1474         struct list_head *i;
1475  
1476 +       /* FIXME: Allow NULL functions and sub in pointers to generic for
1477 +          them. --RR */
1478         WRITE_LOCK(&ip_conntrack_lock);
1479         list_for_each(i, &protocol_list) {
1480                 if (((struct ip_conntrack_protocol *)i)->proto
1481 @@ -542,12 +599,20 @@
1482         return ret;
1483  }
1484  
1485 +/**
1486 + * ip_conntrack_protocol_unregister - Unregister layer 4 protocol helper
1487 + * @proto: structure describing this layer 4 protocol helper
1488 + *
1489 + * This function is called byh layer 4 protocol helpers to unregister
1490 + * themselvers from the conntrack core.  Please note that all conntrack
1491 + * entries for this protocol are deleted from the conntrack hash table.
1492 + */
1493  void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
1494  {
1495         WRITE_LOCK(&ip_conntrack_lock);
1496  
1497 -       /* ip_ct_find_proto() returns proto_generic in case there is no protocol 
1498 -        * helper. So this should be enough - HW */
1499 +       /* ip_ct_find_proto() returns proto_generic in case there is no
1500 +        * protocol helper. So this should be enough - HW */
1501         LIST_DELETE(&protocol_list, proto);
1502         WRITE_UNLOCK(&ip_conntrack_lock);
1503         
1504 @@ -602,5 +667,6 @@
1505  EXPORT_SYMBOL(ip_conntrack_expect_list);
1506  EXPORT_SYMBOL(ip_conntrack_lock);
1507  EXPORT_SYMBOL(ip_conntrack_hash);
1508 +EXPORT_SYMBOL(ip_conntrack_untracked);
1509  EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
1510  EXPORT_SYMBOL_GPL(ip_conntrack_put);
1511 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.4-rc2/net/ipv4/netfilter/ip_nat_core.c
1512 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_nat_core.c        2004-03-04 06:16:37.000000000 +0000
1513 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_nat_core.c    2004-03-07 08:43:29.000000000 +0000
1514 @@ -96,9 +96,16 @@
1515         WRITE_UNLOCK(&ip_nat_lock);
1516  }
1517  
1518 -/* We do checksum mangling, so if they were wrong before they're still
1519 - * wrong.  Also works for incomplete packets (eg. ICMP dest
1520 - * unreachables.) */
1521 +/**
1522 + * ip_nat_cheat_check - Incremental checksum change for IP/TCP checksum
1523 + * @oldvalinv: bit-inverted old value of 32bit word
1524 + * @newval: new value of 32bit word
1525 + * @oldcheck: old checksum value
1526 + *
1527 + * This function implements incremental checksum mangling, so if a checksum
1528 + * was wrong it will still be wrong after mangling.  Also works for incomplete
1529 + * packets (eg. ICMP dest unreachables).  Return value is the new checksum.
1530 + */
1531  u_int16_t
1532  ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
1533  {
1534 @@ -124,7 +131,14 @@
1535         return i;
1536  }
1537  
1538 -/* Is this tuple already taken? (not by us) */
1539 +/**
1540 + * ip_nat_used_tuple - Is this tuple already in use?
1541 + * @tuple: tuple to be used for this check
1542 + * @ignored_conntrack: conntrack excluded from this check
1543 + *
1544 + * This function checks for the reply (inverted) tuple in the conntrack
1545 + * hash.  This is necessarry with NAT, since there is no fixed mapping.
1546 + */
1547  int
1548  ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
1549                   const struct ip_conntrack *ignored_conntrack)
1550 @@ -515,6 +529,19 @@
1551  #endif
1552  };
1553  
1554 +/**
1555 + * ip_nat_setup_info - Set up NAT mappings for NEW packet
1556 + * @conntrack: conntrack on which we operate
1557 + * @mr: address/port range which is valid for this NAT mapping
1558 + * @hooknum: hook at which this NAT mapping applies
1559 + *
1560 + * This function is called by NAT targets (SNAT,DNAT,...) and by
1561 + * the NAT application helper modules.  It is called for the NEW packet
1562 + * of a connection in order to specify which NAT mappings shall apply to
1563 + * this connection at a given hook.
1564 + *
1565 + * Note: The reply mappings are created automagically by this function. 
1566 + */
1567  unsigned int
1568  ip_nat_setup_info(struct ip_conntrack *conntrack,
1569                   const struct ip_nat_multi_range *mr,
1570 @@ -1016,6 +1043,10 @@
1571         /* FIXME: Man, this is a hack.  <SIGH> */
1572         IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
1573         ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
1574 +       
1575 +       /* Initialize fake conntrack so that NAT will skip it */
1576 +       ip_conntrack_untracked.nat.info.initialized |= 
1577 +               (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
1578  
1579         return 0;
1580  }
1581 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_nat_helper.c linux-2.6.4-rc2/net/ipv4/netfilter/ip_nat_helper.c
1582 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_nat_helper.c      2004-03-04 06:16:38.000000000 +0000
1583 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_nat_helper.c  2004-03-07 08:43:10.000000000 +0000
1584 @@ -150,9 +150,19 @@
1585         return 1;
1586  }
1587  
1588 -/* Generic function for mangling variable-length address changes inside
1589 - * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
1590 - * command in FTP).
1591 +/**
1592 + * ip_nat_mangle_tcp_packet - Mangle and potentially resize payload packet
1593 + * @skb: pointer to skb of packet on which we operate
1594 + * @ct: conntrack of the connection to which this packet belongs
1595 + * @ctinfo: conntrack_info of the connection to which this packet belongs
1596 + * @match_offset: offset in bytes where to-be-manipulated part starts
1597 + * @match_len: lenght of the to-be-manipulated part
1598 + * @rep_buffer: pointer to buffer containing replacement
1599 + * @rep_len: length of replacement
1600 + *
1601 + * Generic function for mangling fixed and variable-length changes inside
1602 + * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command 
1603 + * in FTP).
1604   *
1605   * Takes care about all the nasty sequence number changes, checksumming,
1606   * skb enlargement, ...
1607 @@ -198,16 +208,27 @@
1608         return 1;
1609  }
1610                         
1611 -/* Generic function for mangling variable-length address changes inside
1612 - * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
1613 - * command in the Amanda protocol)
1614 +/**
1615 + * ip_nat_mangle_udp_packet - Mangle and potentially resize payload packet
1616 + * @skb: pointer to skb of packet on which we operate
1617 + * @ct: conntrack of the connection to which this packet belongs
1618 + * @ctinfo: conntrack_info of the connection to which this packet belongs
1619 + * @match_offset: offset in bytes where to-be-manipulated part starts
1620 + * @match_len: lenght of the to-be-manipulated part
1621 + * @rep_buffer: pointer to buffer containing replacement
1622 + * @rep_len: length of replacement
1623 + *
1624 + * Generic function for mangling fixed and variable-length changes inside
1625 + * NATed TCP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
1626 + * commad in the Amanda protocol)
1627   *
1628   * Takes care about all the nasty sequence number changes, checksumming,
1629   * skb enlargement, ...
1630   *
1631 - * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
1632 - *       should be fairly easy to do.
1633 - */
1634 + * FIXME: should be unified with ip_nat_mangle_tcp_packet!!
1635 + *
1636 + * */
1637 +
1638  int 
1639  ip_nat_mangle_udp_packet(struct sk_buff **pskb,
1640                          struct ip_conntrack *ct,
1641 @@ -405,6 +426,13 @@
1642         return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
1643  }
1644  
1645 +/**
1646 + * ip_nat_helper_register - Register NAT application helper
1647 + * @me: structure describing the helper
1648 + *
1649 + * This function is called by NAT application helpers to register
1650 + * themselves with the NAT core.
1651 + */
1652  int ip_nat_helper_register(struct ip_nat_helper *me)
1653  {
1654         int ret = 0;
1655 @@ -431,6 +459,13 @@
1656         return ret;
1657  }
1658  
1659 +/**
1660 + * ip_nat_helper_unregister - Unregister NAT application helper
1661 + * @me: structure describing the helper
1662 + *
1663 + * This function is called by NAT application helpers to unregister
1664 + * themselves from the NAT core.
1665 + */
1666  void ip_nat_helper_unregister(struct ip_nat_helper *me)
1667  {
1668         WRITE_LOCK(&ip_nat_lock);
1669 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.4-rc2/net/ipv4/netfilter/ip_nat_standalone.c
1670 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ip_nat_standalone.c  2004-03-04 06:16:55.000000000 +0000
1671 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ip_nat_standalone.c      2004-03-07 08:43:10.000000000 +0000
1672 @@ -266,7 +266,13 @@
1673  };
1674  #endif
1675  
1676 -/* Protocol registration. */
1677 +/**
1678 + * ip_nat_protocol_register - Register a layer 4 protocol helper
1679 + * @proto: structure describing this helper
1680 + * 
1681 + * This function is called by NAT layer 4 protocol helpers to register
1682 + * themselvers with the NAT core.
1683 + */
1684  int ip_nat_protocol_register(struct ip_nat_protocol *proto)
1685  {
1686         int ret = 0;
1687 @@ -287,9 +293,16 @@
1688         return ret;
1689  }
1690  
1691 -/* Noone stores the protocol anywhere; simply delete it. */
1692 +/**
1693 + * ip_nat_protocol_unregister - Unregister a layer 4 protocol helper
1694 + * @proto: structure describing the helper
1695 + *
1696 + * This function is called by NAT layer 4 protocol helpers to
1697 + * unregister themselves from the NAT core.
1698 + */
1699  void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
1700  {
1701 +       /* Noone stores the protocol anywhere; simply delete it. */
1702         WRITE_LOCK(&ip_nat_lock);
1703         LIST_DELETE(&protos, proto);
1704         WRITE_UNLOCK(&ip_nat_lock);
1705 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
1706 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c  1970-01-01 00:00:00.000000000 +0000
1707 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c      2004-03-07 08:43:14.000000000 +0000
1708 @@ -0,0 +1,89 @@
1709 +/**
1710 + * Strip all IP options in the IP packet header.
1711 + *
1712 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
1713 + * This software is distributed under GNU GPL v2, 1991
1714 + */
1715 +
1716 +#include <linux/module.h>
1717 +#include <linux/skbuff.h>
1718 +#include <linux/ip.h>
1719 +#include <net/checksum.h>
1720 +
1721 +#include <linux/netfilter_ipv4/ip_tables.h>
1722 +
1723 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
1724 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
1725 +MODULE_LICENSE("GPL");
1726 +
1727 +static unsigned int
1728 +target(struct sk_buff **pskb,
1729 +       const struct net_device *in,
1730 +       const struct net_device *out,
1731 +       unsigned int hooknum,
1732 +       const void *targinfo,
1733 +       void *userinfo)
1734 +{
1735 +       struct iphdr *iph;
1736 +       struct sk_buff *skb;
1737 +       struct ip_options *opt;
1738 +       unsigned char *optiph;
1739 +       int l;
1740 +       
1741 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
1742 +               return NF_DROP;
1743
1744 +       skb = (*pskb);
1745 +       iph = (*pskb)->nh.iph;
1746 +       optiph = skb->nh.raw;
1747 +       l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
1748 +
1749 +       /* if no options in packet then nothing to clear. */
1750 +       if (iph->ihl * 4 == sizeof(struct iphdr))
1751 +               return IPT_CONTINUE;
1752 +
1753 +       /* else clear all options */
1754 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
1755 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
1756 +       opt = &(IPCB(skb)->opt);
1757 +       opt->is_data = 0;
1758 +       opt->optlen = l;
1759 +
1760 +       skb->nfcache |= NFC_ALTERED;
1761 +
1762 +        return IPT_CONTINUE;
1763 +}
1764 +
1765 +static int
1766 +checkentry(const char *tablename,
1767 +          const struct ipt_entry *e,
1768 +           void *targinfo,
1769 +           unsigned int targinfosize,
1770 +           unsigned int hook_mask)
1771 +{
1772 +       if (strcmp(tablename, "mangle")) {
1773 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1774 +               return 0;
1775 +       }
1776 +       /* nothing else to check because no parameters */
1777 +       return 1;
1778 +}
1779 +
1780 +static struct ipt_target ipt_ipv4optsstrip_reg = { 
1781 +       .name = "IPV4OPTSSTRIP",
1782 +       .target = target,
1783 +       .checkentry = checkentry,
1784 +       .me = THIS_MODULE };
1785 +
1786 +static int __init init(void)
1787 +{
1788 +       return ipt_register_target(&ipt_ipv4optsstrip_reg);
1789 +}
1790 +
1791 +static void __exit fini(void)
1792 +{
1793 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
1794 +}
1795 +
1796 +module_init(init);
1797 +module_exit(fini);
1798 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_LOG.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_LOG.c
1799 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_LOG.c    2004-03-04 06:17:03.000000000 +0000
1800 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_LOG.c        2004-03-07 08:43:12.000000000 +0000
1801 @@ -19,6 +19,7 @@
1802  #include <net/tcp.h>
1803  #include <net/route.h>
1804  
1805 +#include <linux/netfilter.h>
1806  #include <linux/netfilter_ipv4/ip_tables.h>
1807  #include <linux/netfilter_ipv4/ipt_LOG.h>
1808  
1809 @@ -26,6 +27,10 @@
1810  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
1811  MODULE_DESCRIPTION("iptables syslog logging module");
1812  
1813 +static unsigned int nflog = 1;
1814 +MODULE_PARM(nflog, "i");
1815 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
1816
1817  #if 0
1818  #define DEBUGP printk
1819  #else
1820 @@ -324,28 +329,25 @@
1821         /* maxlen = 230+   91  + 230 + 252 = 803 */
1822  }
1823  
1824 -static unsigned int
1825 -ipt_log_target(struct sk_buff **pskb,
1826 +static void
1827 +ipt_log_packet(unsigned int hooknum,
1828 +              const struct sk_buff *skb,
1829                const struct net_device *in,
1830                const struct net_device *out,
1831 -              unsigned int hooknum,
1832 -              const void *targinfo,
1833 -              void *userinfo)
1834 +              const struct ipt_log_info *loginfo,
1835 +              const char *level_string,
1836 +              const char *prefix)
1837  {
1838 -       const struct ipt_log_info *loginfo = targinfo;
1839 -       char level_string[4] = "< >";
1840 -
1841 -       level_string[1] = '0' + (loginfo->level % 8);
1842         spin_lock_bh(&log_lock);
1843         printk(level_string);
1844         printk("%sIN=%s OUT=%s ",
1845 -              loginfo->prefix,
1846 +              prefix == NULL ? loginfo->prefix : prefix,
1847                in ? in->name : "",
1848                out ? out->name : "");
1849  #ifdef CONFIG_BRIDGE_NETFILTER
1850 -       if ((*pskb)->nf_bridge) {
1851 -               struct net_device *physindev = (*pskb)->nf_bridge->physindev;
1852 -               struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev;
1853 +       if (skb->nf_bridge) {
1854 +               struct net_device *physindev = skb->nf_bridge->physindev;
1855 +               struct net_device *physoutdev = skb->nf_bridge->physoutdev;
1856  
1857                 if (physindev && in != physindev)
1858                         printk("PHYSIN=%s ", physindev->name);
1859 @@ -357,25 +359,56 @@
1860         if (in && !out) {
1861                 /* MAC logging for input chain only. */
1862                 printk("MAC=");
1863 -               if ((*pskb)->dev && (*pskb)->dev->hard_header_len
1864 -                   && (*pskb)->mac.raw != (void*)(*pskb)->nh.iph) {
1865 +               if (skb->dev && skb->dev->hard_header_len
1866 +                   && skb->mac.raw != (void*)skb->nh.iph) {
1867                         int i;
1868 -                       unsigned char *p = (*pskb)->mac.raw;
1869 -                       for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
1870 +                       unsigned char *p = skb->mac.raw;
1871 +                       for (i = 0; i < skb->dev->hard_header_len; i++,p++)
1872                                 printk("%02x%c", *p,
1873 -                                      i==(*pskb)->dev->hard_header_len - 1
1874 +                                      i==skb->dev->hard_header_len - 1
1875                                        ? ' ':':');
1876                 } else
1877                         printk(" ");
1878         }
1879  
1880 -       dump_packet(loginfo, *pskb, 0);
1881 +       dump_packet(loginfo, skb, 0);
1882         printk("\n");
1883         spin_unlock_bh(&log_lock);
1884 +}
1885 +
1886 +static unsigned int
1887 +ipt_log_target(struct sk_buff **pskb,
1888 +              const struct net_device *in,
1889 +              const struct net_device *out,
1890 +              unsigned int hooknum,
1891 +              const void *targinfo,
1892 +              void *userinfo)
1893 +{
1894 +       const struct ipt_log_info *loginfo = targinfo;
1895 +       char level_string[4] = "< >";
1896 +
1897 +       level_string[1] = '0' + (loginfo->level % 8);
1898 +       ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
1899  
1900         return IPT_CONTINUE;
1901  }
1902  
1903 +static void
1904 +ipt_logfn(unsigned int hooknum,
1905 +         const struct sk_buff *skb,
1906 +         const struct net_device *in,
1907 +         const struct net_device *out,
1908 +         const char *prefix)
1909 +{
1910 +       struct ipt_log_info loginfo = { 
1911 +               .level = 0, 
1912 +               .logflags = IPT_LOG_MASK, 
1913 +               .prefix = "" 
1914 +       };
1915 +
1916 +       ipt_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
1917 +}
1918 +
1919  static int ipt_log_checkentry(const char *tablename,
1920                               const struct ipt_entry *e,
1921                               void *targinfo,
1922 @@ -413,11 +446,18 @@
1923  
1924  static int __init init(void)
1925  {
1926 -       return ipt_register_target(&ipt_log_reg);
1927 +       if (ipt_register_target(&ipt_log_reg))
1928 +               return -EINVAL;
1929 +       if (nflog)
1930 +               nf_log_register(PF_INET, &ipt_logfn);
1931 +       
1932 +       return 0;
1933  }
1934  
1935  static void __exit fini(void)
1936  {
1937 +       if (nflog)
1938 +               nf_log_unregister(PF_INET, &ipt_logfn);
1939         ipt_unregister_target(&ipt_log_reg);
1940  }
1941  
1942 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_NOTRACK.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_NOTRACK.c
1943 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_NOTRACK.c        1970-01-01 00:00:00.000000000 +0000
1944 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_NOTRACK.c    2004-03-07 08:43:29.000000000 +0000
1945 @@ -0,0 +1,75 @@
1946 +/* This is a module which is used for setting up fake conntracks
1947 + * on packets so that they are not seen by the conntrack/NAT code.
1948 + */
1949 +#include <linux/module.h>
1950 +#include <linux/skbuff.h>
1951 +
1952 +#include <linux/netfilter_ipv4/ip_tables.h>
1953 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1954 +
1955 +static unsigned int
1956 +target(struct sk_buff **pskb,
1957 +       const struct net_device *in,
1958 +       const struct net_device *out,
1959 +       unsigned int hooknum,
1960 +       const void *targinfo,
1961 +       void *userinfo)
1962 +{
1963 +       /* Previously seen (loopback)? Ignore. */
1964 +       if ((*pskb)->nfct != NULL)
1965 +               return IPT_CONTINUE;
1966 +
1967 +       /* Attach fake conntrack entry. 
1968 +          If there is a real ct entry correspondig to this packet, 
1969 +          it'll hang aroun till timing out. We don't deal with it
1970 +          for performance reasons. JK */
1971 +       (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
1972 +       nf_conntrack_get((*pskb)->nfct);
1973 +
1974 +       return IPT_CONTINUE;
1975 +}
1976 +
1977 +static int
1978 +checkentry(const char *tablename,
1979 +          const struct ipt_entry *e,
1980 +           void *targinfo,
1981 +           unsigned int targinfosize,
1982 +           unsigned int hook_mask)
1983 +{
1984 +       if (targinfosize != 0) {
1985 +               printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
1986 +                      targinfosize);
1987 +               return 0;
1988 +       }
1989 +
1990 +       if (strcmp(tablename, "raw") != 0) {
1991 +               printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
1992 +               return 0;
1993 +       }
1994 +
1995 +       return 1;
1996 +}
1997 +
1998 +static struct ipt_target ipt_notrack_reg = { 
1999 +       .name = "NOTRACK", 
2000 +       .target = target, 
2001 +       .checkentry = checkentry,
2002 +       .me = THIS_MODULE 
2003 +};
2004 +
2005 +static int __init init(void)
2006 +{
2007 +       if (ipt_register_target(&ipt_notrack_reg))
2008 +               return -EINVAL;
2009 +
2010 +       return 0;
2011 +}
2012 +
2013 +static void __exit fini(void)
2014 +{
2015 +       ipt_unregister_target(&ipt_notrack_reg);
2016 +}
2017 +
2018 +module_init(init);
2019 +module_exit(fini);
2020 +MODULE_LICENSE("GPL");
2021 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_TTL.c
2022 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_TTL.c    1970-01-01 00:00:00.000000000 +0000
2023 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_TTL.c        2004-03-07 08:43:16.000000000 +0000
2024 @@ -0,0 +1,120 @@
2025 +/* TTL modification target for IP tables
2026 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
2027 + *
2028 + * Version: $Revision$
2029 + *
2030 + * This software is distributed under the terms of GNU GPL
2031 + */
2032 +
2033 +#include <linux/module.h>
2034 +#include <linux/skbuff.h>
2035 +#include <linux/ip.h>
2036 +#include <net/checksum.h>
2037 +
2038 +#include <linux/netfilter_ipv4/ip_tables.h>
2039 +#include <linux/netfilter_ipv4/ipt_TTL.h>
2040 +
2041 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
2042 +MODULE_DESCRIPTION("IP tables TTL modification module");
2043 +MODULE_LICENSE("GPL");
2044 +
2045 +static unsigned int 
2046 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, 
2047 +               const struct net_device *out, unsigned int hooknum, 
2048 +               const void *targinfo, void *userinfo)
2049 +{
2050 +       struct iphdr *iph;
2051 +       const struct ipt_TTL_info *info = targinfo;
2052 +       u_int16_t diffs[2];
2053 +       int new_ttl;
2054 +
2055 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
2056 +               return NF_DROP;
2057 +
2058 +       iph = (*pskb)->nh.iph;
2059 +                        
2060 +       switch (info->mode) {
2061 +               case IPT_TTL_SET:
2062 +                       new_ttl = info->ttl;
2063 +                       break;
2064 +               case IPT_TTL_INC:
2065 +                       new_ttl = iph->ttl + info->ttl;
2066 +                       if (new_ttl > 255)
2067 +                               new_ttl = 255;
2068 +                       break;
2069 +               case IPT_TTL_DEC:
2070 +                       new_ttl = iph->ttl + info->ttl;
2071 +                       if (new_ttl < 0)
2072 +                               new_ttl = 0;
2073 +                       break;
2074 +               default:
2075 +                       new_ttl = iph->ttl;
2076 +                       break;
2077 +       }
2078 +
2079 +       if (new_ttl != iph->ttl) {
2080 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
2081 +               iph->ttl = new_ttl;
2082 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
2083 +               iph->check = csum_fold(csum_partial((char *)diffs,
2084 +                                                   sizeof(diffs),
2085 +                                                   iph->check^0xFFFF));
2086 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
2087 +       }
2088 +
2089 +       return IPT_CONTINUE;
2090 +}
2091 +
2092 +static int ipt_ttl_checkentry(const char *tablename,
2093 +               const struct ipt_entry *e,
2094 +               void *targinfo,
2095 +               unsigned int targinfosize,
2096 +               unsigned int hook_mask)
2097 +{
2098 +       struct ipt_TTL_info *info = targinfo;
2099 +
2100 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
2101 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
2102 +                               targinfosize,
2103 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
2104 +               return 0;       
2105 +       }       
2106 +
2107 +       if (strcmp(tablename, "mangle")) {
2108 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
2109 +               return 0;
2110 +       }
2111 +
2112 +       if (info->mode > IPT_TTL_MAXMODE) {
2113 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
2114 +                       info->mode);
2115 +               return 0;
2116 +       }
2117 +
2118 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
2119 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
2120 +               return 0;
2121 +       }
2122 +       
2123 +       return 1;
2124 +}
2125 +
2126 +static struct ipt_target ipt_TTL = { 
2127 +       .name = "TTL",
2128 +       .target = ipt_ttl_target, 
2129 +       .checkentry = ipt_ttl_checkentry, 
2130 +       .me = THIS_MODULE 
2131 +};
2132 +
2133 +static int __init init(void)
2134 +{
2135 +       return ipt_register_target(&ipt_TTL);
2136 +}
2137 +
2138 +static void __exit fini(void)
2139 +{
2140 +       ipt_unregister_target(&ipt_TTL);
2141 +}
2142 +
2143 +module_init(init);
2144 +module_exit(fini);
2145 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_ULOG.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_ULOG.c
2146 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_ULOG.c   2004-03-04 06:16:42.000000000 +0000
2147 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_ULOG.c       2004-03-07 08:43:12.000000000 +0000
2148 @@ -50,6 +50,7 @@
2149  #include <linux/netlink.h>
2150  #include <linux/netdevice.h>
2151  #include <linux/mm.h>
2152 +#include <linux/netfilter.h>
2153  #include <linux/netfilter_ipv4/ip_tables.h>
2154  #include <linux/netfilter_ipv4/ipt_ULOG.h>
2155  #include <linux/netfilter_ipv4/lockhelp.h>
2156 @@ -80,6 +81,10 @@
2157  MODULE_PARM(flushtimeout, "i");
2158  MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
2159  
2160 +static unsigned int nflog = 1;
2161 +MODULE_PARM(nflog, "i");
2162 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
2163 +
2164  /* global data structures */
2165  
2166  typedef struct {
2167 @@ -157,17 +162,17 @@
2168         return skb;
2169  }
2170  
2171 -static unsigned int ipt_ulog_target(struct sk_buff **pskb,
2172 -                                   const struct net_device *in,
2173 -                                   const struct net_device *out,
2174 -                                   unsigned int hooknum,
2175 -                                   const void *targinfo, void *userinfo)
2176 +static void ipt_ulog_packet(unsigned int hooknum,
2177 +                           const struct sk_buff *skb,
2178 +                           const struct net_device *in,
2179 +                           const struct net_device *out,
2180 +                           const struct ipt_ulog_info *loginfo,
2181 +                           const char *prefix)
2182  {
2183         ulog_buff_t *ub;
2184         ulog_packet_msg_t *pm;
2185         size_t size, copy_len;
2186         struct nlmsghdr *nlh;
2187 -       struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
2188  
2189         /* ffs == find first bit set, necessary because userspace
2190          * is already shifting groupnumber, but we need unshifted.
2191 @@ -176,8 +181,8 @@
2192  
2193         /* calculate the size of the skb needed */
2194         if ((loginfo->copy_range == 0) ||
2195 -           (loginfo->copy_range > (*pskb)->len)) {
2196 -               copy_len = (*pskb)->len;
2197 +           (loginfo->copy_range > skb->len)) {
2198 +               copy_len = skb->len;
2199         } else {
2200                 copy_len = loginfo->copy_range;
2201         }
2202 @@ -214,19 +219,21 @@
2203  
2204         /* copy hook, prefix, timestamp, payload, etc. */
2205         pm->data_len = copy_len;
2206 -       pm->timestamp_sec = (*pskb)->stamp.tv_sec;
2207 -       pm->timestamp_usec = (*pskb)->stamp.tv_usec;
2208 -       pm->mark = (*pskb)->nfmark;
2209 +       pm->timestamp_sec = skb->stamp.tv_sec;
2210 +       pm->timestamp_usec = skb->stamp.tv_usec;
2211 +       pm->mark = skb->nfmark;
2212         pm->hook = hooknum;
2213 -       if (loginfo->prefix[0] != '\0')
2214 +       if (prefix != NULL)
2215 +               strncpy(pm->prefix, prefix, sizeof(pm->prefix));
2216 +       else if (loginfo->prefix[0] != '\0')
2217                 strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
2218         else
2219                 *(pm->prefix) = '\0';
2220  
2221         if (in && in->hard_header_len > 0
2222 -           && (*pskb)->mac.raw != (void *) (*pskb)->nh.iph
2223 +           && skb->mac.raw != (void *) skb->nh.iph
2224             && in->hard_header_len <= ULOG_MAC_LEN) {
2225 -               memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len);
2226 +               memcpy(pm->mac, skb->mac.raw, in->hard_header_len);
2227                 pm->mac_len = in->hard_header_len;
2228         } else
2229                 pm->mac_len = 0;
2230 @@ -241,8 +248,8 @@
2231         else
2232                 pm->outdev_name[0] = '\0';
2233  
2234 -       /* copy_len <= (*pskb)->len, so can't fail. */
2235 -       if (skb_copy_bits(*pskb, 0, pm->payload, copy_len) < 0)
2236 +       /* copy_len <= skb->len, so can't fail. */
2237 +       if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
2238                 BUG();
2239         
2240         /* check if we are building multi-part messages */
2241 @@ -266,8 +273,7 @@
2242  
2243         UNLOCK_BH(&ulog_lock);
2244  
2245 -       return IPT_CONTINUE;
2246 -
2247 +       return;
2248  
2249  nlmsg_failure:
2250         PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
2251 @@ -276,8 +282,35 @@
2252         PRINTR("ipt_ULOG: Error building netlink message\n");
2253  
2254         UNLOCK_BH(&ulog_lock);
2255 +}
2256 +
2257 +static unsigned int ipt_ulog_target(struct sk_buff **pskb,
2258 +                                   const struct net_device *in,
2259 +                                   const struct net_device *out,
2260 +                                   unsigned int hooknum,
2261 +                                   const void *targinfo, void *userinfo)
2262 +{
2263 +       struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
2264  
2265 -       return IPT_CONTINUE;
2266 +       ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
2267
2268 +       return IPT_CONTINUE;
2269 +}
2270
2271 +static void ipt_logfn(unsigned int hooknum,
2272 +                     const struct sk_buff *skb,
2273 +                     const struct net_device *in,
2274 +                     const struct net_device *out,
2275 +                     const char *prefix)
2276 +{
2277 +       struct ipt_ulog_info loginfo = { 
2278 +               .nl_group = ULOG_DEFAULT_NLGROUP,
2279 +               .copy_range = 0,
2280 +               .qthreshold = ULOG_DEFAULT_QTHRESHOLD,
2281 +               .prefix = ""
2282 +       };
2283 +
2284 +       ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
2285  }
2286  
2287  static int ipt_ulog_checkentry(const char *tablename,
2288 @@ -341,7 +374,9 @@
2289                 sock_release(nflognl->sk_socket);
2290                 return -EINVAL;
2291         }
2292 -
2293 +       if (nflog)
2294 +               nf_log_register(PF_INET, &ipt_logfn);
2295 +       
2296         return 0;
2297  }
2298  
2299 @@ -352,6 +387,8 @@
2300  
2301         DEBUGP("ipt_ULOG: cleanup_module\n");
2302  
2303 +       if (nflog)
2304 +               nf_log_unregister(PF_INET, &ipt_logfn);
2305         ipt_unregister_target(&ipt_ulog_reg);
2306         sock_release(nflognl->sk_socket);
2307  
2308 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_connlimit.c
2309 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_connlimit.c      1970-01-01 00:00:00.000000000 +0000
2310 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_connlimit.c  2004-03-07 08:43:18.000000000 +0000
2311 @@ -0,0 +1,230 @@
2312 +/*
2313 + * netfilter module to limit the number of parallel tcp
2314 + * connections per IP address.
2315 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
2316 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
2317 + *             only ignore TIME_WAIT or gone connections
2318 + *
2319 + * based on ...
2320 + *
2321 + * Kernel module to match connection tracking information.
2322 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
2323 + */
2324 +#include <linux/module.h>
2325 +#include <linux/skbuff.h>
2326 +#include <linux/list.h>
2327 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2328 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2329 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
2330 +#include <linux/netfilter_ipv4/ip_tables.h>
2331 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
2332 +
2333 +#define DEBUG 0
2334 +
2335 +MODULE_LICENSE("GPL");
2336 +
2337 +/* we'll save the tuples of all connections we care about */
2338 +struct ipt_connlimit_conn
2339 +{
2340 +        struct list_head list;
2341 +       struct ip_conntrack_tuple tuple;
2342 +};
2343 +
2344 +struct ipt_connlimit_data {
2345 +       spinlock_t lock;
2346 +       struct list_head iphash[256];
2347 +};
2348 +
2349 +static int ipt_iphash(u_int32_t addr)
2350 +{
2351 +       int hash;
2352 +
2353 +       hash  =  addr        & 0xff;
2354 +       hash ^= (addr >>  8) & 0xff;
2355 +       hash ^= (addr >> 16) & 0xff;
2356 +       hash ^= (addr >> 24) & 0xff;
2357 +       return hash;
2358 +}
2359 +
2360 +static int count_them(struct ipt_connlimit_data *data,
2361 +                     u_int32_t addr, u_int32_t mask,
2362 +                     struct ip_conntrack *ct)
2363 +{
2364 +#if DEBUG
2365 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
2366 +                                    "fin_wait", "time_wait", "close", "close_wait",
2367 +                                    "last_ack", "listen" };
2368 +#endif
2369 +       int addit = 1, matches = 0;
2370 +       struct ip_conntrack_tuple tuple;
2371 +       struct ip_conntrack_tuple_hash *found;
2372 +       struct ipt_connlimit_conn *conn;
2373 +       struct list_head *hash,*lh;
2374 +
2375 +       spin_lock(&data->lock);
2376 +       tuple = ct->tuplehash[0].tuple;
2377 +       hash = &data->iphash[ipt_iphash(addr & mask)];
2378 +
2379 +       /* check the saved connections */
2380 +       for (lh = hash->next; lh != hash; lh = lh->next) {
2381 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
2382 +               found = ip_conntrack_find_get(&conn->tuple,ct);
2383 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
2384 +                   found != NULL &&
2385 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
2386 +                       /* Just to be sure we have it only once in the list.
2387 +                          We should'nt see tuples twice unless someone hooks this
2388 +                          into a table without "-p tcp --syn" */
2389 +                       addit = 0;
2390 +               }
2391 +#if DEBUG
2392 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
2393 +                      ipt_iphash(addr & mask),
2394 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
2395 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
2396 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
2397 +#endif
2398 +               if (NULL == found) {
2399 +                       /* this one is gone */
2400 +                       lh = lh->prev;
2401 +                       list_del(lh->next);
2402 +                       kfree(conn);
2403 +                       continue;
2404 +               }
2405 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
2406 +                       /* we don't care about connections which are
2407 +                          closed already -> ditch it */
2408 +                       lh = lh->prev;
2409 +                       list_del(lh->next);
2410 +                       kfree(conn);
2411 +                       nf_conntrack_put(&found->ctrack->infos[0]);
2412 +                       continue;
2413 +               }
2414 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
2415 +                       /* same source IP address -> be counted! */
2416 +                       matches++;
2417 +               }
2418 +               nf_conntrack_put(&found->ctrack->infos[0]);
2419 +       }
2420 +       if (addit) {
2421 +               /* save the new connection in our list */
2422 +#if DEBUG
2423 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
2424 +                      ipt_iphash(addr & mask),
2425 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
2426 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
2427 +#endif
2428 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
2429 +               if (NULL == conn)
2430 +                       return -1;
2431 +               memset(conn,0,sizeof(*conn));
2432 +               INIT_LIST_HEAD(&conn->list);
2433 +               conn->tuple = tuple;
2434 +               list_add(&conn->list,hash);
2435 +               matches++;
2436 +       }
2437 +       spin_unlock(&data->lock);
2438 +       return matches;
2439 +}
2440 +
2441 +static int
2442 +match(const struct sk_buff *skb,
2443 +      const struct net_device *in,
2444 +      const struct net_device *out,
2445 +      const void *matchinfo,
2446 +      int offset,
2447 +      int *hotdrop)
2448 +{
2449 +       const struct ipt_connlimit_info *info = matchinfo;
2450 +       int connections, match;
2451 +       struct ip_conntrack *ct;
2452 +       enum ip_conntrack_info ctinfo;
2453 +
2454 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
2455 +       if (NULL == ct) {
2456 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
2457 +               *hotdrop = 1;
2458 +               return 0;
2459 +       }
2460 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
2461 +       if (-1 == connections) {
2462 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
2463 +               *hotdrop = 1; /* let's free some memory :-) */
2464 +               return 0;
2465 +       }
2466 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
2467 +#if DEBUG
2468 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
2469 +              "connections=%d limit=%d match=%s\n",
2470 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
2471 +              connections, info->limit, match ? "yes" : "no");
2472 +#endif
2473 +
2474 +       return match;
2475 +}
2476 +
2477 +static int check(const char *tablename,
2478 +                const struct ipt_ip *ip,
2479 +                void *matchinfo,
2480 +                unsigned int matchsize,
2481 +                unsigned int hook_mask)
2482 +{
2483 +       struct ipt_connlimit_info *info = matchinfo;
2484 +       int i;
2485 +
2486 +       /* verify size */
2487 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
2488 +               return 0;
2489 +
2490 +       /* refuse anything but tcp */
2491 +       if (ip->proto != IPPROTO_TCP)
2492 +               return 0;
2493 +
2494 +       /* init private data */
2495 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
2496 +       spin_lock_init(&(info->data->lock));
2497 +       for (i = 0; i < 256; i++)
2498 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
2499 +       
2500 +       return 1;
2501 +}
2502 +
2503 +static void destroy(void *matchinfo, unsigned int matchinfosize)
2504 +{
2505 +       struct ipt_connlimit_info *info = matchinfo;
2506 +       struct ipt_connlimit_conn *conn;
2507 +       struct list_head *hash;
2508 +       int i;
2509 +
2510 +       /* cleanup */
2511 +       for (i = 0; i < 256; i++) {
2512 +               hash = &(info->data->iphash[i]);
2513 +               while (hash != hash->next) {
2514 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
2515 +                       list_del(hash->next);
2516 +                       kfree(conn);
2517 +               }
2518 +       }
2519 +       kfree(info->data);
2520 +}
2521 +
2522 +static struct ipt_match connlimit_match = { 
2523 +       .name = "connlimit",
2524 +       .match = &match,
2525 +       .checkentry = &check,
2526 +       .destroy = &destroy,
2527 +       .me = THIS_MODULE
2528 +};
2529 +
2530 +static int __init init(void)
2531 +{
2532 +       return ipt_register_match(&connlimit_match);
2533 +}
2534 +
2535 +static void __exit fini(void)
2536 +{
2537 +       ipt_unregister_match(&connlimit_match);
2538 +}
2539 +
2540 +module_init(init);
2541 +module_exit(fini);
2542 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_conntrack.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_conntrack.c
2543 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_conntrack.c      2004-03-04 06:17:04.000000000 +0000
2544 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_conntrack.c  2004-03-07 08:43:29.000000000 +0000
2545 @@ -35,11 +35,13 @@
2546  
2547  #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
2548  
2549 -       if (ct)
2550 -               statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
2551 -       else
2552 -               statebit = IPT_CONNTRACK_STATE_INVALID;
2553 -
2554 +       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
2555 +               statebit = IPT_CONNTRACK_STATE_UNTRACKED;
2556 +       else if (ct)
2557 +               statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
2558 +       else
2559 +               statebit = IPT_CONNTRACK_STATE_INVALID;
2560
2561         if(sinfo->flags & IPT_CONNTRACK_STATE) {
2562                 if (ct) {
2563                         if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip !=
2564 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_dstlimit.c
2565 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_dstlimit.c       1970-01-01 00:00:00.000000000 +0000
2566 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_dstlimit.c   2004-03-07 08:43:19.000000000 +0000
2567 @@ -0,0 +1,690 @@
2568 +/* iptables match extension to limit the number of packets per second
2569 + * seperately for each destination.
2570 + *
2571 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
2572 + *
2573 + * $Id$
2574 + *
2575 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
2576 + *
2577 + * based on ipt_limit.c by:
2578 + * Jérôme de Vivie     <devivie@info.enserb.u-bordeaux.fr>
2579 + * Hervé Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
2580 + * Rusty Russell       <rusty@rustcorp.com.au>
2581 + *
2582 + * The general idea is to create a hash table for every dstip and have a
2583 + * seperate limit counter per tuple.  This way you can do something like 'limit
2584 + * the number of syn packets for each of my internal addresses.
2585 + *
2586 + * Ideally this would just be implemented as a general 'hash' match, which would
2587 + * allow us to attach any iptables target to it's hash buckets.  But this is
2588 + * not possible in the current iptables architecture.  As always, pkttables for
2589 + * 2.7.x will help ;)
2590 + */
2591 +#include <linux/module.h>
2592 +#include <linux/skbuff.h>
2593 +#include <linux/spinlock.h>
2594 +#include <linux/random.h>
2595 +#include <linux/jhash.h>
2596 +#include <linux/slab.h>
2597 +#include <linux/vmalloc.h>
2598 +#include <linux/tcp.h>
2599 +#include <linux/udp.h>
2600 +#include <linux/proc_fs.h>
2601 +#include <linux/seq_file.h>
2602 +
2603 +#define ASSERT_READ_LOCK(x) 
2604 +#define ASSERT_WRITE_LOCK(x) 
2605 +#include <linux/netfilter_ipv4/lockhelp.h>
2606 +#include <linux/netfilter_ipv4/listhelp.h>
2607 +
2608 +#include <linux/netfilter_ipv4/ip_tables.h>
2609 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
2610 +
2611 +/* FIXME: this is just for IP_NF_ASSERRT */
2612 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2613 +
2614 +#define MS2JIFFIES(x) ((x*HZ)/1000)
2615 +
2616 +MODULE_LICENSE("GPL");
2617 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2618 +MODULE_DESCRIPTION("iptables match for limiting per destination");
2619 +
2620 +/* need to declare this at the top */
2621 +static struct proc_dir_entry *dstlimit_procdir;
2622 +static struct file_operations dl_file_ops;
2623 +
2624 +/* hash table crap */
2625 +
2626 +struct dsthash_dst {
2627 +       u_int32_t src_ip;
2628 +       u_int32_t dst_ip;
2629 +       u_int16_t port;
2630 +};
2631 +
2632 +struct dsthash_ent {
2633 +       /* static / read-only parts in the beginning */
2634 +       struct list_head list;
2635 +       struct dsthash_dst dst;
2636 +
2637 +       /* modified structure members in the end */
2638 +       unsigned long expires;          /* precalculated expiry time */
2639 +       struct {
2640 +               unsigned long prev;     /* last modification */
2641 +               u_int32_t credit;
2642 +               u_int32_t credit_cap, cost;
2643 +       } rateinfo;
2644 +};
2645 +
2646 +struct ipt_dstlimit_htable {
2647 +       struct list_head list;          /* global list of all htables */
2648 +       atomic_t use;
2649 +
2650 +       struct dstlimit_cfg cfg;        /* config */
2651 +
2652 +       /* used internally */
2653 +       spinlock_t lock;                /* lock for list_head */
2654 +       u_int32_t rnd;                  /* random seed for hash */
2655 +       struct timer_list timer;        /* timer for gc */
2656 +       atomic_t count;                 /* number entries in table */
2657 +
2658 +       /* seq_file stuff */
2659 +       struct proc_dir_entry *pde;
2660 +
2661 +       struct list_head hash[0];       /* hashtable itself */
2662 +};
2663 +
2664 +DECLARE_RWLOCK(dstlimit_lock);         /* protects htables list */
2665 +static LIST_HEAD(dstlimit_htables);
2666 +static kmem_cache_t *dstlimit_cachep;
2667 +
2668 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
2669 +{
2670 +       return (ent->dst.dst_ip == b->dst_ip 
2671 +               && ent->dst.port == b->port
2672 +               && ent->dst.src_ip == b->src_ip);
2673 +}
2674 +
2675 +static inline u_int32_t
2676 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
2677 +{
2678 +       return (jhash_3words(dst->dst_ip, dst->port, 
2679 +                            dst->src_ip, ht->rnd) % ht->cfg.size);
2680 +}
2681 +
2682 +static inline struct dsthash_ent *
2683 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2684 +{
2685 +       struct dsthash_ent *ent;
2686 +       u_int32_t hash = hash_dst(ht, dst);
2687 +       MUST_BE_LOCKED(&ht->lock);
2688 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
2689 +       return ent;
2690 +}
2691 +
2692 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
2693 +static struct dsthash_ent *
2694 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2695 +{
2696 +       struct dsthash_ent *ent;
2697 +
2698 +       /* initialize hash with random val at the time we allocate
2699 +        * the first hashtable entry */
2700 +       if (!ht->rnd)
2701 +               get_random_bytes(&ht->rnd, 4);
2702 +
2703 +       if (ht->cfg.max &&
2704 +           atomic_read(&ht->count) >= ht->cfg.max) {
2705 +               /* FIXME: do something. question is what.. */
2706 +               if (net_ratelimit())
2707 +                       printk(KERN_WARNING 
2708 +                               "ipt_dstlimit: max count of %u reached\n", 
2709 +                               ht->cfg.max);
2710 +               return NULL;
2711 +       }
2712 +
2713 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
2714 +       if (!ent) {
2715 +               if (net_ratelimit())
2716 +                       printk(KERN_ERR 
2717 +                               "ipt_dstlimit: can't allocate dsthash_ent\n");
2718 +               return NULL;
2719 +       }
2720 +
2721 +       atomic_inc(&ht->count);
2722 +
2723 +       ent->dst.dst_ip = dst->dst_ip;
2724 +       ent->dst.port = dst->port;
2725 +       ent->dst.src_ip = dst->src_ip;
2726 +
2727 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
2728 +
2729 +       return ent;
2730 +}
2731 +
2732 +static inline void 
2733 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
2734 +{
2735 +       MUST_BE_LOCKED(&ht->lock);
2736 +
2737 +       list_del(&ent->list);
2738 +       kmem_cache_free(dstlimit_cachep, ent);
2739 +       atomic_dec(&ht->count);
2740 +}
2741 +static void htable_gc(unsigned long htlong);
2742 +
2743 +static int htable_create(struct ipt_dstlimit_info *minfo)
2744 +{
2745 +       int i;
2746 +       unsigned int size;
2747 +       struct ipt_dstlimit_htable *hinfo;
2748 +
2749 +       if (minfo->cfg.size)
2750 +               size = minfo->cfg.size;
2751 +       else {
2752 +               size = (((num_physpages << PAGE_SHIFT) / 16384)
2753 +                        / sizeof(struct list_head));
2754 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
2755 +                       size = 8192;
2756 +               if (size < 16)
2757 +                       size = 16;
2758 +       }
2759 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
2760 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
2761 +                       + (sizeof(struct list_head) * size));
2762 +       if (!hinfo) {
2763 +               printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
2764 +               return -1;
2765 +       }
2766 +       minfo->hinfo = hinfo;
2767 +
2768 +       /* copy match config into hashtable config */
2769 +       memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
2770 +       hinfo->cfg.size = size;
2771 +       if (!hinfo->cfg.max)
2772 +               hinfo->cfg.max = 8 * hinfo->cfg.size;
2773 +       else if (hinfo->cfg.max < hinfo->cfg.size)
2774 +               hinfo->cfg.max = hinfo->cfg.size;
2775 +
2776 +       for (i = 0; i < hinfo->cfg.size; i++)
2777 +               INIT_LIST_HEAD(&hinfo->hash[i]);
2778 +
2779 +       atomic_set(&hinfo->count, 0);
2780 +       atomic_set(&hinfo->use, 1);
2781 +       hinfo->rnd = 0;
2782 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
2783 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
2784 +       if (!hinfo->pde) {
2785 +               vfree(hinfo);
2786 +               return -1;
2787 +       }
2788 +       hinfo->pde->proc_fops = &dl_file_ops;
2789 +       hinfo->pde->data = hinfo;
2790 +
2791 +       init_timer(&hinfo->timer);
2792 +       hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
2793 +       hinfo->timer.data = (unsigned long )hinfo;
2794 +       hinfo->timer.function = htable_gc;
2795 +       add_timer(&hinfo->timer);
2796 +
2797 +       WRITE_LOCK(&dstlimit_lock);
2798 +       list_add(&hinfo->list, &dstlimit_htables);
2799 +       WRITE_UNLOCK(&dstlimit_lock);
2800 +
2801 +       return 0;
2802 +}
2803 +
2804 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
2805 +{
2806 +       return 1;
2807 +}
2808 +
2809 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
2810 +{
2811 +       return (jiffies >= he->expires);
2812 +}
2813 +
2814 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
2815 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
2816 +                                             struct dsthash_ent *he))
2817 +{
2818 +       int i;
2819 +
2820 +       IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
2821 +
2822 +       /* lock hash table and iterate over it */
2823 +       LOCK_BH(&ht->lock);
2824 +       for (i = 0; i < ht->cfg.size; i++) {
2825 +               struct dsthash_ent *dh, *n;
2826 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
2827 +                       if ((*select)(ht, dh))
2828 +                               __dsthash_free(ht, dh);
2829 +               }
2830 +       }
2831 +       UNLOCK_BH(&ht->lock);
2832 +}
2833 +
2834 +/* hash table garbage collector, run by timer */
2835 +static void htable_gc(unsigned long htlong)
2836 +{
2837 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
2838 +
2839 +       htable_selective_cleanup(ht, select_gc);
2840 +
2841 +       /* re-add the timer accordingly */
2842 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
2843 +       add_timer(&ht->timer);
2844 +}
2845 +
2846 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
2847 +{
2848 +       /* remove timer, if it is pending */
2849 +       if (timer_pending(&hinfo->timer))
2850 +               del_timer(&hinfo->timer);
2851 +
2852 +       /* remove proc entry */
2853 +       remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
2854 +
2855 +       htable_selective_cleanup(hinfo, select_all);
2856 +       vfree(hinfo);
2857 +}
2858 +
2859 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
2860 +{
2861 +       struct ipt_dstlimit_htable *hinfo;
2862 +
2863 +       READ_LOCK(&dstlimit_lock);
2864 +       list_for_each_entry(hinfo, &dstlimit_htables, list) {
2865 +               if (!strcmp(name, hinfo->pde->name)) {
2866 +                       atomic_inc(&hinfo->use);
2867 +                       READ_UNLOCK(&dstlimit_lock);
2868 +                       return hinfo;
2869 +               }
2870 +       }
2871 +       READ_UNLOCK(&dstlimit_lock);
2872 +
2873 +       return NULL;
2874 +}
2875 +
2876 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
2877 +{
2878 +       if (atomic_dec_and_test(&hinfo->use)) {
2879 +               WRITE_LOCK(&dstlimit_lock);
2880 +               list_del(&hinfo->list);
2881 +               WRITE_UNLOCK(&dstlimit_lock);
2882 +               htable_destroy(hinfo);
2883 +       }
2884 +}
2885 +
2886 +
2887 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
2888 + * see net/sched/sch_tbf.c in the linux source tree
2889 + */
2890 +
2891 +/* Rusty: This is my (non-mathematically-inclined) understanding of
2892 +   this algorithm.  The `average rate' in jiffies becomes your initial
2893 +   amount of credit `credit' and the most credit you can ever have
2894 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
2895 +   test, `cost'.
2896 +
2897 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
2898 +   If you get credit balance more than this, the extra credit is
2899 +   discarded.  Every time the match passes, you lose `cost' credits;
2900 +   if you don't have that many, the test fails.
2901 +
2902 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
2903 +
2904 +   To get the maximum range, we multiply by this factor (ie. you get N
2905 +   credits per jiffy).  We want to allow a rate as low as 1 per day
2906 +   (slowest userspace tool allows), which means
2907 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
2908 +*/
2909 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
2910 +
2911 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
2912 + * us the power of 2 below the theoretical max, so GCC simply does a
2913 + * shift. */
2914 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
2915 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
2916 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
2917 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
2918 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
2919 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
2920 +
2921 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
2922 +
2923 +/* Precision saver. */
2924 +static inline u_int32_t
2925 +user2credits(u_int32_t user)
2926 +{
2927 +       /* If multiplying would overflow... */
2928 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
2929 +               /* Divide first. */
2930 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
2931 +
2932 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
2933 +}
2934 +
2935 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
2936 +{
2937 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
2938 +                                       * CREDITS_PER_JIFFY;
2939 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
2940 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
2941 +}
2942 +
2943 +static int
2944 +dstlimit_match(const struct sk_buff *skb,
2945 +               const struct net_device *in,
2946 +               const struct net_device *out,
2947 +               const void *matchinfo,
2948 +               int offset,
2949 +               int *hotdrop)
2950 +{
2951 +       struct ipt_dstlimit_info *r = 
2952 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
2953 +       struct ipt_dstlimit_htable *hinfo = r->hinfo;
2954 +       unsigned long now = jiffies;
2955 +       struct dsthash_ent *dh;
2956 +       struct dsthash_dst dst;
2957 +
2958 +       memset(&dst, 0, sizeof(dst));
2959 +
2960 +       /* dest ip is always in hash */
2961 +       dst.dst_ip = skb->nh.iph->daddr;
2962 +
2963 +       /* source ip only if respective hashmode, otherwise set to
2964 +        * zero */
2965 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
2966 +               dst.src_ip = skb->nh.iph->saddr;
2967 +
2968 +       /* dest port only if respective mode */
2969 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
2970 +               u16 ports[2];
2971 +
2972 +               /* Must not be a fragment. */
2973 +               if (offset)
2974 +                       return 0;
2975 +
2976 +               /* Must be big enough to read ports (both UDP and TCP have
2977 +                  them at the start). */
2978 +               if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
2979 +                       /* We've been asked to examine this packet, and we
2980 +                          can't.  Hence, no choice but to drop. */
2981 +                       *hotdrop = 1;
2982 +                       return 0;
2983 +               }
2984 +
2985 +               switch (skb->nh.iph->protocol) {
2986 +                       struct tcphdr *th;
2987 +                       struct udphdr *uh;
2988 +               case IPPROTO_TCP:
2989 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
2990 +                       dst.port = th->dest;
2991 +                       break;
2992 +               case IPPROTO_UDP:
2993 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
2994 +                       dst.port = uh->dest;
2995 +                       break;
2996 +               default:
2997 +                       break;
2998 +               }
2999 +       } 
3000 +
3001 +       LOCK_BH(&hinfo->lock);
3002 +       dh = __dsthash_find(hinfo, &dst);
3003 +       if (!dh) {
3004 +               dh = __dsthash_alloc_init(hinfo, &dst);
3005 +
3006 +               if (!dh) {
3007 +                       /* enomem... don't match == DROP */
3008 +                       if (net_ratelimit())
3009 +                               printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
3010 +                       UNLOCK_BH(&hinfo->lock);
3011 +                       return 0;
3012 +               }
3013 +
3014 +               dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
3015 +
3016 +               dh->rateinfo.prev = jiffies;
3017 +               dh->rateinfo.credit = user2credits(hinfo->cfg.avg * 
3018 +                                                       hinfo->cfg.burst);
3019 +               dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
3020 +                                                       hinfo->cfg.burst);
3021 +               dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
3022 +
3023 +               UNLOCK_BH(&hinfo->lock);
3024 +               return 1;
3025 +       }
3026 +
3027 +       /* update expiration timeout */
3028 +       dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
3029 +
3030 +       rateinfo_recalc(dh, now);
3031 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
3032 +               /* We're underlimit. */
3033 +               dh->rateinfo.credit -= dh->rateinfo.cost;
3034 +               UNLOCK_BH(&hinfo->lock);
3035 +               return 1;
3036 +       }
3037 +
3038 +               UNLOCK_BH(&hinfo->lock);
3039 +
3040 +       /* default case: we're overlimit, thus don't match */
3041 +       return 0;
3042 +}
3043 +
3044 +static int
3045 +dstlimit_checkentry(const char *tablename,
3046 +                    const struct ipt_ip *ip,
3047 +                    void *matchinfo,
3048 +                    unsigned int matchsize,
3049 +                    unsigned int hook_mask)
3050 +{
3051 +       struct ipt_dstlimit_info *r = matchinfo;
3052 +
3053 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
3054 +               return 0;
3055 +
3056 +       /* Check for overflow. */
3057 +       if (r->cfg.burst == 0
3058 +           || user2credits(r->cfg.avg * r->cfg.burst) < 
3059 +                                       user2credits(r->cfg.avg)) {
3060 +               printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
3061 +                      r->cfg.avg, r->cfg.burst);
3062 +               return 0;
3063 +       }
3064 +
3065 +       if (r->cfg.mode == 0 
3066 +           || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
3067 +                         |IPT_DSTLIMIT_HASH_DIP
3068 +                         |IPT_DSTLIMIT_HASH_SIP))
3069 +               return 0;
3070 +
3071 +       if (!r->cfg.gc_interval)
3072 +               return 0;
3073 +       
3074 +       if (!r->cfg.expire)
3075 +               return 0;
3076 +
3077 +       r->hinfo = htable_find_get(r->name);
3078 +       if (!r->hinfo && (htable_create(r) != 0)) {
3079 +               return 0;
3080 +       }
3081 +
3082 +       /* Ugly hack: For SMP, we only want to use one set */
3083 +       r->u.master = r;
3084 +
3085 +       return 1;
3086 +}
3087 +
3088 +static void
3089 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
3090 +{
3091 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
3092 +
3093 +       htable_put(r->hinfo);
3094 +}
3095 +
3096 +static struct ipt_match ipt_dstlimit = { 
3097 +       .list = { .prev = NULL, .next = NULL }, 
3098 +       .name = "dstlimit", 
3099 +       .match = dstlimit_match, 
3100 +       .checkentry = dstlimit_checkentry, 
3101 +       .destroy = dstlimit_destroy,
3102 +       .me = THIS_MODULE 
3103 +};
3104 +
3105 +/* PROC stuff */
3106 +
3107 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
3108 +{
3109 +       struct proc_dir_entry *pde = s->private;
3110 +       struct ipt_dstlimit_htable *htable = pde->data;
3111 +       unsigned int *bucket;
3112 +
3113 +       LOCK_BH(&htable->lock);
3114 +       if (*pos >= htable->cfg.size)
3115 +               return NULL;
3116 +
3117 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
3118 +       if (!bucket)
3119 +               return ERR_PTR(-ENOMEM);
3120 +
3121 +       *bucket = *pos;
3122 +       return bucket;
3123 +}
3124 +
3125 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
3126 +{
3127 +       struct proc_dir_entry *pde = s->private;
3128 +       struct ipt_dstlimit_htable *htable = pde->data;
3129 +       unsigned int *bucket = (unsigned int *)v;
3130 +
3131 +       *pos = ++(*bucket);
3132 +       if (*pos >= htable->cfg.size) {
3133 +               kfree(v);
3134 +               return NULL;
3135 +       }
3136 +       return bucket;
3137 +}
3138 +
3139 +static void dl_seq_stop(struct seq_file *s, void *v)
3140 +{
3141 +       struct proc_dir_entry *pde = s->private;
3142 +       struct ipt_dstlimit_htable *htable = pde->data;
3143 +       unsigned int *bucket = (unsigned int *)v;
3144 +
3145 +       kfree(bucket);
3146 +
3147 +       UNLOCK_BH(&htable->lock);
3148 +}
3149 +
3150 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
3151 +{
3152 +       /* recalculate to show accurate numbers */
3153 +       rateinfo_recalc(ent, jiffies);
3154 +
3155 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
3156 +                       (ent->expires - jiffies)/HZ,
3157 +                       NIPQUAD(ent->dst.src_ip),
3158 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
3159 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
3160 +                       ent->rateinfo.cost);
3161 +}
3162 +
3163 +static int dl_seq_show(struct seq_file *s, void *v)
3164 +{
3165 +       struct proc_dir_entry *pde = s->private;
3166 +       struct ipt_dstlimit_htable *htable = pde->data;
3167 +       unsigned int *bucket = (unsigned int *)v;
3168 +
3169 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
3170 +                     struct dsthash_ent *, s)) {
3171 +               /* buffer was filled and unable to print that tuple */
3172 +               return 1;
3173 +       }
3174 +       return 0;
3175 +}
3176 +
3177 +static struct seq_operations dl_seq_ops = {
3178 +       .start = dl_seq_start,
3179 +       .next  = dl_seq_next,
3180 +       .stop  = dl_seq_stop,
3181 +       .show  = dl_seq_show
3182 +};
3183 +
3184 +static int dl_proc_open(struct inode *inode, struct file *file)
3185 +{
3186 +       int ret = seq_open(file, &dl_seq_ops);
3187 +
3188 +       if (!ret) {
3189 +               struct seq_file *sf = file->private_data;
3190 +               sf->private = PDE(inode);
3191 +       }
3192 +       return ret;
3193 +}
3194 +
3195 +static struct file_operations dl_file_ops = {
3196 +       .owner   = THIS_MODULE,
3197 +       .open    = dl_proc_open,
3198 +       .read    = seq_read,
3199 +       .llseek  = seq_lseek,
3200 +       .release = seq_release
3201 +};
3202 +
3203 +static int init_or_fini(int fini)
3204 +{
3205 +       int ret = 0;
3206 +
3207 +       if (fini)
3208 +               goto cleanup;
3209 +
3210 +       if (ipt_register_match(&ipt_dstlimit)) {
3211 +               ret = -EINVAL;
3212 +               goto cleanup_nothing;
3213 +       }
3214 +
3215 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
3216 +        * quite small ? */
3217 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
3218 +                                           sizeof(struct dsthash_ent), 0,
3219 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
3220 +       if (!dstlimit_cachep) {
3221 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
3222 +               ret = -ENOMEM;
3223 +               goto cleanup_unreg_match;
3224 +       }
3225 +
3226 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
3227 +       if (!dstlimit_procdir) {
3228 +               printk(KERN_ERR "Unable to create proc dir entry\n");
3229 +               ret = -ENOMEM;
3230 +               goto cleanup_free_slab;
3231 +       }
3232 +
3233 +       return ret;
3234 +
3235 +cleanup:
3236 +       remove_proc_entry("ipt_dstlimit", proc_net);
3237 +cleanup_free_slab:
3238 +       kmem_cache_destroy(dstlimit_cachep);
3239 +cleanup_unreg_match:
3240 +       ipt_unregister_match(&ipt_dstlimit);
3241 +cleanup_nothing:
3242 +       return ret;
3243 +       
3244 +}
3245 +
3246 +static int __init init(void)
3247 +{
3248 +       return init_or_fini(0);
3249 +}
3250 +
3251 +static void __exit fini(void)
3252 +{
3253 +       init_or_fini(1);
3254 +}
3255 +
3256 +module_init(init);
3257 +module_exit(fini);
3258 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_fuzzy.c
3259 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_fuzzy.c  1970-01-01 00:00:00.000000000 +0000
3260 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_fuzzy.c      2004-03-07 08:43:19.000000000 +0000
3261 @@ -0,0 +1,185 @@
3262 +/*
3263 + *  This module implements a simple TSK FLC 
3264 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
3265 + * to limit , in an adaptive and flexible way , the packet rate crossing 
3266 + * a given stream . It serves as an initial and very simple (but effective)
3267 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
3268 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
3269 + * into our code in a precise , adaptive and efficient manner. 
3270 + *  The goal is very similar to that of "limit" match , but using techniques of
3271 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
3272 + * avoiding over and undershoots - and stuff like that .
3273 + *
3274 + *
3275 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
3276 + * 2002-08-17  : Changed to eliminate floating point operations .
3277 + * 2002-08-23  : Coding style changes .
3278 +*/
3279 +
3280 +#include <linux/module.h>
3281 +#include <linux/skbuff.h>
3282 +#include <linux/ip.h>
3283 +#include <linux/random.h>
3284 +#include <net/tcp.h>
3285 +#include <linux/spinlock.h>
3286 +#include <linux/netfilter_ipv4/ip_tables.h>
3287 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
3288 +
3289 +/*
3290 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
3291 + Expressed in percentage
3292 +*/
3293 +
3294 +#define PAR_LOW                1/100
3295 +#define PAR_HIGH       1
3296 +
3297 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
3298 +
3299 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
3300 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
3301 +MODULE_LICENSE("GPL");
3302 +
3303 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
3304 +{
3305 +       if (tx >= maxi)
3306 +               return 100;
3307 +
3308 +       if (tx <= mini)
3309 +               return 0;
3310 +
3311 +       return ( (100*(tx-mini)) / (maxi-mini) );
3312 +}
3313 +
3314 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
3315 +{
3316 +       if (tx <= mini)
3317 +               return 100;
3318 +
3319 +       if (tx >= maxi)
3320 +               return 0;
3321 +
3322 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) );
3323 +}
3324 +
3325 +static int
3326 +ipt_fuzzy_match(const struct sk_buff *pskb,
3327 +              const struct net_device *in,
3328 +              const struct net_device *out,
3329 +              const void *matchinfo,
3330 +              int offset,
3331 +              int *hotdrop)
3332 +{
3333 +       /* From userspace */
3334 +       
3335 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
3336 +
3337 +       u_int8_t random_number;
3338 +       unsigned long amount;
3339 +       u_int8_t howhigh, howlow;
3340 +       
3341 +
3342 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
3343 +
3344 +       info->bytes_total += pskb->len;
3345 +       info->packets_total++;
3346 +
3347 +       info->present_time = jiffies;
3348 +       
3349 +       if (info->present_time >= info->previous_time)
3350 +               amount = info->present_time - info->previous_time;
3351 +       else { 
3352 +               /* There was a transition : I choose to re-sample 
3353 +                  and keep the old acceptance rate...
3354 +               */
3355 +
3356 +               amount = 0;
3357 +               info->previous_time = info->present_time;
3358 +               info->bytes_total = info->packets_total = 0;
3359 +       };
3360 +       
3361 +       if (amount > HZ/10) /* More than 100 ms elapsed ... */
3362 +       {
3363 +
3364 +               info->mean_rate = (u_int32_t) ((HZ*info->packets_total)  \
3365 +                                       / amount );
3366 +
3367 +               info->previous_time = info->present_time;
3368 +               info->bytes_total = info->packets_total = 0;
3369 +
3370 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
3371 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
3372 +
3373 +               info->acceptance_rate = (u_int8_t) \
3374 +                          (howhigh*PAR_LOW + PAR_HIGH*howlow);
3375 +
3376 +               /* In fact , the above defuzzification would require a denominator
3377 +                  proportional to (howhigh+howlow) but , in this particular case ,
3378 +                  that expression is constant .
3379 +                  An imediate consequence is that it isn't necessary to call 
3380 +                  both mf_high and mf_low - but to keep things understandable ,
3381 +                  I did so .  */ 
3382 +
3383 +       }
3384 +       
3385 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
3386 +
3387 +
3388 +       if ( info->acceptance_rate < 100 )
3389 +       {                
3390 +               get_random_bytes((void *)(&random_number), 1);
3391 +
3392 +               /*  If within the acceptance , it can pass => don't match */
3393 +               if (random_number <= (255 * info->acceptance_rate) / 100)
3394 +                       return 0;
3395 +               else
3396 +                       return 1; /* It can't pass ( It matches ) */
3397 +       } ;
3398 +
3399 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
3400 +       
3401 +}
3402 +
3403 +static int
3404 +ipt_fuzzy_checkentry(const char *tablename,
3405 +                  const struct ipt_ip *e,
3406 +                  void *matchinfo,
3407 +                  unsigned int matchsize,
3408 +                  unsigned int hook_mask)
3409 +{
3410 +       
3411 +       const struct ipt_fuzzy_info *info = matchinfo;
3412 +
3413 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
3414 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
3415 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
3416 +               return 0;
3417 +       }
3418 +
3419 +       if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
3420 +           || (info->minimum_rate >= info->maximum_rate )) {
3421 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
3422 +               return 0;
3423 +       }
3424 +
3425 +       return 1;
3426 +}
3427 +
3428 +static struct ipt_match ipt_fuzzy_reg = { 
3429 +       .name = "fuzzy",
3430 +       .match = ipt_fuzzy_match,
3431 +       .checkentry = ipt_fuzzy_checkentry,
3432 +       .me = THIS_MODULE
3433 +};
3434 +
3435 +static int __init init(void)
3436 +{
3437 +       return ipt_register_match(&ipt_fuzzy_reg);
3438 +}
3439 +
3440 +static void __exit fini(void)
3441 +{
3442 +       ipt_unregister_match(&ipt_fuzzy_reg);
3443 +}
3444 +
3445 +module_init(init);
3446 +module_exit(fini);
3447 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_ipv4options.c
3448 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_ipv4options.c    1970-01-01 00:00:00.000000000 +0000
3449 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_ipv4options.c        2004-03-07 08:43:20.000000000 +0000
3450 @@ -0,0 +1,172 @@
3451 +/*
3452 +  This is a module which is used to match ipv4 options.
3453 +  This file is distributed under the terms of the GNU General Public
3454 +  License (GPL). Copies of the GPL can be obtained from:
3455 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
3456 +
3457 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
3458 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
3459 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
3460 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
3461 +  19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
3462 +*/
3463 +
3464 +#include <linux/module.h>
3465 +#include <linux/skbuff.h>
3466 +#include <net/ip.h>
3467 +
3468 +#include <linux/netfilter_ipv4/ip_tables.h>
3469 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
3470 +
3471 +MODULE_LICENSE("GPL");
3472 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
3473 +
3474 +static int
3475 +match(const struct sk_buff *skb,
3476 +      const struct net_device *in,
3477 +      const struct net_device *out,
3478 +      const void *matchinfo,
3479 +      int offset,
3480 +      int *hotdrop)
3481 +{
3482 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
3483 +       const struct iphdr *iph = skb->nh.iph;
3484 +       const struct ip_options *opt;
3485 +
3486 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
3487 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
3488 +
3489 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
3490 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3491 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3492 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3493 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3494 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
3495 +                       return 0;
3496 +               return 1;
3497 +       }
3498 +       else {
3499 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
3500 +                       /* there are options, and we don't need to care which one */
3501 +                       return 1;
3502 +               else {
3503 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
3504 +                               /* there are options but we don't want any ! */
3505 +                               return 0;
3506 +               }
3507 +       }
3508 +
3509 +       opt = &(IPCB(skb)->opt);
3510 +
3511 +       /* source routing */
3512 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
3513 +               if (!((opt->srr) & (opt->is_strictroute)))
3514 +                       return 0;
3515 +       }
3516 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
3517 +               if (!((opt->srr) & (!opt->is_strictroute)))
3518 +                       return 0;
3519 +       }
3520 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
3521 +               if (opt->srr)
3522 +                       return 0;
3523 +       }
3524 +       /* record route */
3525 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
3526 +               if (!opt->rr)
3527 +                       return 0;
3528 +       }
3529 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
3530 +               if (opt->rr)
3531 +                       return 0;
3532 +       }
3533 +       /* timestamp */
3534 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
3535 +               if (!opt->ts)
3536 +                       return 0;
3537 +       }
3538 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
3539 +               if (opt->ts)
3540 +                       return 0;
3541 +       }
3542 +       /* router-alert option  */
3543 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
3544 +               if (!opt->router_alert)
3545 +                       return 0;
3546 +       }
3547 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
3548 +               if (opt->router_alert)
3549 +                       return 0;
3550 +       }
3551 +
3552 +       /* we match ! */
3553 +       return 1;
3554 +}
3555 +
3556 +static int
3557 +checkentry(const char *tablename,
3558 +          const struct ipt_ip *ip,
3559 +          void *matchinfo,
3560 +          unsigned int matchsize,
3561 +          unsigned int hook_mask)
3562 +{
3563 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
3564 +       /* Check the size */
3565 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
3566 +               return 0;
3567 +       /* Now check the coherence of the data ... */
3568 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
3569 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
3570 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
3571 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
3572 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
3573 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
3574 +               return 0; /* opposites */
3575 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
3576 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3577 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3578 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3579 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3580 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
3581 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
3582 +               return 0; /* opposites */
3583 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
3584 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
3585 +               return 0; /* cannot match in the same time loose and strict source routing */
3586 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3587 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
3588 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
3589 +               return 0; /* opposites */
3590 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
3591 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
3592 +               return 0; /* opposites */
3593 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
3594 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
3595 +               return 0; /* opposites */
3596 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
3597 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
3598 +               return 0; /* opposites */
3599 +
3600 +       /* everything looks ok. */
3601 +       return 1;
3602 +}
3603 +
3604 +static struct ipt_match ipv4options_match = { 
3605 +       .name = "ipv4options",
3606 +       .match = match,
3607 +       .checkentry = checkentry,
3608 +       .me = THIS_MODULE
3609 +};
3610 +
3611 +static int __init init(void)
3612 +{
3613 +       return ipt_register_match(&ipv4options_match);
3614 +}
3615 +
3616 +static void __exit fini(void)
3617 +{
3618 +       ipt_unregister_match(&ipv4options_match);
3619 +}
3620 +
3621 +module_init(init);
3622 +module_exit(fini);
3623 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_mport.c
3624 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_mport.c  1970-01-01 00:00:00.000000000 +0000
3625 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_mport.c      2004-03-07 08:43:23.000000000 +0000
3626 @@ -0,0 +1,116 @@
3627 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
3628 +   the same place so we can treat them as equal. */
3629 +#include <linux/module.h>
3630 +#include <linux/types.h>
3631 +#include <linux/udp.h>
3632 +#include <linux/skbuff.h>
3633 +
3634 +#include <linux/netfilter_ipv4/ipt_mport.h>
3635 +#include <linux/netfilter_ipv4/ip_tables.h>
3636 +
3637 +MODULE_LICENSE("GPL");
3638 +
3639 +#if 0
3640 +#define duprintf(format, args...) printk(format , ## args)
3641 +#else
3642 +#define duprintf(format, args...)
3643 +#endif
3644 +
3645 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
3646 +static inline int
3647 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
3648 +{
3649 +       unsigned int i;
3650 +        unsigned int m;
3651 +        u_int16_t pflags = minfo->pflags;
3652 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
3653 +                u_int16_t s, e;
3654 +
3655 +                if (pflags & m
3656 +                    && minfo->ports[i] == 65535)
3657 +                        return 0;
3658 +
3659 +                s = minfo->ports[i];
3660 +
3661 +                if (pflags & m) {
3662 +                        e = minfo->ports[++i];
3663 +                        m <<= 1;
3664 +                } else
3665 +                        e = s;
3666 +
3667 +                if (minfo->flags & IPT_MPORT_SOURCE
3668 +                    && src >= s && src <= e)
3669 +                        return 1;
3670 +
3671 +               if (minfo->flags & IPT_MPORT_DESTINATION
3672 +                   && dst >= s && dst <= e)
3673 +                       return 1;
3674 +       }
3675 +
3676 +       return 0;
3677 +}
3678 +
3679 +static int
3680 +match(const struct sk_buff *skb,
3681 +      const struct net_device *in,
3682 +      const struct net_device *out,
3683 +      const void *matchinfo,
3684 +      int offset,
3685 +      int *hotdrop)
3686 +{
3687 +       u16 ports[2];
3688 +       const struct ipt_mport *minfo = matchinfo;
3689 +
3690 +       if (offset)
3691 +               return 0;
3692 +
3693 +       /* Must be big enough to read ports (both UDP and TCP have
3694 +           them at the start). */
3695 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
3696 +               /* We've been asked to examine this packet, and we
3697 +                  can't.  Hence, no choice but to drop. */
3698 +                       duprintf("ipt_multiport:"
3699 +                                " Dropping evil offset=0 tinygram.\n");
3700 +                       *hotdrop = 1;
3701 +                       return 0;
3702 +       }
3703 +
3704 +       return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
3705 +}
3706 +
3707 +/* Called when user tries to insert an entry of this type. */
3708 +static int
3709 +checkentry(const char *tablename,
3710 +          const struct ipt_ip *ip,
3711 +          void *matchinfo,
3712 +          unsigned int matchsize,
3713 +          unsigned int hook_mask)
3714 +{
3715 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
3716 +               return 0;
3717 +
3718 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
3719 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
3720 +               && !(ip->invflags & IPT_INV_PROTO)
3721 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
3722 +}
3723 +
3724 +static struct ipt_match mport_match = { 
3725 +       .name = "mport",
3726 +       .match = &match,
3727 +       .checkentry = &checkentry,
3728 +       .me = THIS_MODULE
3729 +};
3730 +
3731 +static int __init init(void)
3732 +{
3733 +       return ipt_register_match(&mport_match);
3734 +}
3735 +
3736 +static void __exit fini(void)
3737 +{
3738 +       ipt_unregister_match(&mport_match);
3739 +}
3740 +
3741 +module_init(init);
3742 +module_exit(fini);
3743 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_nth.c
3744 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_nth.c    1970-01-01 00:00:00.000000000 +0000
3745 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_nth.c        2004-03-07 08:43:24.000000000 +0000
3746 @@ -0,0 +1,166 @@
3747 +/*
3748 +  This is a module which is used for match support for every Nth packet
3749 +  This file is distributed under the terms of the GNU General Public
3750 +  License (GPL). Copies of the GPL can be obtained from:
3751 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
3752 +
3753 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
3754 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
3755 +        * added support for multiple counters
3756 +        * added support for matching on individual packets
3757 +          in the counter cycle
3758 +  2004-02-19 Harald Welte <laforge@netfilter.org>
3759 +       * port to 2.6.x
3760 +
3761 +*/
3762 +
3763 +#include <linux/module.h>
3764 +#include <linux/skbuff.h>
3765 +#include <linux/ip.h>
3766 +#include <net/tcp.h>
3767 +#include <linux/spinlock.h>
3768 +#include <linux/netfilter_ipv4/ip_tables.h>
3769 +#include <linux/netfilter_ipv4/ipt_nth.h>
3770 +
3771 +MODULE_LICENSE("GPL");
3772 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
3773 +
3774 +/*
3775 + * State information.
3776 + */
3777 +struct state {
3778 +       spinlock_t lock;
3779 +       u_int16_t number;
3780 +};
3781 +
3782 +static struct state states[IPT_NTH_NUM_COUNTERS];
3783 +
3784 +static int
3785 +ipt_nth_match(const struct sk_buff *pskb,
3786 +             const struct net_device *in,
3787 +             const struct net_device *out,
3788 +             const void *matchinfo,
3789 +             int offset,
3790 +             int *hotdrop)
3791 +{
3792 +       /* Parameters from userspace */
3793 +       const struct ipt_nth_info *info = matchinfo;
3794 +        unsigned counter = info->counter;
3795 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
3796 +       {
3797 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3798 +               return 0;
3799 +        };
3800 +
3801 +        spin_lock(&states[counter].lock);
3802 +
3803 +        /* Are we matching every nth packet?*/
3804 +        if (info->packet == 0xFF)
3805 +        {
3806 +               /* We're matching every nth packet and only every nth packet*/
3807 +               /* Do we match or invert match? */
3808 +               if (info->not == 0)
3809 +               {
3810 +                       if (states[counter].number == 0)
3811 +                       {
3812 +                               ++states[counter].number;
3813 +                               goto match;
3814 +                       }
3815 +                       if (states[counter].number >= info->every)
3816 +                               states[counter].number = 0; /* reset the counter */
3817 +                       else
3818 +                               ++states[counter].number;
3819 +                       goto dontmatch;
3820 +               }
3821 +               else
3822 +               {
3823 +                       if (states[counter].number == 0)
3824 +                       {
3825 +                               ++states[counter].number;
3826 +                               goto dontmatch;
3827 +                       }
3828 +                       if (states[counter].number >= info->every)
3829 +                               states[counter].number = 0;
3830 +                       else
3831 +                               ++states[counter].number;
3832 +                       goto match;
3833 +               }
3834 +        }
3835 +        else
3836 +        {
3837 +               /* We're using the --packet, so there must be a rule for every value */
3838 +               if (states[counter].number == info->packet)
3839 +               {
3840 +                       /* only increment the counter when a match happens */
3841 +                       if (states[counter].number >= info->every)
3842 +                               states[counter].number = 0; /* reset the counter */
3843 +                       else
3844 +                               ++states[counter].number;
3845 +                       goto match;
3846 +               }
3847 +               else
3848 +                       goto dontmatch;
3849 +       }
3850 +
3851 + dontmatch:
3852 +       /* don't match */
3853 +       spin_unlock(&states[counter].lock);
3854 +       return 0;
3855 +
3856 + match:
3857 +       spin_unlock(&states[counter].lock);
3858 +       return 1;
3859 +}
3860 +
3861 +static int
3862 +ipt_nth_checkentry(const char *tablename,
3863 +                  const struct ipt_ip *e,
3864 +                  void *matchinfo,
3865 +                  unsigned int matchsize,
3866 +                  unsigned int hook_mask)
3867 +{
3868 +       /* Parameters from userspace */
3869 +       const struct ipt_nth_info *info = matchinfo;
3870 +        unsigned counter = info->counter;
3871 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
3872 +       {
3873 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3874 +                       return 0;
3875 +               };
3876 +
3877 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
3878 +               printk("nth: matchsize %u != %u\n", matchsize,
3879 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
3880 +               return 0;
3881 +       }
3882 +
3883 +       states[counter].number = info->startat;
3884 +
3885 +       return 1;
3886 +}
3887 +
3888 +static struct ipt_match ipt_nth_reg = { 
3889 +       .name = "nth",
3890 +       .match = ipt_nth_match,
3891 +       .checkentry = ipt_nth_checkentry,
3892 +       .me = THIS_MODULE
3893 +};
3894 +
3895 +static int __init init(void)
3896 +{
3897 +       unsigned counter;
3898 +
3899 +       memset(&states, 0, sizeof(states));
3900 +        for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
3901 +               spin_lock_init(&(states[counter].lock));
3902 +
3903 +       return ipt_register_match(&ipt_nth_reg);
3904 +}
3905 +
3906 +static void __exit fini(void)
3907 +{
3908 +       ipt_unregister_match(&ipt_nth_reg);
3909 +}
3910 +
3911 +module_init(init);
3912 +module_exit(fini);
3913 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_quota.c
3914 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_quota.c  1970-01-01 00:00:00.000000000 +0000
3915 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_quota.c      2004-03-07 08:43:28.000000000 +0000
3916 @@ -0,0 +1,91 @@
3917 +/* 
3918 + * netfilter module to enforce network quotas
3919 + *
3920 + * Sam Johnston <samj@samj.net>
3921 + */
3922 +#include <linux/module.h>
3923 +#include <linux/skbuff.h>
3924 +#include <linux/spinlock.h>
3925 +#include <linux/interrupt.h>
3926 +
3927 +#include <linux/netfilter_ipv4/ip_tables.h>
3928 +#include <linux/netfilter_ipv4/ipt_quota.h>
3929 +
3930 +MODULE_LICENSE("GPL");
3931 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
3932 +
3933 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
3934 +
3935 +static int
3936 +match(const struct sk_buff *skb,
3937 +      const struct net_device *in,
3938 +      const struct net_device *out,
3939 +      const void *matchinfo,
3940 +      int offset, int *hotdrop)
3941 +{
3942 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
3943 +       unsigned int datalen;
3944 +
3945 +       if (skb->len < sizeof(struct iphdr))
3946 +               return NF_ACCEPT;
3947 +       
3948 +       datalen = skb->len - skb->nh.iph->ihl*4;
3949 +
3950 +        spin_lock_bh(&quota_lock);
3951 +
3952 +        if (q->quota >= datalen) {
3953 +                /* we can afford this one */
3954 +                q->quota -= datalen;
3955 +                spin_unlock_bh(&quota_lock);
3956 +
3957 +#ifdef DEBUG_IPT_QUOTA
3958 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
3959 +#endif
3960 +                return 1;
3961 +        }
3962 +
3963 +        /* so we do not allow even small packets from now on */
3964 +        q->quota = 0;
3965 +
3966 +#ifdef DEBUG_IPT_QUOTA
3967 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
3968 +#endif
3969 +
3970 +        spin_unlock_bh(&quota_lock);
3971 +        return 0;
3972 +}
3973 +
3974 +static int
3975 +checkentry(const char *tablename,
3976 +           const struct ipt_ip *ip,
3977 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
3978 +{
3979 +        /* TODO: spinlocks? sanity checks? */
3980 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
3981 +                return 0;
3982 +
3983 +        return 1;
3984 +}
3985 +
3986 +static struct ipt_match quota_match = {
3987 +       .name = "quota",
3988 +       .match = match,
3989 +       .checkentry = checkentry,
3990 +       .me = THIS_MODULE
3991 +};
3992 +
3993 +static int __init
3994 +init(void)
3995 +{
3996 +        return ipt_register_match(&quota_match);
3997 +}
3998 +
3999 +static void __exit
4000 +fini(void)
4001 +{
4002 +        ipt_unregister_match(&quota_match);
4003 +}
4004 +
4005 +module_init(init);
4006 +module_exit(fini);
4007 +
4008 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_realm.c
4009 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_realm.c  1970-01-01 00:00:00.000000000 +0000
4010 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_realm.c      2004-03-07 08:43:30.000000000 +0000
4011 @@ -0,0 +1,78 @@
4012 +/* IP tables module for matching the routing realm
4013 + *
4014 + * $Id$
4015 + *
4016 + * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
4017 + *
4018 + * This program is free software; you can redistribute it and/or modify
4019 + * it under the terms of the GNU General Public License version 2 as
4020 + * published by the Free Software Foundation.
4021 + */
4022 +
4023 +#include <linux/module.h>
4024 +#include <linux/skbuff.h>
4025 +#include <linux/netdevice.h>
4026 +#include <net/route.h>
4027 +
4028 +#include <linux/netfilter_ipv4/ipt_realm.h>
4029 +#include <linux/netfilter_ipv4/ip_tables.h>
4030 +
4031 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
4032 +MODULE_LICENSE("GPL");
4033 +
4034 +static int
4035 +match(const struct sk_buff *skb,
4036 +      const struct net_device *in,
4037 +      const struct net_device *out,
4038 +      const void *matchinfo,
4039 +      int offset,
4040 +      int *hotdrop)
4041 +{
4042 +       const struct ipt_realm_info *info = matchinfo;
4043 +       struct dst_entry *dst = skb->dst;
4044 +    
4045 +       if (!dst)
4046 +               return 0;
4047 +
4048 +       return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
4049 +}
4050 +
4051 +static int check(const char *tablename,
4052 +                 const struct ipt_ip *ip,
4053 +                 void *matchinfo,
4054 +                 unsigned int matchsize,
4055 +                 unsigned int hook_mask)
4056 +{
4057 +       if (hook_mask
4058 +           & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
4059 +               (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
4060 +               printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
4061 +                      "LOCAL_IN or FORWARD.\n");
4062 +               return 0;
4063 +       }
4064 +
4065 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
4066 +               return 0;
4067 +
4068 +       return 1;
4069 +}
4070 +
4071 +static struct ipt_match realm_match = {
4072 +       .name = "realm",
4073 +       .match = match, 
4074 +       .checkentry = check,
4075 +       .me = THIS_MODULE
4076 +};
4077 +
4078 +static int __init init(void)
4079 +{
4080 +       return ipt_register_match(&realm_match);
4081 +}
4082 +
4083 +static void __exit fini(void)
4084 +{
4085 +       ipt_unregister_match(&realm_match);
4086 +}
4087 +
4088 +module_init(init);
4089 +module_exit(fini);
4090 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_sctp.c
4091 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_sctp.c   1970-01-01 00:00:00.000000000 +0000
4092 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_sctp.c       2004-03-07 08:43:31.000000000 +0000
4093 @@ -0,0 +1,197 @@
4094 +#include <linux/module.h>
4095 +#include <linux/skbuff.h>
4096 +#include <net/ip.h>
4097 +#include <linux/sctp.h>
4098 +
4099 +#include <linux/netfilter_ipv4/ip_tables.h>
4100 +#include <linux/netfilter_ipv4/ipt_sctp.h>
4101 +
4102 +#if 1
4103 +#define duprintf(format, args...) printk(format , ## args)
4104 +#else
4105 +#define duprintf(format, args...)
4106 +#endif
4107 +
4108 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
4109 +                                             || (!!((invflag) & (option)) ^ (cond)))
4110 +
4111 +static int
4112 +match_flags(const struct ipt_sctp_flag_info *flag_info,
4113 +           const int flag_count,
4114 +           u_int8_t chunktype,
4115 +           u_int8_t chunkflags)
4116 +{
4117 +       int i;
4118 +
4119 +       for (i = 0; i < flag_count; i++) {
4120 +               if (flag_info[i].chunktype == chunktype) {
4121 +                       return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
4122 +               }
4123 +       }
4124 +
4125 +       return 1;
4126 +}
4127 +
4128 +static int
4129 +match_packet(const struct sk_buff *skb,
4130 +            const u_int32_t *chunkmap,
4131 +            int chunk_match_type,
4132 +            const struct ipt_sctp_flag_info *flag_info,
4133 +            const int flag_count,
4134 +            int *hotdrop)
4135 +{
4136 +       int offset;
4137 +       u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
4138 +       sctp_chunkhdr_t sch;
4139 +
4140 +       if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
4141 +               SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
4142 +       }
4143 +
4144 +       offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
4145 +       do {
4146 +               if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
4147 +                       duprintf("Dropping invalid SCTP packet.\n");
4148 +                       *hotdrop = 1;
4149 +                       return 0;
4150 +               }
4151 +
4152 +//             duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", 
4153 +//                             ++i, offset, sch.type, htons(sch.length), sch.flags);
4154 +
4155 +               offset += (htons(sch.length) + 3) & ~3;
4156 +
4157 +               duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
4158 +
4159 +               if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
4160 +                       switch (chunk_match_type) {
4161 +                       case SCTP_CHUNK_MATCH_ANY:
4162 +                               if (match_flags(flag_info, flag_count, 
4163 +                                       sch.type, sch.flags)) {
4164 +                                       return 1;
4165 +                               }
4166 +                               break;
4167 +
4168 +                       case SCTP_CHUNK_MATCH_ALL:
4169 +                               if (match_flags(flag_info, flag_count, 
4170 +                                       sch.type, sch.flags)) {
4171 +                                       SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
4172 +                               }
4173 +                               break;
4174 +
4175 +                       case SCTP_CHUNK_MATCH_ONLY:
4176 +                               if (!match_flags(flag_info, flag_count, 
4177 +                                       sch.type, sch.flags)) {
4178 +                                       return 0;
4179 +                               }
4180 +                               break;
4181 +                       }
4182 +               } else {
4183 +                       switch (chunk_match_type) {
4184 +                       case SCTP_CHUNK_MATCH_ONLY:
4185 +                               return 0;
4186 +                       }
4187 +               }
4188 +       } while (offset < skb->len);
4189 +
4190 +       switch (chunk_match_type) {
4191 +       case SCTP_CHUNK_MATCH_ALL:
4192 +               return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
4193 +       case SCTP_CHUNK_MATCH_ANY:
4194 +               return 0;
4195 +       case SCTP_CHUNK_MATCH_ONLY:
4196 +               return 1;
4197 +       }
4198 +
4199 +       /* This will never be reached, but required to stop compiler whine */
4200 +       return 0;
4201 +}
4202 +
4203 +static int
4204 +match(const struct sk_buff *skb,
4205 +      const struct net_device *in,
4206 +      const struct net_device *out,
4207 +      const void *matchinfo,
4208 +      int offset,
4209 +      int *hotdrop)
4210 +{
4211 +       const struct ipt_sctp_info *info;
4212 +       sctp_sctphdr_t sh;
4213 +
4214 +       info = (const struct ipt_sctp_info *)matchinfo;
4215 +
4216 +       if (offset) {
4217 +               duprintf("Dropping non-first fragment.. FIXME\n");
4218 +               return 0;
4219 +       }
4220 +       
4221 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
4222 +               duprintf("Dropping evil TCP offset=0 tinygram.\n");
4223 +               *hotdrop = 1;
4224 +               return 0;
4225 +               }
4226 +       duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
4227 +
4228 +       return  SCCHECK(((ntohs(sh.source) >= info->spts[0]) 
4229 +                       && (ntohs(sh.source) <= info->spts[1])), 
4230 +                       IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
4231 +               && SCCHECK(((ntohs(sh.dest) >= info->dpts[0]) 
4232 +                       && (ntohs(sh.dest) <= info->dpts[1])), 
4233 +                       IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
4234 +               && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
4235 +                                       info->flag_info, info->flag_count, 
4236 +                                       hotdrop),
4237 +                          IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
4238 +}
4239 +
4240 +static int
4241 +checkentry(const char *tablename,
4242 +          const struct ipt_ip *ip,
4243 +          void *matchinfo,
4244 +          unsigned int matchsize,
4245 +          unsigned int hook_mask)
4246 +{
4247 +       const struct ipt_sctp_info *info;
4248 +
4249 +       info = (const struct ipt_sctp_info *)matchinfo;
4250 +
4251 +       return ip->proto == IPPROTO_SCTP
4252 +               && !(ip->invflags & IPT_INV_PROTO)
4253 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
4254 +               && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
4255 +               && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
4256 +               && !(info->invflags & ~info->flags)
4257 +               && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || 
4258 +                       (info->chunk_match_type &
4259 +                               (SCTP_CHUNK_MATCH_ALL 
4260 +                               | SCTP_CHUNK_MATCH_ANY
4261 +                               | SCTP_CHUNK_MATCH_ONLY)));
4262 +}
4263 +
4264 +static struct ipt_match sctp_match = 
4265 +{ 
4266 +       .list = { NULL, NULL},
4267 +       .name = "sctp",
4268 +       .match = &match,
4269 +       .checkentry = &checkentry,
4270 +       .destroy = NULL,
4271 +       .me = THIS_MODULE
4272 +};
4273 +
4274 +static int __init init(void)
4275 +{
4276 +       return ipt_register_match(&sctp_match);
4277 +}
4278 +
4279 +static void __exit fini(void)
4280 +{
4281 +       ipt_unregister_match(&sctp_match);
4282 +}
4283 +
4284 +module_init(init);
4285 +module_exit(fini);
4286 +
4287 +MODULE_LICENSE("GPL");
4288 +MODULE_AUTHOR("Kiran Kumar Immidi");
4289 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
4290 +
4291 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_state.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_state.c
4292 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_state.c  2004-03-04 06:17:10.000000000 +0000
4293 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_state.c      2004-03-07 08:43:29.000000000 +0000
4294 @@ -30,7 +30,9 @@
4295         enum ip_conntrack_info ctinfo;
4296         unsigned int statebit;
4297  
4298 -       if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
4299 +       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
4300 +               statebit = IPT_STATE_UNTRACKED;
4301 +       else if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
4302                 statebit = IPT_STATE_INVALID;
4303         else
4304                 statebit = IPT_STATE_BIT(ctinfo);
4305 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.4-rc2/net/ipv4/netfilter/ipt_u32.c
4306 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/ipt_u32.c    1970-01-01 00:00:00.000000000 +0000
4307 +++ linux-2.6.4-rc2/net/ipv4/netfilter/ipt_u32.c        2004-03-07 08:44:17.000000000 +0000
4308 @@ -0,0 +1,211 @@
4309 +/* Kernel module to match u32 packet content. */
4310 +
4311 +/* 
4312 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
4313 +have specified values.  The specification of what to extract is general 
4314 +enough to find data at given offsets from tcp headers or payloads.
4315 +
4316 + --u32 tests
4317 + The argument amounts to a program in a small language described below.
4318 + tests := location = value |  tests && location = value
4319 + value := range | value , range
4320 + range := number | number : number
4321 +  a single number, n, is interpreted the same as n:n
4322 +  n:m is interpreted as the range of numbers >=n and <=m
4323 + location := number | location operator number
4324 + operator := & | << | >> | @
4325 +
4326 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
4327 + membership operator and the value syntax describes a set.  The @ operator
4328 + is what allows moving to the next header and is described further below.
4329 +
4330 + *** Until I can find out how to avoid it, there are some artificial limits
4331 + on the size of the tests:
4332 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
4333 + - no more than 10 ranges (and 9 commas) per value
4334 + - no more than 10 numbers (and 9 operators) per location
4335 +
4336 + To describe the meaning of location, imagine the following machine that
4337 + interprets it.  There are three registers:
4338 +  A is of type char*, initially the address of the IP header
4339 +  B and C are unsigned 32 bit integers, initially zero
4340 +
4341 +  The instructions are:
4342 +   number      B = number;
4343 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
4344 +   &number     C = C&number
4345 +   <<number    C = C<<number
4346 +   >>number    C = C>>number
4347 +   @number     A = A+C; then do the instruction number
4348 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
4349 +  Otherwise the result of the computation is the final value of C.
4350 +
4351 + Whitespace is allowed but not required in the tests.
4352 + However the characters that do occur there are likely to require
4353 + shell quoting, so it's a good idea to enclose the arguments in quotes.
4354 +
4355 +Example:
4356 + match IP packets with total length >= 256
4357 + The IP header contains a total length field in bytes 2-3.
4358 + --u32 "0&0xFFFF=0x100:0xFFFF" 
4359 + read bytes 0-3
4360 + AND that with FFFF (giving bytes 2-3),
4361 + and test whether that's in the range [0x100:0xFFFF]
4362 +
4363 +Example: (more realistic, hence more complicated)
4364 + match icmp packets with icmp type 0
4365 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
4366 + --u32 "6&0xFF=1 && ...
4367 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
4368 + Next test that it's not a fragment.
4369 +  (If so it might be part of such a packet but we can't always tell.)
4370 +  n.b. This test is generally needed if you want to match anything
4371 +  beyond the IP header.
4372 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
4373 + packet (not a fragment).  Alternatively, you can allow first fragments
4374 + by only testing the last 5 bits of byte 6.
4375 + ... 4&0x3FFF=0 && ...
4376 + Last test: the first byte past the IP header (the type) is 0
4377 + This is where we have to use the @syntax.  The length of the IP header
4378 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
4379 + IP header itself.
4380 + ... 0>>22&0x3C@0>>24=0"
4381 + The first 0 means read bytes 0-3,
4382 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
4383 +   the first byte, so only 22 bits is four times that plus a few more bits.
4384 + &3C then eliminates the two extra bits on the right and the first four 
4385 + bits of the first byte.
4386 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
4387 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
4388 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
4389 + @ means to use this number as a new offset into the packet, and read
4390 + four bytes starting from there.  This is the first 4 bytes of the icmp
4391 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
4392 + the value 24 to the right to throw out all but the first byte and compare
4393 + the result with 0.
4394 +
4395 +Example: 
4396 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
4397 + First we test that the packet is a tcp packet (similar to icmp).
4398 + --u32 "6&0xFF=6 && ...
4399 + Next, test that it's not a fragment (same as above).
4400 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
4401 + 0>>22&3C as above computes the number of bytes in the IP header.
4402 + @ makes this the new offset into the packet, which is the start of the
4403 + tcp header.  The length of the tcp header (again in 32 bit words) is
4404 + the left half of byte 12 of the tcp header.  The 12>>26&3C
4405 + computes this length in bytes (similar to the IP header before).
4406 + @ makes this the new offset, which is the start of the tcp payload.
4407 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
4408 + result is any of 1, 2, 5 or 8
4409 +*/
4410 +
4411 +#include <linux/module.h>
4412 +#include <linux/skbuff.h>
4413 +
4414 +#include <linux/netfilter_ipv4/ipt_u32.h>
4415 +#include <linux/netfilter_ipv4/ip_tables.h>
4416 +
4417 +/* #include <asm-i386/timex.h> for timing */
4418 +
4419 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
4420 +MODULE_DESCRIPTION("IP tables u32 matching module");
4421 +MODULE_LICENSE("GPL");
4422 +
4423 +static int
4424 +match(const struct sk_buff *skb,
4425 +      const struct net_device *in,
4426 +      const struct net_device *out,
4427 +      const void *matchinfo,
4428 +      int offset,
4429 +      const void *hdr,
4430 +      u_int16_t datalen,
4431 +      int *hotdrop)
4432 +{
4433 +       const struct ipt_u32 *data = matchinfo;
4434 +       int testind, i;
4435 +       unsigned char* origbase = (char*)skb->nh.iph;
4436 +       unsigned char* base = origbase;
4437 +       unsigned char* head = skb->head;
4438 +       unsigned char* end = skb->end;
4439 +       int nnums, nvals;
4440 +       u_int32_t pos, val;
4441 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
4442 +          cycles1 = get_cycles(); */
4443 +
4444 +       for (testind=0; testind < data->ntests; testind++) {
4445 +               base = origbase; /* reset for each test */
4446 +               pos = data->tests[testind].location[0].number;
4447 +               if (base+pos+3 > end || base+pos < head) 
4448 +                       return 0;
4449 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
4450 +                       (base[pos+2]<<8) + base[pos+3];
4451 +               nnums = data->tests[testind].nnums;
4452 +               for (i=1; i < nnums; i++) {
4453 +                       u_int32_t number = data->tests[testind].location[i].number;
4454 +                       switch (data->tests[testind].location[i].nextop) {
4455 +                       case IPT_U32_AND: 
4456 +                               val = val & number; 
4457 +                               break;
4458 +                       case IPT_U32_LEFTSH: 
4459 +                               val = val << number;
4460 +                               break;
4461 +                       case IPT_U32_RIGHTSH: 
4462 +                               val = val >> number; 
4463 +                               break;
4464 +                       case IPT_U32_AT:
4465 +                               base = base + val;
4466 +                               pos = number;
4467 +                               if (base+pos+3 > end || base+pos < head) 
4468 +                                       return 0;
4469 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
4470 +                                       (base[pos+2]<<8) + base[pos+3];
4471 +                               break;
4472 +                       }
4473 +               }
4474 +               nvals = data->tests[testind].nvalues;
4475 +               for (i=0; i < nvals; i++) {
4476 +                       if ((data->tests[testind].value[i].min <= val) &&
4477 +                           (val <= data->tests[testind].value[i].max)) {
4478 +                               break;
4479 +                       }
4480 +               }
4481 +               if (i >= data->tests[testind].nvalues) {
4482 +                       /* cycles2 = get_cycles(); 
4483 +                          printk("failed %d in %d cycles\n", testind, 
4484 +                                 cycles2-cycles1); */
4485 +                       return 0;
4486 +               }
4487 +       }
4488 +       /* cycles2 = get_cycles();
4489 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
4490 +       return 1;
4491 +}
4492 +
4493 +static int
4494 +checkentry(const char *tablename,
4495 +           const struct ipt_ip *ip,
4496 +           void *matchinfo,
4497 +           unsigned int matchsize,
4498 +           unsigned int hook_mask)
4499 +{
4500 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
4501 +               return 0;
4502 +       return 1;
4503 +}
4504 +
4505 +static struct ipt_match u32_match
4506 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
4507 +
4508 +static int __init init(void)
4509 +{
4510 +       return ipt_register_match(&u32_match);
4511 +}
4512 +
4513 +static void __exit fini(void)
4514 +{
4515 +       ipt_unregister_match(&u32_match);
4516 +}
4517 +
4518 +module_init(init);
4519 +module_exit(fini);
4520 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.4-rc2/net/ipv4/netfilter/iptable_raw.c
4521 --- linux-2.6.4-rc2.org/net/ipv4/netfilter/iptable_raw.c        1970-01-01 00:00:00.000000000 +0000
4522 +++ linux-2.6.4-rc2/net/ipv4/netfilter/iptable_raw.c    2004-03-07 08:43:29.000000000 +0000
4523 @@ -0,0 +1,149 @@
4524 +/* 
4525 + * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
4526 + *
4527 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4528 + */
4529 +#include <linux/module.h>
4530 +#include <linux/netfilter_ipv4/ip_tables.h>
4531 +
4532 +#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
4533 +
4534 +/* Standard entry. */
4535 +struct ipt_standard
4536 +{
4537 +       struct ipt_entry entry;
4538 +       struct ipt_standard_target target;
4539 +};
4540 +
4541 +struct ipt_error_target
4542 +{
4543 +       struct ipt_entry_target target;
4544 +       char errorname[IPT_FUNCTION_MAXNAMELEN];
4545 +};
4546 +
4547 +struct ipt_error
4548 +{
4549 +       struct ipt_entry entry;
4550 +       struct ipt_error_target target;
4551 +};
4552 +
4553 +static struct
4554 +{
4555 +       struct ipt_replace repl;
4556 +       struct ipt_standard entries[2];
4557 +       struct ipt_error term;
4558 +} initial_table __initdata
4559 += { { "raw", RAW_VALID_HOOKS, 3,
4560 +      sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
4561 +      { [NF_IP_PRE_ROUTING] 0,
4562 +       [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
4563 +      { [NF_IP_PRE_ROUTING] 0,
4564 +       [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
4565 +      0, NULL, { } },
4566 +    {
4567 +           /* PRE_ROUTING */
4568 +           { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
4569 +               0,
4570 +               sizeof(struct ipt_entry),
4571 +               sizeof(struct ipt_standard),
4572 +               0, { 0, 0 }, { } },
4573 +             { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
4574 +               -NF_ACCEPT - 1 } },
4575 +           /* LOCAL_OUT */
4576 +           { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
4577 +               0,
4578 +               sizeof(struct ipt_entry),
4579 +               sizeof(struct ipt_standard),
4580 +               0, { 0, 0 }, { } },
4581 +             { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
4582 +               -NF_ACCEPT - 1 } }
4583 +    },
4584 +    /* ERROR */
4585 +    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
4586 +       0,
4587 +       sizeof(struct ipt_entry),
4588 +       sizeof(struct ipt_error),
4589 +       0, { 0, 0 }, { } },
4590 +      { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
4591 +         { } },
4592 +       "ERROR"
4593 +      }
4594 +    }
4595 +};
4596 +
4597 +static struct ipt_table packet_raw = { 
4598 +       .name = "raw", 
4599 +       .table = &initial_table.repl,
4600 +       .valid_hooks =  RAW_VALID_HOOKS, 
4601 +       .lock = RW_LOCK_UNLOCKED, 
4602 +       .me = THIS_MODULE
4603 +};
4604 +
4605 +/* The work comes in here from netfilter.c. */
4606 +static unsigned int
4607 +ipt_hook(unsigned int hook,
4608 +        struct sk_buff **pskb,
4609 +        const struct net_device *in,
4610 +        const struct net_device *out,
4611 +        int (*okfn)(struct sk_buff *))
4612 +{
4613 +       return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
4614 +}
4615 +
4616 +/* 'raw' is the very first table. */
4617 +static struct nf_hook_ops ipt_ops[] = {
4618 +       {
4619 +         .hook = ipt_hook, 
4620 +         .pf = PF_INET, 
4621 +         .hooknum = NF_IP_PRE_ROUTING, 
4622 +         .priority = NF_IP_PRI_RAW
4623 +       },
4624 +       {
4625 +         .hook = ipt_hook, 
4626 +         .pf = PF_INET, 
4627 +         .hooknum = NF_IP_LOCAL_OUT, 
4628 +         .priority = NF_IP_PRI_RAW
4629 +       },
4630 +};
4631 +
4632 +static int __init init(void)
4633 +{
4634 +       int ret;
4635 +
4636 +       /* Register table */
4637 +       ret = ipt_register_table(&packet_raw);
4638 +       if (ret < 0)
4639 +               return ret;
4640 +
4641 +       /* Register hooks */
4642 +       ret = nf_register_hook(&ipt_ops[0]);
4643 +       if (ret < 0)
4644 +               goto cleanup_table;
4645 +
4646 +       ret = nf_register_hook(&ipt_ops[1]);
4647 +       if (ret < 0)
4648 +               goto cleanup_hook0;
4649 +
4650 +       return ret;
4651 +
4652 + cleanup_hook0:
4653 +       nf_unregister_hook(&ipt_ops[0]);
4654 + cleanup_table:
4655 +       ipt_unregister_table(&packet_raw);
4656 +
4657 +       return ret;
4658 +}
4659 +
4660 +static void __exit fini(void)
4661 +{
4662 +       unsigned int i;
4663 +
4664 +       for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
4665 +               nf_unregister_hook(&ipt_ops[i]);
4666 +
4667 +       ipt_unregister_table(&packet_raw);
4668 +}
4669 +
4670 +module_init(init);
4671 +module_exit(fini);
4672 +MODULE_LICENSE("GPL");
4673 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv6/netfilter/Kconfig linux-2.6.4-rc2/net/ipv6/netfilter/Kconfig
4674 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/Kconfig      2004-03-04 06:17:03.000000000 +0000
4675 +++ linux-2.6.4-rc2/net/ipv6/netfilter/Kconfig  2004-03-07 08:43:29.000000000 +0000
4676 @@ -218,5 +218,37 @@
4677           To compile it as a module, choose M here.  If unsure, say N.
4678  
4679  #dep_tristate '  LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
4680 +config IP6_NF_TARGET_HL
4681 +       tristate  'HL target support'
4682 +       depends on IP6_NF_MANGLE
4683 +         help
4684 +
4685 +config IP6_NF_TARGET_REJECT
4686 +       tristate  'REJECT target support'
4687 +       depends on IP6_NF_FILTER
4688 +         help
4689 +
4690 +config IP6_NF_MATCH_FUZZY
4691 +       tristate  'Fuzzy match support'
4692 +       depends on IP6_NF_FILTER
4693 +         help
4694 +
4695 +config IP6_NF_MATCH_NTH
4696 +       tristate  'Nth match support'
4697 +       depends on IP6_NF_IPTABLES
4698 +         help
4699 +
4700 +config IP6_NF_RAW
4701 +       tristate  'raw table support (required for TRACE)'
4702 +       depends on IP6_NF_IPTABLES
4703 +       help
4704 +         This option adds a `raw' table to ip6tables. This table is the very
4705 +         first in the netfilter framework and hooks in at the PREROUTING
4706 +         and OUTPUT chains.
4707 +       
4708 +         If you want to compile it as a module, say M here and read
4709 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
4710 +         help
4711 +
4712  endmenu
4713  
4714 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv6/netfilter/Makefile linux-2.6.4-rc2/net/ipv6/netfilter/Makefile
4715 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/Makefile     2004-03-04 06:16:48.000000000 +0000
4716 +++ linux-2.6.4-rc2/net/ipv6/netfilter/Makefile 2004-03-07 08:43:29.000000000 +0000
4717 @@ -8,6 +8,7 @@
4718  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
4719  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
4720  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
4721 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
4722  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
4723  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
4724  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
4725 @@ -19,6 +20,11 @@
4726  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
4727  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
4728  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
4729 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
4730  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
4731  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
4732 +obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
4733 +
4734 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
4735 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
4736  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
4737 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_HL.c
4738 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_HL.c    1970-01-01 00:00:00.000000000 +0000
4739 +++ linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_HL.c        2004-03-07 08:43:13.000000000 +0000
4740 @@ -0,0 +1,105 @@
4741 +/* 
4742 + * Hop Limit modification target for ip6tables
4743 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
4744 + * Based on HW's TTL module
4745 + *
4746 + * This software is distributed under the terms of GNU GPL
4747 + */
4748 +
4749 +#include <linux/module.h>
4750 +#include <linux/skbuff.h>
4751 +#include <linux/ip.h>
4752 +
4753 +#include <linux/netfilter_ipv6/ip6_tables.h>
4754 +#include <linux/netfilter_ipv6/ip6t_HL.h>
4755 +
4756 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
4757 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
4758 +MODULE_LICENSE("GPL");
4759 +
4760 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
4761 +               const struct net_device *in, const struct net_device *out,
4762 +               const void *targinfo, void *userinfo)
4763 +{
4764 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
4765 +       const struct ip6t_HL_info *info = targinfo;
4766 +       u_int16_t diffs[2];
4767 +       int new_hl;
4768 +                        
4769 +       switch (info->mode) {
4770 +               case IP6T_HL_SET:
4771 +                       new_hl = info->hop_limit;
4772 +                       break;
4773 +               case IP6T_HL_INC:
4774 +                       new_hl = ip6h->hop_limit + info->hop_limit;
4775 +                       if (new_hl > 255)
4776 +                               new_hl = 255;
4777 +                       break;
4778 +               case IP6T_HL_DEC:
4779 +                       new_hl = ip6h->hop_limit + info->hop_limit;
4780 +                       if (new_hl < 0)
4781 +                               new_hl = 0;
4782 +                       break;
4783 +               default:
4784 +                       new_hl = ip6h->hop_limit;
4785 +                       break;
4786 +       }
4787 +
4788 +       if (new_hl != ip6h->hop_limit) {
4789 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
4790 +               ip6h->hop_limit = new_hl;
4791 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
4792 +       }
4793 +
4794 +       return IP6T_CONTINUE;
4795 +}
4796 +
4797 +static int ip6t_hl_checkentry(const char *tablename,
4798 +               const struct ip6t_entry *e,
4799 +               void *targinfo,
4800 +               unsigned int targinfosize,
4801 +               unsigned int hook_mask)
4802 +{
4803 +       struct ip6t_HL_info *info = targinfo;
4804 +
4805 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
4806 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
4807 +                               targinfosize,
4808 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
4809 +               return 0;       
4810 +       }       
4811 +
4812 +       if (strcmp(tablename, "mangle")) {
4813 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
4814 +               return 0;
4815 +       }
4816 +
4817 +       if (info->mode > IP6T_HL_MAXMODE) {
4818 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
4819 +                       info->mode);
4820 +               return 0;
4821 +       }
4822 +
4823 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
4824 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
4825 +               return 0;
4826 +       }
4827 +       
4828 +       return 1;
4829 +}
4830 +
4831 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
4832 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
4833 +
4834 +static int __init init(void)
4835 +{
4836 +       return ip6t_register_target(&ip6t_HL);
4837 +}
4838 +
4839 +static void __exit fini(void)
4840 +{
4841 +       ip6t_unregister_target(&ip6t_HL);
4842 +}
4843 +
4844 +module_init(init);
4845 +module_exit(fini);
4846 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_LOG.c linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_LOG.c
4847 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_LOG.c   2004-03-04 06:16:41.000000000 +0000
4848 +++ linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_LOG.c       2004-03-07 08:43:12.000000000 +0000
4849 @@ -18,12 +18,17 @@
4850  #include <net/udp.h>
4851  #include <net/tcp.h>
4852  #include <net/ipv6.h>
4853 +#include <linux/netfilter.h>
4854  #include <linux/netfilter_ipv6/ip6_tables.h>
4855  
4856  MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
4857  MODULE_DESCRIPTION("IP6 tables LOG target module");
4858  MODULE_LICENSE("GPL");
4859  
4860 +static unsigned int nflog = 1;
4861 +MODULE_PARM(nflog, "i");
4862 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
4863
4864  struct in_device;
4865  #include <net/route.h>
4866  #include <linux/netfilter_ipv6/ip6t_LOG.h>
4867 @@ -265,40 +270,38 @@
4868         }
4869  }
4870  
4871 -static unsigned int
4872 -ip6t_log_target(struct sk_buff **pskb,
4873 -               unsigned int hooknum,
4874 +static void
4875 +ip6t_log_packet(unsigned int hooknum,
4876 +               const struct sk_buff *skb,
4877                 const struct net_device *in,
4878                 const struct net_device *out,
4879 -               const void *targinfo,
4880 -               void *userinfo)
4881 +               const struct ip6t_log_info *loginfo,
4882 +               const char *level_string,
4883 +               const char *prefix)
4884  {
4885 -       struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
4886 -       const struct ip6t_log_info *loginfo = targinfo;
4887 -       char level_string[4] = "< >";
4888 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
4889  
4890 -       level_string[1] = '0' + (loginfo->level % 8);
4891         spin_lock_bh(&log_lock);
4892         printk(level_string);
4893         printk("%sIN=%s OUT=%s ",
4894 -               loginfo->prefix,
4895 +               prefix == NULL ? loginfo->prefix : prefix,
4896                 in ? in->name : "",
4897                 out ? out->name : "");
4898         if (in && !out) {
4899                 /* MAC logging for input chain only. */
4900                 printk("MAC=");
4901 -               if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) {
4902 -                       if ((*pskb)->dev->type != ARPHRD_SIT){
4903 +               if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
4904 +                       if (skb->dev->type != ARPHRD_SIT){
4905                           int i;
4906 -                         unsigned char *p = (*pskb)->mac.raw;
4907 -                         for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
4908 +                         unsigned char *p = skb->mac.raw;
4909 +                         for (i = 0; i < skb->dev->hard_header_len; i++,p++)
4910                                 printk("%02x%c", *p,
4911 -                                       i==(*pskb)->dev->hard_header_len - 1
4912 +                                       i==skb->dev->hard_header_len - 1
4913                                         ? ' ':':');
4914                         } else {
4915                           int i;
4916 -                         unsigned char *p = (*pskb)->mac.raw;
4917 -                         if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){
4918 +                         unsigned char *p = skb->mac.raw;
4919 +                         if ( p - (ETH_ALEN*2+2) > skb->head ){
4920                             p -= (ETH_ALEN+2);
4921                             for (i = 0; i < (ETH_ALEN); i++,p++)
4922                                 printk("%02x%s", *p,
4923 @@ -309,10 +312,10 @@
4924                                         i == ETH_ALEN-1 ? ' ' : ':');
4925                           }
4926                           
4927 -                         if (((*pskb)->dev->addr_len == 4) &&
4928 -                             (*pskb)->dev->hard_header_len > 20){
4929 +                         if ((skb->dev->addr_len == 4) &&
4930 +                             skb->dev->hard_header_len > 20){
4931                             printk("TUNNEL=");
4932 -                           p = (*pskb)->mac.raw + 12;
4933 +                           p = skb->mac.raw + 12;
4934                             for (i = 0; i < 4; i++,p++)
4935                                 printk("%3d%s", *p,
4936                                         i == 3 ? "->" : ".");
4937 @@ -328,10 +331,41 @@
4938         dump_packet(loginfo, ipv6h, 1);
4939         printk("\n");
4940         spin_unlock_bh(&log_lock);
4941 +}
4942 +
4943 +static unsigned int
4944 +ip6t_log_target(struct sk_buff **pskb,
4945 +               unsigned int hooknum,
4946 +               const struct net_device *in,
4947 +               const struct net_device *out,
4948 +               const void *targinfo,
4949 +               void *userinfo)
4950 +{
4951 +       const struct ip6t_log_info *loginfo = targinfo;
4952 +       char level_string[4] = "< >";
4953 +
4954 +       level_string[1] = '0' + (loginfo->level % 8);
4955 +       ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
4956  
4957         return IP6T_CONTINUE;
4958  }
4959  
4960 +static void
4961 +ip6t_logfn(unsigned int hooknum,
4962 +          const struct sk_buff *skb,
4963 +          const struct net_device *in,
4964 +          const struct net_device *out,
4965 +          const char *prefix)
4966 +{
4967 +       struct ip6t_log_info loginfo = {
4968 +               .level = 0,
4969 +               .logflags = IP6T_LOG_MASK,
4970 +               .prefix = ""
4971 +       };
4972 +
4973 +       ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
4974 +}
4975 +
4976  static int ip6t_log_checkentry(const char *tablename,
4977                                const struct ip6t_entry *e,
4978                                void *targinfo,
4979 @@ -360,20 +394,27 @@
4980         return 1;
4981  }
4982  
4983 -static struct ip6t_target ip6t_log_reg
4984 -= { { NULL, NULL }, "LOG", ip6t_log_target, ip6t_log_checkentry, NULL, 
4985 -    THIS_MODULE };
4986 +static struct ip6t_target ip6t_log_reg = {
4987 +       .name           = "LOG",
4988 +       .target         = ip6t_log_target, 
4989 +       .checkentry     = ip6t_log_checkentry, 
4990 +       .me             = THIS_MODULE,
4991 +};
4992  
4993  static int __init init(void)
4994  {
4995         if (ip6t_register_target(&ip6t_log_reg))
4996                 return -EINVAL;
4997 +       if (nflog)
4998 +               nf_log_register(PF_INET6, &ip6t_logfn);
4999  
5000         return 0;
5001  }
5002  
5003  static void __exit fini(void)
5004  {
5005 +       if (nflog)
5006 +               nf_log_unregister(PF_INET6, &ip6t_logfn);
5007         ip6t_unregister_target(&ip6t_log_reg);
5008  }
5009  
5010 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_REJECT.c
5011 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_REJECT.c        1970-01-01 00:00:00.000000000 +0000
5012 +++ linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_REJECT.c    2004-03-07 08:43:15.000000000 +0000
5013 @@ -0,0 +1,274 @@
5014 +/*
5015 + * This is a module which is used for rejecting packets.
5016 + *     Added support for customized reject packets (Jozsef Kadlecsik).
5017 + * Sun 12 Nov 2000
5018 + *     Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
5019 + */
5020 +#include <linux/config.h>
5021 +#include <linux/module.h>
5022 +#include <linux/skbuff.h>
5023 +#include <linux/icmpv6.h>
5024 +#include <net/tcp.h>
5025 +#include <linux/netfilter_ipv6/ip6_tables.h>
5026 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
5027 +
5028 +#if 1
5029 +#define DEBUGP printk
5030 +#else
5031 +#define DEBUGP(format, args...)
5032 +#endif
5033 +
5034 +#if 0
5035 +/* Send RST reply */
5036 +static void send_reset(struct sk_buff *oldskb)
5037 +{
5038 +       struct sk_buff *nskb;
5039 +       struct tcphdr *otcph, *tcph;
5040 +       struct rtable *rt;
5041 +       unsigned int otcplen;
5042 +       int needs_ack;
5043 +
5044 +       /* IP header checks: fragment, too short. */
5045 +       if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
5046 +           || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
5047 +               return;
5048 +
5049 +       otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
5050 +       otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
5051 +
5052 +       /* No RST for RST. */
5053 +       if (otcph->rst)
5054 +               return;
5055 +
5056 +       /* Check checksum. */
5057 +       if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
5058 +                        oldskb->nh.iph->daddr,
5059 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
5060 +               return;
5061 +
5062 +       /* Copy skb (even if skb is about to be dropped, we can't just
5063 +           clone it because there may be other things, such as tcpdump,
5064 +           interested in it) */
5065 +       nskb = skb_copy(oldskb, GFP_ATOMIC);
5066 +       if (!nskb)
5067 +               return;
5068 +
5069 +       /* This packet will not be the same as the other: clear nf fields */
5070 +       nf_conntrack_put(nskb->nfct);
5071 +       nskb->nfct = NULL;
5072 +       nskb->nfcache = 0;
5073 +#ifdef CONFIG_NETFILTER_DEBUG
5074 +       nskb->nf_debug = 0;
5075 +#endif
5076 +
5077 +       tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
5078 +
5079 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
5080 +       tcph->source = xchg(&tcph->dest, tcph->source);
5081 +
5082 +       /* Truncate to length (no data) */
5083 +       tcph->doff = sizeof(struct tcphdr)/4;
5084 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
5085 +       nskb->nh.iph->tot_len = htons(nskb->len);
5086 +
5087 +       if (tcph->ack) {
5088 +               needs_ack = 0;
5089 +               tcph->seq = otcph->ack_seq;
5090 +               tcph->ack_seq = 0;
5091 +       } else {
5092 +               needs_ack = 1;
5093 +               tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
5094 +                                     + otcplen - (otcph->doff<<2));
5095 +               tcph->seq = 0;
5096 +       }
5097 +
5098 +       /* Reset flags */
5099 +       ((u_int8_t *)tcph)[13] = 0;
5100 +       tcph->rst = 1;
5101 +       tcph->ack = needs_ack;
5102 +
5103 +       tcph->window = 0;
5104 +       tcph->urg_ptr = 0;
5105 +
5106 +       /* Adjust TCP checksum */
5107 +       tcph->check = 0;
5108 +       tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
5109 +                                  nskb->nh.iph->saddr,
5110 +                                  nskb->nh.iph->daddr,
5111 +                                  csum_partial((char *)tcph,
5112 +                                               sizeof(struct tcphdr), 0));
5113 +
5114 +       /* Adjust IP TTL, DF */
5115 +       nskb->nh.iph->ttl = MAXTTL;
5116 +       /* Set DF, id = 0 */
5117 +       nskb->nh.iph->frag_off = htons(IP_DF);
5118 +       nskb->nh.iph->id = 0;
5119 +
5120 +       /* Adjust IP checksum */
5121 +       nskb->nh.iph->check = 0;
5122 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
5123 +                                          nskb->nh.iph->ihl);
5124 +
5125 +       /* Routing */
5126 +       if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
5127 +                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
5128 +                           0) != 0)
5129 +               goto free_nskb;
5130 +
5131 +       dst_release(nskb->dst);
5132 +       nskb->dst = &rt->u.dst;
5133 +
5134 +       /* "Never happens" */
5135 +       if (nskb->len > nskb->dst->pmtu)
5136 +               goto free_nskb;
5137 +
5138 +       NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
5139 +               ip_finish_output);
5140 +       return;
5141 +
5142 + free_nskb:
5143 +       kfree_skb(nskb);
5144 +}
5145 +#endif
5146 +
5147 +static unsigned int reject6_target(struct sk_buff **pskb,
5148 +                          unsigned int hooknum,
5149 +                          const struct net_device *in,
5150 +                          const struct net_device *out,
5151 +                          const void *targinfo,
5152 +                          void *userinfo)
5153 +{
5154 +       const struct ip6t_reject_info *reject = targinfo;
5155 +
5156 +       /* WARNING: This code causes reentry within ip6tables.
5157 +          This means that the ip6tables jump stack is now crap.  We
5158 +          must return an absolute verdict. --RR */
5159 +       DEBUGP("REJECTv6: calling icmpv6_send\n");
5160 +       switch (reject->with) {
5161 +       case IP6T_ICMP6_NO_ROUTE:
5162 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
5163 +               break;
5164 +       case IP6T_ICMP6_ADM_PROHIBITED:
5165 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
5166 +               break;
5167 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
5168 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
5169 +               break;
5170 +       case IP6T_ICMP6_ADDR_UNREACH:
5171 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
5172 +               break;
5173 +       case IP6T_ICMP6_PORT_UNREACH:
5174 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
5175 +               break;
5176 +#if 0
5177 +       case IPT_ICMP_ECHOREPLY: {
5178 +               struct icmp6hdr *icmph  = (struct icmphdr *)
5179 +                       ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
5180 +               unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
5181 +
5182 +               /* Not non-head frags, or truncated */
5183 +               if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
5184 +                   && datalen >= 4) {
5185 +                       /* Usually I don't like cut & pasting code,
5186 +                           but dammit, my party is starting in 45
5187 +                           mins! --RR */
5188 +                       struct icmp_bxm icmp_param;
5189 +
5190 +                       icmp_param.icmph=*icmph;
5191 +                       icmp_param.icmph.type=ICMP_ECHOREPLY;
5192 +                       icmp_param.data_ptr=(icmph+1);
5193 +                       icmp_param.data_len=datalen;
5194 +                       icmp_reply(&icmp_param, *pskb);
5195 +               }
5196 +       }
5197 +       break;
5198 +       case IPT_TCP_RESET:
5199 +               send_reset(*pskb);
5200 +               break;
5201 +#endif
5202 +       default:
5203 +               printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
5204 +               break;
5205 +       }
5206 +
5207 +       return NF_DROP;
5208 +}
5209 +
5210 +static inline int find_ping_match(const struct ip6t_entry_match *m)
5211 +{
5212 +       const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
5213 +
5214 +       if (strcmp(m->u.kernel.match->name, "icmp6") == 0
5215 +           && icmpinfo->type == ICMPV6_ECHO_REQUEST
5216 +           && !(icmpinfo->invflags & IP6T_ICMP_INV))
5217 +               return 1;
5218 +
5219 +       return 0;
5220 +}
5221 +
5222 +static int check(const char *tablename,
5223 +                const struct ip6t_entry *e,
5224 +                void *targinfo,
5225 +                unsigned int targinfosize,
5226 +                unsigned int hook_mask)
5227 +{
5228 +       const struct ip6t_reject_info *rejinfo = targinfo;
5229 +
5230 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
5231 +               DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
5232 +               return 0;
5233 +       }
5234 +
5235 +       /* Only allow these for packet filtering. */
5236 +       if (strcmp(tablename, "filter") != 0) {
5237 +               DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
5238 +               return 0;
5239 +       }
5240 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
5241 +                          | (1 << NF_IP6_FORWARD)
5242 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
5243 +               DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
5244 +               return 0;
5245 +       }
5246 +
5247 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
5248 +               /* Must specify that it's an ICMP ping packet. */
5249 +               if (e->ipv6.proto != IPPROTO_ICMPV6
5250 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
5251 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
5252 +                       return 0;
5253 +               }
5254 +               /* Must contain ICMP match. */
5255 +               if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
5256 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
5257 +                       return 0;
5258 +               }
5259 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
5260 +               /* Must specify that it's a TCP packet */
5261 +               if (e->ipv6.proto != IPPROTO_TCP
5262 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
5263 +                       DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
5264 +                       return 0;
5265 +               }
5266 +       }
5267 +
5268 +       return 1;
5269 +}
5270 +
5271 +static struct ip6t_target ip6t_reject_reg
5272 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
5273 +
5274 +static int __init init(void)
5275 +{
5276 +       if (ip6t_register_target(&ip6t_reject_reg))
5277 +               return -EINVAL;
5278 +       return 0;
5279 +}
5280 +
5281 +static void __exit fini(void)
5282 +{
5283 +       ip6t_unregister_target(&ip6t_reject_reg);
5284 +}
5285 +
5286 +module_init(init);
5287 +module_exit(fini);
5288 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_fuzzy.c
5289 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 00:00:00.000000000 +0000
5290 +++ linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_fuzzy.c     2004-03-07 08:43:19.000000000 +0000
5291 @@ -0,0 +1,189 @@
5292 +/*
5293 + * This module implements a simple TSK FLC
5294 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
5295 + * to limit , in an adaptive and flexible way , the packet rate crossing
5296 + * a given stream . It serves as an initial and very simple (but effective)
5297 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
5298 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
5299 + * into our code in a precise , adaptive and efficient manner.
5300 + *  The goal is very similar to that of "limit" match , but using techniques of
5301 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
5302 + * avoiding over and undershoots - and stuff like that .
5303 + *
5304 + *
5305 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
5306 + * 2002-08-17  : Changed to eliminate floating point operations .
5307 + * 2002-08-23  : Coding style changes .
5308 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
5309 + */
5310 +
5311 +#include <linux/module.h>
5312 +#include <linux/skbuff.h>
5313 +#include <linux/ipv6.h>
5314 +#include <linux/random.h>
5315 +#include <net/tcp.h>
5316 +#include <linux/spinlock.h>
5317 +#include <linux/netfilter_ipv6/ip6_tables.h>
5318 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
5319 +
5320 +/*
5321 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
5322 + Expressed in percentage
5323 +*/
5324 +
5325 +#define PAR_LOW                1/100
5326 +#define PAR_HIGH       1
5327 +
5328 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
5329 +
5330 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
5331 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
5332 +MODULE_LICENSE("GPL");
5333 +
5334 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
5335 +{
5336 +       if (tx >= maxi) return 100;
5337 +
5338 +       if (tx <= mini) return 0;
5339 +
5340 +       return ((100 * (tx-mini)) / (maxi-mini));
5341 +}
5342 +
5343 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
5344 +{
5345 +       if (tx <= mini) return 100;
5346 +
5347 +       if (tx >= maxi) return 0;
5348 +
5349 +       return ((100 * (maxi - tx)) / (maxi - mini));
5350 +
5351 +}
5352 +
5353 +static int
5354 +ip6t_fuzzy_match(const struct sk_buff *pskb,
5355 +              const struct net_device *in,
5356 +              const struct net_device *out,
5357 +              const void *matchinfo,
5358 +              int offset,
5359 +              const void *hdr,
5360 +              u_int16_t datalen,
5361 +              int *hotdrop)
5362 +{
5363 +       /* From userspace */
5364 +
5365 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
5366 +
5367 +       u_int8_t random_number;
5368 +       unsigned long amount;
5369 +       u_int8_t howhigh, howlow;
5370 +
5371 +
5372 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
5373 +
5374 +       info->bytes_total += pskb->len;
5375 +       info->packets_total++;
5376 +
5377 +       info->present_time = jiffies;
5378 +
5379 +       if (info->present_time >= info->previous_time)
5380 +               amount = info->present_time - info->previous_time;
5381 +       else {
5382 +               /* There was a transition : I choose to re-sample
5383 +                  and keep the old acceptance rate...
5384 +               */
5385 +
5386 +               amount = 0;
5387 +               info->previous_time = info->present_time;
5388 +               info->bytes_total = info->packets_total = 0;
5389 +            };
5390 +
5391 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
5392 +
5393 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
5394 +                                       / amount);
5395 +
5396 +               info->previous_time = info->present_time;
5397 +               info->bytes_total = info->packets_total = 0;
5398 +
5399 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
5400 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
5401 +
5402 +               info->acceptance_rate = (u_int8_t) \
5403 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
5404 +
5405 +       /* In fact, the above defuzzification would require a denominator
5406 +        * proportional to (howhigh+howlow) but, in this particular case,
5407 +        * that expression is constant.
5408 +        * An imediate consequence is that it is not necessary to call
5409 +        * both mf_high and mf_low - but to keep things understandable,
5410 +        * I did so.
5411 +        */
5412 +
5413 +       }
5414 +
5415 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
5416 +
5417 +
5418 +       if (info->acceptance_rate < 100)
5419 +       {
5420 +               get_random_bytes((void *)(&random_number), 1);
5421 +
5422 +               /*  If within the acceptance , it can pass => don't match */
5423 +               if (random_number <= (255 * info->acceptance_rate) / 100)
5424 +                       return 0;
5425 +               else
5426 +                       return 1; /* It can't pass (It matches) */
5427 +       };
5428 +
5429 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
5430 +
5431 +}
5432 +
5433 +static int
5434 +ip6t_fuzzy_checkentry(const char *tablename,
5435 +                  const struct ip6t_ip6 *ip,
5436 +                  void *matchinfo,
5437 +                  unsigned int matchsize,
5438 +                  unsigned int hook_mask)
5439 +{
5440 +
5441 +       const struct ip6t_fuzzy_info *info = matchinfo;
5442 +
5443 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
5444 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
5445 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
5446 +               return 0;
5447 +       }
5448 +
5449 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
5450 +        || (info->minimum_rate >= info->maximum_rate)) {
5451 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
5452 +               return 0;
5453 +       }
5454 +
5455 +       return 1;
5456 +}
5457 +
5458 +static struct ip6t_match ip6t_fuzzy_reg = {
5459 +       {NULL, NULL},
5460 +       "fuzzy",
5461 +       ip6t_fuzzy_match,
5462 +       ip6t_fuzzy_checkentry,
5463 +       NULL,
5464 +       THIS_MODULE };
5465 +
5466 +static int __init init(void)
5467 +{
5468 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
5469 +               return -EINVAL;
5470 +
5471 +       return 0;
5472 +}
5473 +
5474 +static void __exit fini(void)
5475 +{
5476 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
5477 +}
5478 +
5479 +module_init(init);
5480 +module_exit(fini);
5481 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_nth.c
5482 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6t_nth.c   1970-01-01 00:00:00.000000000 +0000
5483 +++ linux-2.6.4-rc2/net/ipv6/netfilter/ip6t_nth.c       2004-03-07 08:43:24.000000000 +0000
5484 @@ -0,0 +1,173 @@
5485 +/*
5486 +  This is a module which is used for match support for every Nth packet
5487 +  This file is distributed under the terms of the GNU General Public
5488 +  License (GPL). Copies of the GPL can be obtained from:
5489 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
5490 +
5491 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
5492 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
5493 +        * added support for multiple counters
5494 +        * added support for matching on individual packets
5495 +          in the counter cycle
5496 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
5497 +
5498 +*/
5499 +
5500 +#include <linux/module.h>
5501 +#include <linux/skbuff.h>
5502 +#include <linux/ip.h>
5503 +#include <net/tcp.h>
5504 +#include <linux/spinlock.h>
5505 +#include <linux/netfilter_ipv6/ip6_tables.h>
5506 +#include <linux/netfilter_ipv6/ip6t_nth.h>
5507 +
5508 +MODULE_LICENSE("GPL");
5509 +
5510 +/*
5511 + * State information.
5512 + */
5513 +struct state {
5514 +       spinlock_t lock;
5515 +       u_int16_t number;
5516 +};
5517 +
5518 +static struct state states[IP6T_NTH_NUM_COUNTERS];
5519 +
5520 +static int
5521 +ip6t_nth_match(const struct sk_buff *pskb,
5522 +             const struct net_device *in,
5523 +             const struct net_device *out,
5524 +             const void *matchinfo,
5525 +             int offset,
5526 +             const void *hdr,
5527 +             u_int16_t datalen,
5528 +             int *hotdrop)
5529 +{
5530 +       /* Parameters from userspace */
5531 +       const struct ip6t_nth_info *info = matchinfo;
5532 +        unsigned counter = info->counter;
5533 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
5534 +       {
5535 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
5536 +               return 0;
5537 +        };
5538 +
5539 +        spin_lock(&states[counter].lock);
5540 +
5541 +        /* Are we matching every nth packet?*/
5542 +        if (info->packet == 0xFF)
5543 +        {
5544 +               /* We're matching every nth packet and only every nth packet*/
5545 +               /* Do we match or invert match? */
5546 +               if (info->not == 0)
5547 +               {
5548 +                       if (states[counter].number == 0)
5549 +                       {
5550 +                               ++states[counter].number;
5551 +                               goto match;
5552 +                       }
5553 +                       if (states[counter].number >= info->every)
5554 +                               states[counter].number = 0; /* reset the counter */
5555 +                       else
5556 +                               ++states[counter].number;
5557 +                       goto dontmatch;
5558 +               }
5559 +               else
5560 +               {
5561 +                       if (states[counter].number == 0)
5562 +                       {
5563 +                               ++states[counter].number;
5564 +                               goto dontmatch;
5565 +                       }
5566 +                       if (states[counter].number >= info->every)
5567 +                               states[counter].number = 0;
5568 +                       else
5569 +                               ++states[counter].number;
5570 +                       goto match;
5571 +               }
5572 +        }
5573 +        else
5574 +        {
5575 +               /* We're using the --packet, so there must be a rule for every value */
5576 +               if (states[counter].number == info->packet)
5577 +               {
5578 +                       /* only increment the counter when a match happens */
5579 +                       if (states[counter].number >= info->every)
5580 +                               states[counter].number = 0; /* reset the counter */
5581 +                       else
5582 +                               ++states[counter].number;
5583 +                       goto match;
5584 +               }
5585 +               else
5586 +                       goto dontmatch;
5587 +       }
5588 +
5589 + dontmatch:
5590 +       /* don't match */
5591 +       spin_unlock(&states[counter].lock);
5592 +       return 0;
5593 +
5594 + match:
5595 +       spin_unlock(&states[counter].lock);
5596 +       return 1;
5597 +}
5598 +
5599 +static int
5600 +ip6t_nth_checkentry(const char *tablename,
5601 +                  const struct ip6t_ip6 *e,
5602 +                  void *matchinfo,
5603 +                  unsigned int matchsize,
5604 +                  unsigned int hook_mask)
5605 +{
5606 +       /* Parameters from userspace */
5607 +       const struct ip6t_nth_info *info = matchinfo;
5608 +        unsigned counter = info->counter;
5609 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
5610 +       {
5611 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
5612 +                       return 0;
5613 +               };
5614 +
5615 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
5616 +               printk("nth: matchsize %u != %u\n", matchsize,
5617 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
5618 +               return 0;
5619 +       }
5620 +
5621 +       states[counter].number = info->startat;
5622 +
5623 +       return 1;
5624 +}
5625 +
5626 +static struct ip6t_match ip6t_nth_reg = { 
5627 +       {NULL, NULL},
5628 +       "nth",
5629 +       ip6t_nth_match,
5630 +       ip6t_nth_checkentry,
5631 +       NULL,
5632 +       THIS_MODULE };
5633 +
5634 +static int __init init(void)
5635 +{
5636 +       unsigned counter;
5637 +        memset(&states, 0, sizeof(states));
5638 +       if (ip6t_register_match(&ip6t_nth_reg))
5639 +               return -EINVAL;
5640 +
5641 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
5642 +       {
5643 +               spin_lock_init(&(states[counter].lock));
5644 +        };
5645 +
5646 +       printk("ip6t_nth match loaded\n");
5647 +       return 0;
5648 +}
5649 +
5650 +static void __exit fini(void)
5651 +{
5652 +       ip6t_unregister_match(&ip6t_nth_reg);
5653 +       printk("ip6t_nth match unloaded\n");
5654 +}
5655 +
5656 +module_init(init);
5657 +module_exit(fini);
5658 diff -Nur --exclude '*.orig' linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.4-rc2/net/ipv6/netfilter/ip6table_raw.c
5659 --- linux-2.6.4-rc2.org/net/ipv6/netfilter/ip6table_raw.c       1970-01-01 00:00:00.000000000 +0000
5660 +++ linux-2.6.4-rc2/net/ipv6/netfilter/ip6table_raw.c   2004-03-07 08:43:29.000000000 +0000
5661 @@ -0,0 +1,154 @@
5662 +/*
5663 + * IPv6 raw table, a port of the IPv4 raw table to IPv6
5664 + *
5665 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5666 + */
5667 +#include <linux/module.h>
5668 +#include <linux/netfilter_ipv6/ip6_tables.h>
5669 +
5670 +#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
5671 +
5672 +#if 0
5673 +#define DEBUGP(x, args...)     printk(KERN_DEBUG x, ## args)
5674 +#else
5675 +#define DEBUGP(x, args...)
5676 +#endif
5677 +
5678 +/* Standard entry. */
5679 +struct ip6t_standard
5680 +{
5681 +       struct ip6t_entry entry;
5682 +       struct ip6t_standard_target target;
5683 +};
5684 +
5685 +struct ip6t_error_target
5686 +{
5687 +       struct ip6t_entry_target target;
5688 +       char errorname[IP6T_FUNCTION_MAXNAMELEN];
5689 +};
5690 +
5691 +struct ip6t_error
5692 +{
5693 +       struct ip6t_entry entry;
5694 +       struct ip6t_error_target target;
5695 +};
5696 +
5697 +static struct
5698 +{
5699 +       struct ip6t_replace repl;
5700 +       struct ip6t_standard entries[2];
5701 +       struct ip6t_error term;
5702 +} initial_table __initdata 
5703 += { { "raw", RAW_VALID_HOOKS, 3,
5704 +      sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
5705 +      { [NF_IP6_PRE_ROUTING]   0,
5706 +       [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) },
5707 +      { [NF_IP6_PRE_ROUTING]   0,
5708 +       [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) },
5709 +      0, NULL, { } },
5710 +    {
5711 +           /* PRE_ROUTING */
5712 +            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
5713 +               0,
5714 +               sizeof(struct ip6t_entry),
5715 +               sizeof(struct ip6t_standard),
5716 +               0, { 0, 0 }, { } },
5717 +             { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
5718 +               -NF_ACCEPT - 1 } },
5719 +           /* LOCAL_OUT */
5720 +            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
5721 +               0,
5722 +               sizeof(struct ip6t_entry),
5723 +               sizeof(struct ip6t_standard),
5724 +               0, { 0, 0 }, { } },
5725 +             { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
5726 +               -NF_ACCEPT - 1 } },
5727 +    },
5728 +    /* ERROR */
5729 +    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
5730 +       0,
5731 +       sizeof(struct ip6t_entry),
5732 +       sizeof(struct ip6t_error),
5733 +       0, { 0, 0 }, { } },
5734 +      { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
5735 +         { } },
5736 +       "ERROR"
5737 +      }
5738 +    }
5739 +};
5740 +
5741 +static struct ip6t_table packet_raw = { 
5742 +       .name = "raw", 
5743 +       .table = &initial_table.repl,
5744 +       .valid_hooks = RAW_VALID_HOOKS, 
5745 +       .lock = RW_LOCK_UNLOCKED, 
5746 +       .me = THIS_MODULE
5747 +};
5748 +
5749 +/* The work comes in here from netfilter.c. */
5750 +static unsigned int
5751 +ip6t_hook(unsigned int hook,
5752 +        struct sk_buff **pskb,
5753 +        const struct net_device *in,
5754 +        const struct net_device *out,
5755 +        int (*okfn)(struct sk_buff *))
5756 +{
5757 +       return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
5758 +}
5759 +
5760 +static struct nf_hook_ops ip6t_ops[] = { 
5761 +       {
5762 +         .hook = ip6t_hook, 
5763 +         .pf = PF_INET6,
5764 +         .hooknum = NF_IP6_PRE_ROUTING,
5765 +         .priority = NF_IP6_PRI_FIRST
5766 +       },
5767 +       {
5768 +         .hook = ip6t_hook, 
5769 +         .pf = PF_INET6, 
5770 +         .hooknum = NF_IP6_LOCAL_OUT,
5771 +         .priority = NF_IP6_PRI_FIRST
5772 +       },
5773 +};
5774 +
5775 +static int __init init(void)
5776 +{
5777 +       int ret;
5778 +
5779 +       /* Register table */
5780 +       ret = ip6t_register_table(&packet_raw);
5781 +       if (ret < 0)
5782 +               return ret;
5783 +
5784 +       /* Register hooks */
5785 +       ret = nf_register_hook(&ip6t_ops[0]);
5786 +       if (ret < 0)
5787 +               goto cleanup_table;
5788 +
5789 +       ret = nf_register_hook(&ip6t_ops[1]);
5790 +       if (ret < 0)
5791 +               goto cleanup_hook0;
5792 +
5793 +       return ret;
5794 +
5795 + cleanup_hook0:
5796 +       nf_unregister_hook(&ip6t_ops[0]);
5797 + cleanup_table:
5798 +       ip6t_unregister_table(&packet_raw);
5799 +
5800 +       return ret;
5801 +}
5802 +
5803 +static void __exit fini(void)
5804 +{
5805 +       unsigned int i;
5806 +
5807 +       for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
5808 +               nf_unregister_hook(&ip6t_ops[i]);
5809 +
5810 +       ip6t_unregister_table(&packet_raw);
5811 +}
5812 +
5813 +module_init(init);
5814 +module_exit(fini);
5815 +MODULE_LICENSE("GPL");
This page took 0.600025 seconds and 3 git commands to generate.