]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.0-t9-netfilter-20031113.patch
- obsolete
[packages/kernel.git] / 2.6.0-t9-netfilter-20031113.patch
1 diff -Nur linux-2.6.0-test9.org/include/linux/netfilter.h linux-2.6.0-test9/include/linux/netfilter.h
2 --- linux-2.6.0-test9.org/include/linux/netfilter.h     2003-10-25 20:43:40.000000000 +0200
3 +++ linux-2.6.0-test9/include/linux/netfilter.h 2003-11-13 11:01:38.000000000 +0100
4 @@ -23,6 +23,7 @@
5     <= 0x2000 is used for protocol-flags. */
6  #define NFC_UNKNOWN 0x4000
7  #define NFC_ALTERED 0x8000
8 +#define NFC_TRACE   0x10000
9  
10  #ifdef __KERNEL__
11  #include <linux/config.h>
12 @@ -99,6 +100,24 @@
13  
14  extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
15  
16 +typedef void nf_logfn(unsigned int hooknum,
17 +                     const struct sk_buff *skb,
18 +                     const struct net_device *in,
19 +                     const struct net_device *out,
20 +                     const char *prefix);
21 +
22 +/* Function to register/unregister log function. */
23 +int nf_log_register(int pf, nf_logfn *logfn);
24 +void nf_log_unregister(int pf, nf_logfn *logfn);
25 +
26 +/* Calls the registered backend logging function */
27 +void nf_log_packet(int pf,
28 +                  unsigned int hooknum,
29 +                  const struct sk_buff *skb,
30 +                  const struct net_device *in,
31 +                  const struct net_device *out,
32 +                  const char *fmt, ...);
33 +                   
34  /* Activate hook; either okfn or kfree_skb called, unless a hook
35     returns NF_STOLEN (in which case, it's up to the hook to deal with
36     the consequences).
37 diff -Nur linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.0-test9/include/linux/netfilter_ipv4/ip_conntrack.h
38 --- linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ip_conntrack.h   2003-10-25 20:44:44.000000000 +0200
39 +++ linux-2.6.0-test9/include/linux/netfilter_ipv4/ip_conntrack.h       2003-11-13 11:01:38.000000000 +0100
40 @@ -268,6 +268,9 @@
41  
42  extern unsigned int ip_conntrack_htable_size;
43  
44 +/* A fake conntrack entry which never vanishes. */
45 +extern struct ip_conntrack ip_conntrack_untracked;
46 +
47  /* eg. PROVIDES_CONNTRACK(ftp); */
48  #define PROVIDES_CONNTRACK(name)                        \
49          int needs_ip_conntrack_##name;                  \
50 diff -Nur linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.0-test9/include/linux/netfilter_ipv4/ip_tables.h
51 --- linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ip_tables.h      2003-10-25 20:43:46.000000000 +0200
52 +++ linux-2.6.0-test9/include/linux/netfilter_ipv4/ip_tables.h  2003-11-13 11:01:38.000000000 +0100
53 @@ -134,6 +134,12 @@
54         /* Back pointer */
55         unsigned int comefrom;
56  
57 +       /* Name of the chain */
58 +       char *chainname;
59 +       
60 +       /* Rule number in the chain. */
61 +       u_int32_t rulenum;
62 +
63         /* Packet and byte counters. */
64         struct ipt_counters counters;
65  
66 diff -Nur linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ipt_ULOG.h linux-2.6.0-test9/include/linux/netfilter_ipv4/ipt_ULOG.h
67 --- linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ipt_ULOG.h       2003-10-25 20:43:28.000000000 +0200
68 +++ linux-2.6.0-test9/include/linux/netfilter_ipv4/ipt_ULOG.h   2003-11-13 11:01:18.000000000 +0100
69 @@ -11,6 +11,9 @@
70  #define NETLINK_NFLOG  5
71  #endif
72  
73 +#define NFLOG_DEFAULT_NLGROUP          1
74 +#define NFLOG_DEFAULT_QTHRESHOLD       1
75 +
76  #define ULOG_MAC_LEN   80
77  #define ULOG_PREFIX_LEN        32
78  
79 diff -Nur linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ipt_conntrack.h linux-2.6.0-test9/include/linux/netfilter_ipv4/ipt_conntrack.h
80 --- linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ipt_conntrack.h  2003-10-25 20:44:16.000000000 +0200
81 +++ linux-2.6.0-test9/include/linux/netfilter_ipv4/ipt_conntrack.h      2003-11-13 11:01:38.000000000 +0100
82 @@ -10,6 +10,7 @@
83  
84  #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
85  #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
86 +#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
87  
88  /* flags, invflags: */
89  #define IPT_CONNTRACK_STATE    0x01
90 diff -Nur linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.0-test9/include/linux/netfilter_ipv4/ipt_sctp.h
91 --- linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ipt_sctp.h       1970-01-01 01:00:00.000000000 +0100
92 +++ linux-2.6.0-test9/include/linux/netfilter_ipv4/ipt_sctp.h   2003-11-13 11:01:48.000000000 +0100
93 @@ -0,0 +1,25 @@
94 +/* iptables module for matching the SCTP header
95 + *
96 + * (C) 2003 Harald Welte <laforge@gnumonks.org>
97 + *
98 + * This software is distributed under GNU GPL v2, 1991
99 + *
100 + * $Id$
101 + */
102 +#ifndef _IPT_SCTP_H
103 +#define _IPT_SCTP_H
104 +
105 +struct ipt_sctp_info {
106 +       u_int16_t spts[2];                      /* Souce port range */
107 +       u_int16_t dpts[2];                      /* Destination port range */
108 +       u_int32_t chunks;                       /* chunks to be matched */
109 +       u_int32_t chunk_mask;                   /* chunk mask to be matched */
110 +       u_int8_t invflags;                      /* Inverse flags */
111 +};
112 +
113 +#define IPT_SCTP_INV_SRCPT     0x01    /* Invert the sense of source ports */
114 +#define IPT_SCTP_INV_DSTPT     0x02    /* Invert the sense of dest ports */
115 +#define IPT_SCTP_INV_CHUNKS    0x03    /* Invert the sense of chunks */
116 +#define IPT_SCTP_INV_MASK      0x03    /* All possible flags */
117 +
118 +#endif /* _IPT_SCTP_H */
119 diff -Nur linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ipt_state.h linux-2.6.0-test9/include/linux/netfilter_ipv4/ipt_state.h
120 --- linux-2.6.0-test9.org/include/linux/netfilter_ipv4/ipt_state.h      2003-10-25 20:44:36.000000000 +0200
121 +++ linux-2.6.0-test9/include/linux/netfilter_ipv4/ipt_state.h  2003-11-13 11:01:38.000000000 +0100
122 @@ -4,6 +4,8 @@
123  #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
124  #define IPT_STATE_INVALID (1 << 0)
125  
126 +#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
127 +
128  struct ipt_state_info
129  {
130         unsigned int statemask;
131 diff -Nur linux-2.6.0-test9.org/include/linux/netfilter_ipv4.h linux-2.6.0-test9/include/linux/netfilter_ipv4.h
132 --- linux-2.6.0-test9.org/include/linux/netfilter_ipv4.h        2003-10-25 20:44:34.000000000 +0200
133 +++ linux-2.6.0-test9/include/linux/netfilter_ipv4.h    2003-11-13 11:01:38.000000000 +0100
134 @@ -51,6 +51,8 @@
135  
136  enum nf_ip_hook_priorities {
137         NF_IP_PRI_FIRST = INT_MIN,
138 +       NF_IP_PRI_CONNTRACK_DEFRAG = -400,
139 +       NF_IP_PRI_RAW = -300,
140         NF_IP_PRI_CONNTRACK = -200,
141         NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
142         NF_IP_PRI_MANGLE = -150,
143 diff -Nur linux-2.6.0-test9.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.0-test9/include/linux/netfilter_ipv6/ip6_tables.h
144 --- linux-2.6.0-test9.org/include/linux/netfilter_ipv6/ip6_tables.h     2003-10-25 20:44:48.000000000 +0200
145 +++ linux-2.6.0-test9/include/linux/netfilter_ipv6/ip6_tables.h 2003-11-13 11:01:38.000000000 +0100
146 @@ -140,6 +140,12 @@
147         /* Back pointer */
148         unsigned int comefrom;
149  
150 +       /* Name of the chain */
151 +       char *chainname;
152 +       
153 +       /* Rule number in the chain. */
154 +       u_int32_t rulenum;
155 +
156         /* Packet and byte counters. */
157         struct ip6t_counters counters;
158  
159 diff -Nur linux-2.6.0-test9.org/net/bridge/br_netfilter.c linux-2.6.0-test9/net/bridge/br_netfilter.c
160 --- linux-2.6.0-test9.org/net/bridge/br_netfilter.c     2003-10-25 20:44:49.000000000 +0200
161 +++ linux-2.6.0-test9/net/bridge/br_netfilter.c 2003-11-13 10:57:06.000000000 +0100
162 @@ -297,6 +297,8 @@
163         if (skb->pkt_type == PACKET_OTHERHOST) {
164                 skb->pkt_type = PACKET_HOST;
165                 nf_bridge->mask |= BRNF_PKT_TYPE;
166 +               /* The physdev module checks on this */
167 +               nf_bridge->mask |= BRNF_BRIDGED;
168         }
169  
170         nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
171 diff -Nur linux-2.6.0-test9.org/net/bridge/br_netfilter.c.orig linux-2.6.0-test9/net/bridge/br_netfilter.c.orig
172 --- linux-2.6.0-test9.org/net/bridge/br_netfilter.c.orig        1970-01-01 01:00:00.000000000 +0100
173 +++ linux-2.6.0-test9/net/bridge/br_netfilter.c.orig    2003-10-25 20:44:49.000000000 +0200
174 @@ -0,0 +1,754 @@
175 +/*
176 + *     Handle firewalling
177 + *     Linux ethernet bridge
178 + *
179 + *     Authors:
180 + *     Lennert Buytenhek               <buytenh@gnu.org>
181 + *     Bart De Schuymer (maintainer)   <bdschuym@pandora.be>
182 + *
183 + *     Changes:
184 + *     Apr 29 2003: physdev module support (bdschuym)
185 + *     Jun 19 2003: let arptables see bridged ARP traffic (bdschuym)
186 + *     Oct 06 2003: filter encapsulated IP/ARP VLAN traffic on untagged bridge
187 + *                  (bdschuym)
188 + *
189 + *     This program is free software; you can redistribute it and/or
190 + *     modify it under the terms of the GNU General Public License
191 + *     as published by the Free Software Foundation; either version
192 + *     2 of the License, or (at your option) any later version.
193 + *
194 + *     Lennert dedicates this file to Kerstin Wurdinger.
195 + */
196 +
197 +#include <linux/module.h>
198 +#include <linux/kernel.h>
199 +#include <linux/ip.h>
200 +#include <linux/netdevice.h>
201 +#include <linux/skbuff.h>
202 +#include <linux/if_ether.h>
203 +#include <linux/if_vlan.h>
204 +#include <linux/netfilter_bridge.h>
205 +#include <linux/netfilter_ipv4.h>
206 +#include <linux/netfilter_arp.h>
207 +#include <linux/in_route.h>
208 +#include <net/ip.h>
209 +#include <asm/uaccess.h>
210 +#include <asm/checksum.h>
211 +#include "br_private.h"
212 +
213 +
214 +#define skb_origaddr(skb)       (((struct bridge_skb_cb *) \
215 +                                (skb->cb))->daddr.ipv4)
216 +#define store_orig_dstaddr(skb)         (skb_origaddr(skb) = (skb)->nh.iph->daddr)
217 +#define dnat_took_place(skb)    (skb_origaddr(skb) != (skb)->nh.iph->daddr)
218 +#define clear_cb(skb)           (memset(&skb_origaddr(skb), 0, \
219 +                                sizeof(struct bridge_skb_cb)))
220 +
221 +#define has_bridge_parent(device)      ((device)->br_port != NULL)
222 +#define bridge_parent(device)          ((device)->br_port->br->dev)
223 +
224 +#define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) && \
225 +       hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP))
226 +#define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) && \
227 +       hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP))
228 +
229 +/* We need these fake structures to make netfilter happy --
230 + * lots of places assume that skb->dst != NULL, which isn't
231 + * all that unreasonable.
232 + *
233 + * Currently, we fill in the PMTU entry because netfilter
234 + * refragmentation needs it, and the rt_flags entry because
235 + * ipt_REJECT needs it.  Future netfilter modules might
236 + * require us to fill additional fields.
237 + */
238 +static struct net_device __fake_net_device = {
239 +       .hard_header_len        = ETH_HLEN
240 +};
241 +
242 +static struct rtable __fake_rtable = {
243 +       .u = {
244 +               .dst = {
245 +                       .__refcnt               = ATOMIC_INIT(1),
246 +                       .dev                    = &__fake_net_device,
247 +                       .path                   = &__fake_rtable.u.dst,
248 +                       .metrics                = {[RTAX_MTU - 1] = 1500},
249 +               }
250 +       },
251 +
252 +       .rt_flags       = 0
253 +};
254 +
255 +
256 +/* PF_BRIDGE/PRE_ROUTING *********************************************/
257 +static void __br_dnat_complain(void)
258 +{
259 +       static unsigned long last_complaint;
260 +
261 +       if (jiffies - last_complaint >= 5 * HZ) {
262 +               printk(KERN_WARNING "Performing cross-bridge DNAT requires IP "
263 +                       "forwarding to be enabled\n");
264 +               last_complaint = jiffies;
265 +       }
266 +}
267 +
268 +
269 +/* This requires some explaining. If DNAT has taken place,
270 + * we will need to fix up the destination Ethernet address,
271 + * and this is a tricky process.
272 + *
273 + * There are two cases to consider:
274 + * 1. The packet was DNAT'ed to a device in the same bridge
275 + *    port group as it was received on. We can still bridge
276 + *    the packet.
277 + * 2. The packet was DNAT'ed to a different device, either
278 + *    a non-bridged device or another bridge port group.
279 + *    The packet will need to be routed.
280 + *
281 + * The correct way of distinguishing between these two cases is to
282 + * call ip_route_input() and to look at skb->dst->dev, which is
283 + * changed to the destination device if ip_route_input() succeeds.
284 + *
285 + * Let us first consider the case that ip_route_input() succeeds:
286 + *
287 + * If skb->dst->dev equals the logical bridge device the packet
288 + * came in on, we can consider this bridging. We then call
289 + * skb->dst->output() which will make the packet enter br_nf_local_out()
290 + * not much later. In that function it is assured that the iptables
291 + * FORWARD chain is traversed for the packet.
292 + *
293 + * Otherwise, the packet is considered to be routed and we just
294 + * change the destination MAC address so that the packet will
295 + * later be passed up to the IP stack to be routed.
296 + *
297 + * Let us now consider the case that ip_route_input() fails:
298 + *
299 + * After a "echo '0' > /proc/sys/net/ipv4/ip_forward" ip_route_input()
300 + * will fail, while __ip_route_output_key() will return success. The source
301 + * address for __ip_route_output_key() is set to zero, so __ip_route_output_key
302 + * thinks we're handling a locally generated packet and won't care
303 + * if IP forwarding is allowed. We send a warning message to the users's
304 + * log telling her to put IP forwarding on.
305 + *
306 + * ip_route_input() will also fail if there is no route available.
307 + * In that case we just drop the packet.
308 + *
309 + * --Lennert, 20020411
310 + * --Bart, 20020416 (updated)
311 + * --Bart, 20021007 (updated)
312 + */
313 +
314 +static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
315 +{
316 +#ifdef CONFIG_NETFILTER_DEBUG
317 +       skb->nf_debug |= (1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_FORWARD);
318 +#endif
319 +
320 +       if (skb->pkt_type == PACKET_OTHERHOST) {
321 +               skb->pkt_type = PACKET_HOST;
322 +               skb->nf_bridge->mask |= BRNF_PKT_TYPE;
323 +       }
324 +       skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
325 +
326 +       skb->dev = bridge_parent(skb->dev);
327 +       if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
328 +               skb_pull(skb, VLAN_HLEN);
329 +               skb->nh.raw += VLAN_HLEN;
330 +       }
331 +       skb->dst->output(skb);
332 +       return 0;
333 +}
334 +
335 +static int br_nf_pre_routing_finish(struct sk_buff *skb)
336 +{
337 +       struct net_device *dev = skb->dev;
338 +       struct iphdr *iph = skb->nh.iph;
339 +       struct nf_bridge_info *nf_bridge = skb->nf_bridge;
340 +
341 +#ifdef CONFIG_NETFILTER_DEBUG
342 +       skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
343 +#endif
344 +
345 +       if (nf_bridge->mask & BRNF_PKT_TYPE) {
346 +               skb->pkt_type = PACKET_OTHERHOST;
347 +               nf_bridge->mask ^= BRNF_PKT_TYPE;
348 +       }
349 +       nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
350 +
351 +       if (dnat_took_place(skb)) {
352 +               if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
353 +                   dev)) {
354 +                       struct rtable *rt;
355 +                       struct flowi fl = { .nl_u = 
356 +                       { .ip4_u = { .daddr = iph->daddr, .saddr = 0 ,
357 +                                    .tos = iph->tos} }, .proto = 0};
358 +
359 +                       if (!ip_route_output_key(&rt, &fl)) {
360 +                               /* Bridged-and-DNAT'ed traffic doesn't
361 +                                * require ip_forwarding.
362 +                                */
363 +                               if (((struct dst_entry *)rt)->dev == dev) {
364 +                                       skb->dst = (struct dst_entry *)rt;
365 +                                       goto bridged_dnat;
366 +                               }
367 +                               __br_dnat_complain();
368 +                               dst_release((struct dst_entry *)rt);
369 +                       }
370 +                       kfree_skb(skb);
371 +                       return 0;
372 +               } else {
373 +                       if (skb->dst->dev == dev) {
374 +bridged_dnat:
375 +                               /* Tell br_nf_local_out this is a
376 +                                * bridged frame
377 +                                */
378 +                               nf_bridge->mask |= BRNF_BRIDGED_DNAT;
379 +                               skb->dev = nf_bridge->physindev;
380 +                               clear_cb(skb);
381 +                               if (skb->protocol ==
382 +                                   __constant_htons(ETH_P_8021Q)) {
383 +                                       skb_push(skb, VLAN_HLEN);
384 +                                       skb->nh.raw -= VLAN_HLEN;
385 +                               }
386 +                               NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING,
387 +                                              skb, skb->dev, NULL,
388 +                                              br_nf_pre_routing_finish_bridge,
389 +                                              1);
390 +                               return 0;
391 +                       }
392 +                       memcpy(skb->mac.ethernet->h_dest, dev->dev_addr,
393 +                              ETH_ALEN);
394 +                       skb->pkt_type = PACKET_HOST;
395 +               }
396 +       } else {
397 +               skb->dst = (struct dst_entry *)&__fake_rtable;
398 +               dst_hold(skb->dst);
399 +       }
400 +
401 +       clear_cb(skb);
402 +       skb->dev = nf_bridge->physindev;
403 +       if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
404 +               skb_push(skb, VLAN_HLEN);
405 +               skb->nh.raw -= VLAN_HLEN;
406 +       }
407 +       NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
408 +                      br_handle_frame_finish, 1);
409 +
410 +       return 0;
411 +}
412 +
413 +/* Replicate the checks that IPv4 does on packet reception.
414 + * Set skb->dev to the bridge device (i.e. parent of the
415 + * receiving device) to make netfilter happy, the REDIRECT
416 + * target in particular.  Save the original destination IP
417 + * address to be able to detect DNAT afterwards.
418 + */
419 +static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
420 +   const struct net_device *in, const struct net_device *out,
421 +   int (*okfn)(struct sk_buff *))
422 +{
423 +       struct iphdr *iph;
424 +       __u32 len;
425 +       struct sk_buff *skb = *pskb;
426 +       struct nf_bridge_info *nf_bridge;
427 +
428 +       if (skb->protocol != __constant_htons(ETH_P_IP)) {
429 +               struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)
430 +                                         ((*pskb)->mac.ethernet);
431 +
432 +               if (!IS_VLAN_IP)
433 +                       return NF_ACCEPT;
434 +               if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
435 +                       goto out;
436 +               skb_pull(*pskb, VLAN_HLEN);
437 +               (*pskb)->nh.raw += VLAN_HLEN;
438 +       } else if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
439 +               goto out;
440 +
441 +       if (!pskb_may_pull(skb, sizeof(struct iphdr)))
442 +               goto inhdr_error;
443 +
444 +       iph = skb->nh.iph;
445 +       if (iph->ihl < 5 || iph->version != 4)
446 +               goto inhdr_error;
447 +
448 +       if (!pskb_may_pull(skb, 4*iph->ihl))
449 +               goto inhdr_error;
450 +
451 +       iph = skb->nh.iph;
452 +       if (ip_fast_csum((__u8 *)iph, iph->ihl) != 0)
453 +               goto inhdr_error;
454 +
455 +       len = ntohs(iph->tot_len);
456 +       if (skb->len < len || len < 4*iph->ihl)
457 +               goto inhdr_error;
458 +
459 +       if (skb->len > len) {
460 +               __pskb_trim(skb, len);
461 +               if (skb->ip_summed == CHECKSUM_HW)
462 +                       skb->ip_summed = CHECKSUM_NONE;
463 +       }
464 +
465 +#ifdef CONFIG_NETFILTER_DEBUG
466 +       skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING);
467 +#endif
468 +       if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
469 +               return NF_DROP;
470 +
471 +       if (skb->pkt_type == PACKET_OTHERHOST) {
472 +               skb->pkt_type = PACKET_HOST;
473 +               nf_bridge->mask |= BRNF_PKT_TYPE;
474 +       }
475 +
476 +       nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
477 +       nf_bridge->physindev = skb->dev;
478 +       skb->dev = bridge_parent(skb->dev);
479 +       store_orig_dstaddr(skb);
480 +
481 +       NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
482 +               br_nf_pre_routing_finish);
483 +
484 +       return NF_STOLEN;
485 +
486 +inhdr_error:
487 +//     IP_INC_STATS_BH(IpInHdrErrors);
488 +out:
489 +       return NF_DROP;
490 +}
491 +
492 +
493 +/* PF_BRIDGE/LOCAL_IN ************************************************/
494 +/* The packet is locally destined, which requires a real
495 + * dst_entry, so detach the fake one.  On the way up, the
496 + * packet would pass through PRE_ROUTING again (which already
497 + * took place when the packet entered the bridge), but we
498 + * register an IPv4 PRE_ROUTING 'sabotage' hook that will
499 + * prevent this from happening.
500 + */
501 +static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
502 +   const struct net_device *in, const struct net_device *out,
503 +   int (*okfn)(struct sk_buff *))
504 +{
505 +       struct sk_buff *skb = *pskb;
506 +
507 +       if (skb->dst == (struct dst_entry *)&__fake_rtable) {
508 +               dst_release(skb->dst);
509 +               skb->dst = NULL;
510 +       }
511 +
512 +       return NF_ACCEPT;
513 +}
514 +
515 +/* PF_BRIDGE/FORWARD *************************************************/
516 +static int br_nf_forward_finish(struct sk_buff *skb)
517 +{
518 +       struct nf_bridge_info *nf_bridge = skb->nf_bridge;
519 +       struct net_device *in;
520 +       struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
521 +
522 +#ifdef CONFIG_NETFILTER_DEBUG
523 +       skb->nf_debug ^= (1 << NF_BR_FORWARD);
524 +#endif
525 +
526 +       if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) {
527 +               in = nf_bridge->physindev;
528 +               if (nf_bridge->mask & BRNF_PKT_TYPE) {
529 +                       skb->pkt_type = PACKET_OTHERHOST;
530 +                       nf_bridge->mask ^= BRNF_PKT_TYPE;
531 +               }
532 +       } else {
533 +               in = *((struct net_device **)(skb->cb));
534 +       }
535 +       if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
536 +               skb_push(skb, VLAN_HLEN);
537 +               skb->nh.raw -= VLAN_HLEN;
538 +       }
539 +       NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in,
540 +                       skb->dev, br_forward_finish, 1);
541 +       return 0;
542 +}
543 +
544 +/* This is the 'purely bridged' case.  For IP, we pass the packet to
545 + * netfilter with indev and outdev set to the bridge device,
546 + * but we are still able to filter on the 'real' indev/outdev
547 + * because of the ipt_physdev.c module. For ARP, indev and outdev are the
548 + * bridge ports.
549 + */
550 +static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb,
551 +   const struct net_device *in, const struct net_device *out,
552 +   int (*okfn)(struct sk_buff *))
553 +{
554 +       struct sk_buff *skb = *pskb;
555 +       struct nf_bridge_info *nf_bridge;
556 +       struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
557 +
558 +       if (skb->protocol != __constant_htons(ETH_P_IP) &&
559 +           skb->protocol != __constant_htons(ETH_P_ARP)) {
560 +               if (!IS_VLAN_IP && !IS_VLAN_ARP)
561 +                       return NF_ACCEPT;
562 +               skb_pull(*pskb, VLAN_HLEN);
563 +               (*pskb)->nh.raw += VLAN_HLEN;
564 +       }
565 +
566 +#ifdef CONFIG_NETFILTER_DEBUG
567 +       skb->nf_debug ^= (1 << NF_BR_FORWARD);
568 +#endif
569 +       if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) {
570 +               nf_bridge = skb->nf_bridge;
571 +               if (skb->pkt_type == PACKET_OTHERHOST) {
572 +                       skb->pkt_type = PACKET_HOST;
573 +                       nf_bridge->mask |= BRNF_PKT_TYPE;
574 +               }
575 +
576 +               /* The physdev module checks on this */
577 +               nf_bridge->mask |= BRNF_BRIDGED;
578 +               nf_bridge->physoutdev = skb->dev;
579 +
580 +               NF_HOOK(PF_INET, NF_IP_FORWARD, skb, bridge_parent(in),
581 +                       bridge_parent(out), br_nf_forward_finish);
582 +       } else {
583 +               struct net_device **d = (struct net_device **)(skb->cb);
584 +               struct arphdr *arp = skb->nh.arph;
585 +
586 +               if (arp->ar_pln != 4) {
587 +                       if (IS_VLAN_ARP) {
588 +                               skb_push(*pskb, VLAN_HLEN);
589 +                               (*pskb)->nh.raw -= VLAN_HLEN;
590 +                       }
591 +                       return NF_ACCEPT;
592 +               }
593 +               *d = (struct net_device *)in;
594 +               NF_HOOK(NF_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in,
595 +                       (struct net_device *)out, br_nf_forward_finish);
596 +       }
597 +
598 +       return NF_STOLEN;
599 +}
600 +
601 +
602 +/* PF_BRIDGE/LOCAL_OUT ***********************************************/
603 +static int br_nf_local_out_finish(struct sk_buff *skb)
604 +{
605 +#ifdef CONFIG_NETFILTER_DEBUG
606 +       skb->nf_debug &= ~(1 << NF_BR_LOCAL_OUT);
607 +#endif
608 +       if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
609 +               skb_push(skb, VLAN_HLEN);
610 +               skb->nh.raw -= VLAN_HLEN;
611 +       }
612 +
613 +       NF_HOOK_THRESH(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
614 +                       br_forward_finish, NF_BR_PRI_FIRST + 1);
615 +
616 +       return 0;
617 +}
618 +
619 +
620 +/* This function sees both locally originated IP packets and forwarded
621 + * IP packets (in both cases the destination device is a bridge
622 + * device). It also sees bridged-and-DNAT'ed packets.
623 + * To be able to filter on the physical bridge devices (with the ipt_physdev.c
624 + * module), we steal packets destined to a bridge device away from the
625 + * PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later,
626 + * when we have determined the real output device. This is done in here.
627 + *
628 + * If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged
629 + * and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward()
630 + * will then fake the PF_INET/FORWARD hook. br_nf_local_out() has priority
631 + * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor
632 + * will be executed.
633 + * Otherwise, if nf_bridge->physindev is NULL, the bridge-nf code never touched
634 + * this packet before, and so the packet was locally originated. We fake
635 + * the PF_INET/LOCAL_OUT hook.
636 + * Finally, if nf_bridge->physindev isn't NULL, then the packet was IP routed,
637 + * so we fake the PF_INET/FORWARD hook. ipv4_sabotage_out() makes sure
638 + * even routed packets that didn't arrive on a bridge interface have their
639 + * nf_bridge->physindev set.
640 + */
641 +
642 +static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
643 +   const struct net_device *in, const struct net_device *out,
644 +   int (*_okfn)(struct sk_buff *))
645 +{
646 +       int (*okfn)(struct sk_buff *skb);
647 +       struct net_device *realindev;
648 +       struct sk_buff *skb = *pskb;
649 +       struct nf_bridge_info *nf_bridge;
650 +       struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
651 +
652 +       if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
653 +               return NF_ACCEPT;
654 +
655 +       /* Sometimes we get packets with NULL ->dst here (for example,
656 +        * running a dhcp client daemon triggers this).
657 +        */
658 +       if (skb->dst == NULL)
659 +               return NF_ACCEPT;
660 +
661 +       nf_bridge = skb->nf_bridge;
662 +       nf_bridge->physoutdev = skb->dev;
663 +
664 +       realindev = nf_bridge->physindev;
665 +
666 +       /* Bridged, take PF_BRIDGE/FORWARD.
667 +        * (see big note in front of br_nf_pre_routing_finish)
668 +        */
669 +       if (nf_bridge->mask & BRNF_BRIDGED_DNAT) {
670 +               okfn = br_forward_finish;
671 +
672 +               if (nf_bridge->mask & BRNF_PKT_TYPE) {
673 +                       skb->pkt_type = PACKET_OTHERHOST;
674 +                       nf_bridge->mask ^= BRNF_PKT_TYPE;
675 +               }
676 +               if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
677 +                       skb_push(skb, VLAN_HLEN);
678 +                       skb->nh.raw -= VLAN_HLEN;
679 +               }
680 +
681 +               NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev,
682 +                       skb->dev, okfn);
683 +       } else {
684 +               struct net_device *realoutdev = bridge_parent(skb->dev);
685 +
686 +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
687 +               /* iptables should match -o br0.x */
688 +               if (nf_bridge->netoutdev)
689 +                       realoutdev = nf_bridge->netoutdev;
690 +#endif
691 +               okfn = br_nf_local_out_finish;
692 +               if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
693 +                       skb_pull(skb, VLAN_HLEN);
694 +                       (*pskb)->nh.raw += VLAN_HLEN;
695 +               }
696 +               /* IP forwarded traffic has a physindev, locally
697 +                * generated traffic hasn't.
698 +                */
699 +               if (realindev != NULL) {
700 +                       if (((nf_bridge->mask & BRNF_DONT_TAKE_PARENT) == 0) &&
701 +                           has_bridge_parent(realindev))
702 +                               realindev = bridge_parent(realindev);
703 +                       NF_HOOK_THRESH(PF_INET, NF_IP_FORWARD, skb, realindev,
704 +                                      realoutdev, okfn,
705 +                                      NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
706 +               } else {
707 +#ifdef CONFIG_NETFILTER_DEBUG
708 +                       skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);
709 +#endif
710 +
711 +                       NF_HOOK_THRESH(PF_INET, NF_IP_LOCAL_OUT, skb, realindev,
712 +                                      realoutdev, okfn,
713 +                                      NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
714 +               }
715 +       }
716 +
717 +       return NF_STOLEN;
718 +}
719 +
720 +
721 +/* PF_BRIDGE/POST_ROUTING ********************************************/
722 +static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
723 +   const struct net_device *in, const struct net_device *out,
724 +   int (*okfn)(struct sk_buff *))
725 +{
726 +       struct sk_buff *skb = *pskb;
727 +       struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge;
728 +       struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
729 +       struct net_device *realoutdev = bridge_parent(skb->dev);
730 +
731 +       /* Be very paranoid. Must be a device driver bug. */
732 +       if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) {
733 +               printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: "
734 +                                "bad mac.raw pointer.");
735 +               if (skb->dev != NULL) {
736 +                       printk("[%s]", skb->dev->name);
737 +                       if (has_bridge_parent(skb->dev))
738 +                               printk("[%s]", bridge_parent(skb->dev)->name);
739 +               }
740 +               printk(" head:%p, raw:%p\n", skb->head, skb->mac.raw);
741 +               return NF_ACCEPT;
742 +       }
743 +
744 +       if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
745 +               return NF_ACCEPT;
746 +
747 +       /* Sometimes we get packets with NULL ->dst here (for example,
748 +        * running a dhcp client daemon triggers this).
749 +        */
750 +       if (skb->dst == NULL)
751 +               return NF_ACCEPT;
752 +
753 +#ifdef CONFIG_NETFILTER_DEBUG
754 +       skb->nf_debug ^= (1 << NF_IP_POST_ROUTING);
755 +#endif
756 +
757 +       /* We assume any code from br_dev_queue_push_xmit onwards doesn't care
758 +        * about the value of skb->pkt_type.
759 +        */
760 +       if (skb->pkt_type == PACKET_OTHERHOST) {
761 +               skb->pkt_type = PACKET_HOST;
762 +               nf_bridge->mask |= BRNF_PKT_TYPE;
763 +       }
764 +
765 +       if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
766 +               skb_pull(skb, VLAN_HLEN);
767 +               skb->nh.raw += VLAN_HLEN;
768 +       }
769 +
770 +       nf_bridge_save_header(skb);
771 +
772 +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
773 +       if (nf_bridge->netoutdev)
774 +               realoutdev = nf_bridge->netoutdev;
775 +#endif
776 +       NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
777 +               realoutdev, br_dev_queue_push_xmit);
778 +
779 +       return NF_STOLEN;
780 +}
781 +
782 +
783 +/* IPv4/SABOTAGE *****************************************************/
784 +
785 +/* Don't hand locally destined packets to PF_INET/PRE_ROUTING
786 + * for the second time.
787 + */
788 +static unsigned int ipv4_sabotage_in(unsigned int hook, struct sk_buff **pskb,
789 +   const struct net_device *in, const struct net_device *out,
790 +   int (*okfn)(struct sk_buff *))
791 +{
792 +       if ((*pskb)->nf_bridge &&
793 +           !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
794 +               okfn(*pskb);
795 +               return NF_STOLEN;
796 +       }
797 +
798 +       return NF_ACCEPT;
799 +}
800 +
801 +/* Postpone execution of PF_INET/FORWARD, PF_INET/LOCAL_OUT
802 + * and PF_INET/POST_ROUTING until we have done the forwarding
803 + * decision in the bridge code and have determined skb->physoutdev.
804 + */
805 +static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
806 +   const struct net_device *in, const struct net_device *out,
807 +   int (*okfn)(struct sk_buff *))
808 +{
809 +       if ((out->hard_start_xmit == br_dev_xmit &&
810 +           okfn != br_nf_forward_finish &&
811 +           okfn != br_nf_local_out_finish &&
812 +           okfn != br_dev_queue_push_xmit)
813 +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
814 +           || ((out->priv_flags & IFF_802_1Q_VLAN) &&
815 +           VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
816 +#endif
817 +           ) {
818 +               struct sk_buff *skb = *pskb;
819 +               struct nf_bridge_info *nf_bridge;
820 +
821 +               if (!skb->nf_bridge && !nf_bridge_alloc(skb))
822 +                       return NF_DROP;
823 +
824 +               nf_bridge = skb->nf_bridge;
825 +
826 +               /* This frame will arrive on PF_BRIDGE/LOCAL_OUT and we
827 +                * will need the indev then. For a brouter, the real indev
828 +                * can be a bridge port, so we make sure br_nf_local_out()
829 +                * doesn't use the bridge parent of the indev by using
830 +                * the BRNF_DONT_TAKE_PARENT mask.
831 +                */
832 +               if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) {
833 +                       nf_bridge->mask &= BRNF_DONT_TAKE_PARENT;
834 +                       nf_bridge->physindev = (struct net_device *)in;
835 +               }
836 +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
837 +               /* the iptables outdev is br0.x, not br0 */
838 +               if (out->priv_flags & IFF_802_1Q_VLAN)
839 +                       nf_bridge->netoutdev = (struct net_device *)out;
840 +#endif
841 +               okfn(skb);
842 +               return NF_STOLEN;
843 +       }
844 +
845 +       return NF_ACCEPT;
846 +}
847 +
848 +/* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent
849 + * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input.
850 + * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
851 + * ip_refrag() can return NF_STOLEN.
852 + */
853 +static struct nf_hook_ops br_nf_ops[] = {
854 +       { .hook = br_nf_pre_routing, 
855 +         .owner = THIS_MODULE, 
856 +         .pf = PF_BRIDGE, 
857 +         .hooknum = NF_BR_PRE_ROUTING, 
858 +         .priority = NF_BR_PRI_BRNF, },
859 +       { .hook = br_nf_local_in,
860 +         .owner = THIS_MODULE,
861 +         .pf = PF_BRIDGE,
862 +         .hooknum = NF_BR_LOCAL_IN,
863 +         .priority = NF_BR_PRI_BRNF, },
864 +       { .hook = br_nf_forward,
865 +         .owner = THIS_MODULE,
866 +         .pf = PF_BRIDGE,
867 +         .hooknum = NF_BR_FORWARD,
868 +         .priority = NF_BR_PRI_BRNF, },
869 +       { .hook = br_nf_local_out,
870 +         .owner = THIS_MODULE,
871 +         .pf = PF_BRIDGE,
872 +         .hooknum = NF_BR_LOCAL_OUT,
873 +         .priority = NF_BR_PRI_FIRST, },
874 +       { .hook = br_nf_post_routing,
875 +         .owner = THIS_MODULE,
876 +         .pf = PF_BRIDGE,
877 +         .hooknum = NF_BR_POST_ROUTING,
878 +         .priority = NF_BR_PRI_LAST, },
879 +       { .hook = ipv4_sabotage_in,
880 +         .owner = THIS_MODULE,
881 +         .pf = PF_INET,
882 +         .hooknum = NF_IP_PRE_ROUTING,
883 +         .priority = NF_IP_PRI_FIRST, },
884 +       { .hook = ipv4_sabotage_out,
885 +         .owner = THIS_MODULE,
886 +         .pf = PF_INET,
887 +         .hooknum = NF_IP_FORWARD,
888 +         .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD, },
889 +       { .hook = ipv4_sabotage_out,
890 +         .owner = THIS_MODULE,
891 +         .pf = PF_INET,
892 +         .hooknum = NF_IP_LOCAL_OUT,
893 +         .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
894 +       { .hook = ipv4_sabotage_out,
895 +         .owner = THIS_MODULE,
896 +         .pf = PF_INET,
897 +         .hooknum = NF_IP_POST_ROUTING,
898 +         .priority = NF_IP_PRI_FIRST, },
899 +};
900 +
901 +int br_netfilter_init(void)
902 +{
903 +       int i;
904 +
905 +       for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) {
906 +               int ret;
907 +
908 +               if ((ret = nf_register_hook(&br_nf_ops[i])) >= 0)
909 +                       continue;
910 +
911 +               while (i--)
912 +                       nf_unregister_hook(&br_nf_ops[i]);
913 +
914 +               return ret;
915 +       }
916 +
917 +       printk(KERN_NOTICE "Bridge firewalling registered\n");
918 +
919 +       return 0;
920 +}
921 +
922 +void br_netfilter_fini(void)
923 +{
924 +       int i;
925 +
926 +       for (i = ARRAY_SIZE(br_nf_ops) - 1; i >= 0; i--)
927 +               nf_unregister_hook(&br_nf_ops[i]);
928 +}
929 diff -Nur linux-2.6.0-test9.org/net/core/netfilter.c linux-2.6.0-test9/net/core/netfilter.c
930 --- linux-2.6.0-test9.org/net/core/netfilter.c  2003-10-25 20:43:34.000000000 +0200
931 +++ linux-2.6.0-test9/net/core/netfilter.c      2003-11-13 11:01:18.000000000 +0100
932 @@ -8,8 +8,10 @@
933   *
934   * February 2000: Modified by James Morris to have 1 queue per protocol.
935   * 15-Mar-2000:   Added NF_REPEAT --RR.
936 + * 08-May-2003:          Internal logging interface added by Jozsef Kadlecsik.
937   */
938  #include <linux/config.h>
939 +#include <linux/kernel.h>
940  #include <linux/netfilter.h>
941  #include <net/protocol.h>
942  #include <linux/init.h>
943 @@ -743,7 +745,70 @@
944  EXPORT_SYMBOL(skb_ip_make_writable);
945  #endif /*CONFIG_INET*/
946  
947 +/* Internal logging interface, which relies on the real 
948 +   LOG target modules */
949  
950 +#define NF_LOG_PREFIXLEN               128
951 +
952 +static nf_logfn *nf_logging[NPROTO]; /* = NULL */
953 +static int reported = 0;
954 +static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;
955 +
956 +int nf_log_register(int pf, nf_logfn *logfn)
957 +{
958 +       int ret = -EBUSY;
959 +
960 +       /* Any setup of logging members must be done before
961 +        * substituting pointer. */
962 +       smp_wmb();
963 +       spin_lock(&nf_log_lock);
964 +       if (!nf_logging[pf]) {
965 +               nf_logging[pf] = logfn;
966 +               ret = 0;
967 +       }
968 +       spin_unlock(&nf_log_lock);
969 +       return ret;
970 +}              
971 +
972 +void nf_log_unregister(int pf, nf_logfn *logfn)
973 +{
974 +       spin_lock(&nf_log_lock);
975 +       if (nf_logging[pf] == logfn)
976 +               nf_logging[pf] = NULL;
977 +       spin_unlock(&nf_log_lock);
978 +
979 +       /* Give time to concurrent readers. */
980 +       synchronize_net();
981 +}              
982 +
983 +void nf_log_packet(int pf,
984 +                  unsigned int hooknum,
985 +                  const struct sk_buff *skb,
986 +                  const struct net_device *in,
987 +                  const struct net_device *out,
988 +                  const char *fmt, ...)
989 +{
990 +       va_list args;
991 +       char prefix[NF_LOG_PREFIXLEN];
992 +       nf_logfn *logfn;
993 +       
994 +       rcu_read_lock();
995 +       logfn = nf_logging[pf];
996 +       if (logfn) {
997 +               va_start(args, fmt);
998 +               vsnprintf(prefix, sizeof(prefix), fmt, args);
999 +               va_end(args);
1000 +               /* We must read logging before nf_logfn[pf] */
1001 +               smp_read_barrier_depends();
1002 +               logfn(hooknum, skb, in, out, prefix);
1003 +       } else if (!reported) {
1004 +               printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
1005 +                      "no backend logging module loaded in!\n");
1006 +               reported++;
1007 +       }
1008 +       rcu_read_unlock();
1009 +}
1010
1011  /* This does not belong here, but ipt_REJECT needs it if connection
1012     tracking in use: without this, connection may not be in hash table,
1013     and hence manufactured ICMP or RST packets will not be associated
1014 @@ -763,6 +828,9 @@
1015  EXPORT_SYMBOL(ip_ct_attach);
1016  EXPORT_SYMBOL(ip_route_me_harder);
1017  EXPORT_SYMBOL(nf_getsockopt);
1018 +EXPORT_SYMBOL(nf_log_register);
1019 +EXPORT_SYMBOL(nf_log_unregister);
1020 +EXPORT_SYMBOL(nf_log_packet);
1021  EXPORT_SYMBOL(nf_hook_slow);
1022  EXPORT_SYMBOL(nf_hooks);
1023  EXPORT_SYMBOL(nf_register_hook);
1024 diff -Nur linux-2.6.0-test9.org/net/core/netfilter.c.orig linux-2.6.0-test9/net/core/netfilter.c.orig
1025 --- linux-2.6.0-test9.org/net/core/netfilter.c.orig     1970-01-01 01:00:00.000000000 +0100
1026 +++ linux-2.6.0-test9/net/core/netfilter.c.orig 2003-11-13 11:01:18.000000000 +0100
1027 @@ -0,0 +1,840 @@
1028 +/* netfilter.c: look after the filters for various protocols. 
1029 + * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
1030 + *
1031 + * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
1032 + * way.
1033 + *
1034 + * Rusty Russell (C)2000 -- This code is GPL.
1035 + *
1036 + * February 2000: Modified by James Morris to have 1 queue per protocol.
1037 + * 15-Mar-2000:   Added NF_REPEAT --RR.
1038 + * 08-May-2003:          Internal logging interface added by Jozsef Kadlecsik.
1039 + */
1040 +#include <linux/config.h>
1041 +#include <linux/kernel.h>
1042 +#include <linux/netfilter.h>
1043 +#include <net/protocol.h>
1044 +#include <linux/init.h>
1045 +#include <linux/skbuff.h>
1046 +#include <linux/wait.h>
1047 +#include <linux/module.h>
1048 +#include <linux/interrupt.h>
1049 +#include <linux/if.h>
1050 +#include <linux/netdevice.h>
1051 +#include <linux/inetdevice.h>
1052 +#include <linux/tcp.h>
1053 +#include <linux/udp.h>
1054 +#include <linux/icmp.h>
1055 +#include <net/sock.h>
1056 +#include <net/route.h>
1057 +#include <linux/ip.h>
1058 +
1059 +#define __KERNEL_SYSCALLS__
1060 +#include <linux/unistd.h>
1061 +
1062 +/* In this code, we can be waiting indefinitely for userspace to
1063 + * service a packet if a hook returns NF_QUEUE.  We could keep a count
1064 + * of skbuffs queued for userspace, and not deregister a hook unless
1065 + * this is zero, but that sucks.  Now, we simply check when the
1066 + * packets come back: if the hook is gone, the packet is discarded. */
1067 +#ifdef CONFIG_NETFILTER_DEBUG
1068 +#define NFDEBUG(format, args...)  printk(format , ## args)
1069 +#else
1070 +#define NFDEBUG(format, args...)
1071 +#endif
1072 +
1073 +/* Sockopts only registered and called from user context, so
1074 +   net locking would be overkill.  Also, [gs]etsockopt calls may
1075 +   sleep. */
1076 +static DECLARE_MUTEX(nf_sockopt_mutex);
1077 +
1078 +struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
1079 +static LIST_HEAD(nf_sockopts);
1080 +static spinlock_t nf_hook_lock = SPIN_LOCK_UNLOCKED;
1081 +
1082 +/* 
1083 + * A queue handler may be registered for each protocol.  Each is protected by
1084 + * long term mutex.  The handler must provide an an outfn() to accept packets
1085 + * for queueing and must reinject all packets it receives, no matter what.
1086 + */
1087 +static struct nf_queue_handler_t {
1088 +       nf_queue_outfn_t outfn;
1089 +       void *data;
1090 +} queue_handler[NPROTO];
1091 +static rwlock_t queue_handler_lock = RW_LOCK_UNLOCKED;
1092 +
1093 +int nf_register_hook(struct nf_hook_ops *reg)
1094 +{
1095 +       struct list_head *i;
1096 +
1097 +       spin_lock_bh(&nf_hook_lock);
1098 +       list_for_each(i, &nf_hooks[reg->pf][reg->hooknum]) {
1099 +               if (reg->priority < ((struct nf_hook_ops *)i)->priority)
1100 +                       break;
1101 +       }
1102 +       list_add_rcu(&reg->list, i->prev);
1103 +       spin_unlock_bh(&nf_hook_lock);
1104 +
1105 +       synchronize_net();
1106 +       return 0;
1107 +}
1108 +
1109 +void nf_unregister_hook(struct nf_hook_ops *reg)
1110 +{
1111 +       spin_lock_bh(&nf_hook_lock);
1112 +       list_del_rcu(&reg->list);
1113 +       spin_unlock_bh(&nf_hook_lock);
1114 +
1115 +       synchronize_net();
1116 +}
1117 +
1118 +/* Do exclusive ranges overlap? */
1119 +static inline int overlap(int min1, int max1, int min2, int max2)
1120 +{
1121 +       return max1 > min2 && min1 < max2;
1122 +}
1123 +
1124 +/* Functions to register sockopt ranges (exclusive). */
1125 +int nf_register_sockopt(struct nf_sockopt_ops *reg)
1126 +{
1127 +       struct list_head *i;
1128 +       int ret = 0;
1129 +
1130 +       if (down_interruptible(&nf_sockopt_mutex) != 0)
1131 +               return -EINTR;
1132 +
1133 +       list_for_each(i, &nf_sockopts) {
1134 +               struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
1135 +               if (ops->pf == reg->pf
1136 +                   && (overlap(ops->set_optmin, ops->set_optmax, 
1137 +                               reg->set_optmin, reg->set_optmax)
1138 +                       || overlap(ops->get_optmin, ops->get_optmax, 
1139 +                                  reg->get_optmin, reg->get_optmax))) {
1140 +                       NFDEBUG("nf_sock overlap: %u-%u/%u-%u v %u-%u/%u-%u\n",
1141 +                               ops->set_optmin, ops->set_optmax, 
1142 +                               ops->get_optmin, ops->get_optmax, 
1143 +                               reg->set_optmin, reg->set_optmax,
1144 +                               reg->get_optmin, reg->get_optmax);
1145 +                       ret = -EBUSY;
1146 +                       goto out;
1147 +               }
1148 +       }
1149 +
1150 +       list_add(&reg->list, &nf_sockopts);
1151 +out:
1152 +       up(&nf_sockopt_mutex);
1153 +       return ret;
1154 +}
1155 +
1156 +void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
1157 +{
1158 +       /* No point being interruptible: we're probably in cleanup_module() */
1159 + restart:
1160 +       down(&nf_sockopt_mutex);
1161 +       if (reg->use != 0) {
1162 +               /* To be woken by nf_sockopt call... */
1163 +               /* FIXME: Stuart Young's name appears gratuitously. */
1164 +               set_current_state(TASK_UNINTERRUPTIBLE);
1165 +               reg->cleanup_task = current;
1166 +               up(&nf_sockopt_mutex);
1167 +               schedule();
1168 +               goto restart;
1169 +       }
1170 +       list_del(&reg->list);
1171 +       up(&nf_sockopt_mutex);
1172 +}
1173 +
1174 +#ifdef CONFIG_NETFILTER_DEBUG
1175 +#include <net/ip.h>
1176 +#include <net/tcp.h>
1177 +#include <linux/netfilter_ipv4.h>
1178 +
1179 +static void debug_print_hooks_ip(unsigned int nf_debug)
1180 +{
1181 +       if (nf_debug & (1 << NF_IP_PRE_ROUTING)) {
1182 +               printk("PRE_ROUTING ");
1183 +               nf_debug ^= (1 << NF_IP_PRE_ROUTING);
1184 +       }
1185 +       if (nf_debug & (1 << NF_IP_LOCAL_IN)) {
1186 +               printk("LOCAL_IN ");
1187 +               nf_debug ^= (1 << NF_IP_LOCAL_IN);
1188 +       }
1189 +       if (nf_debug & (1 << NF_IP_FORWARD)) {
1190 +               printk("FORWARD ");
1191 +               nf_debug ^= (1 << NF_IP_FORWARD);
1192 +       }
1193 +       if (nf_debug & (1 << NF_IP_LOCAL_OUT)) {
1194 +               printk("LOCAL_OUT ");
1195 +               nf_debug ^= (1 << NF_IP_LOCAL_OUT);
1196 +       }
1197 +       if (nf_debug & (1 << NF_IP_POST_ROUTING)) {
1198 +               printk("POST_ROUTING ");
1199 +               nf_debug ^= (1 << NF_IP_POST_ROUTING);
1200 +       }
1201 +       if (nf_debug)
1202 +               printk("Crap bits: 0x%04X", nf_debug);
1203 +       printk("\n");
1204 +}
1205 +
1206 +void nf_dump_skb(int pf, struct sk_buff *skb)
1207 +{
1208 +       printk("skb: pf=%i %s dev=%s len=%u\n", 
1209 +              pf,
1210 +              skb->sk ? "(owned)" : "(unowned)",
1211 +              skb->dev ? skb->dev->name : "(no dev)",
1212 +              skb->len);
1213 +       switch (pf) {
1214 +       case PF_INET: {
1215 +               const struct iphdr *ip = skb->nh.iph;
1216 +               __u32 *opt = (__u32 *) (ip + 1);
1217 +               int opti;
1218 +               __u16 src_port = 0, dst_port = 0;
1219 +
1220 +               if (ip->protocol == IPPROTO_TCP
1221 +                   || ip->protocol == IPPROTO_UDP) {
1222 +                       struct tcphdr *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);
1223 +                       src_port = ntohs(tcp->source);
1224 +                       dst_port = ntohs(tcp->dest);
1225 +               }
1226 +       
1227 +               printk("PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
1228 +                      " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
1229 +                      ip->protocol, NIPQUAD(ip->saddr),
1230 +                      src_port, NIPQUAD(ip->daddr),
1231 +                      dst_port,
1232 +                      ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
1233 +                      ntohs(ip->frag_off), ip->ttl);
1234 +
1235 +               for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
1236 +                       printk(" O=0x%8.8X", *opt++);
1237 +               printk("\n");
1238 +       }
1239 +       }
1240 +}
1241 +
1242 +void nf_debug_ip_local_deliver(struct sk_buff *skb)
1243 +{
1244 +       /* If it's a loopback packet, it must have come through
1245 +        * NF_IP_LOCAL_OUT, NF_IP_RAW_INPUT, NF_IP_PRE_ROUTING and
1246 +        * NF_IP_LOCAL_IN.  Otherwise, must have gone through
1247 +        * NF_IP_RAW_INPUT and NF_IP_PRE_ROUTING.  */
1248 +       if (!skb->dev) {
1249 +               printk("ip_local_deliver: skb->dev is NULL.\n");
1250 +       }
1251 +       else if (strcmp(skb->dev->name, "lo") == 0) {
1252 +               if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
1253 +                                     | (1 << NF_IP_POST_ROUTING)
1254 +                                     | (1 << NF_IP_PRE_ROUTING)
1255 +                                     | (1 << NF_IP_LOCAL_IN))) {
1256 +                       printk("ip_local_deliver: bad loopback skb: ");
1257 +                       debug_print_hooks_ip(skb->nf_debug);
1258 +                       nf_dump_skb(PF_INET, skb);
1259 +               }
1260 +       }
1261 +       else {
1262 +               if (skb->nf_debug != ((1<<NF_IP_PRE_ROUTING)
1263 +                                     | (1<<NF_IP_LOCAL_IN))) {
1264 +                       printk("ip_local_deliver: bad non-lo skb: ");
1265 +                       debug_print_hooks_ip(skb->nf_debug);
1266 +                       nf_dump_skb(PF_INET, skb);
1267 +               }
1268 +       }
1269 +}
1270 +
1271 +void nf_debug_ip_loopback_xmit(struct sk_buff *newskb)
1272 +{
1273 +       if (newskb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
1274 +                                | (1 << NF_IP_POST_ROUTING))) {
1275 +               printk("ip_dev_loopback_xmit: bad owned skb = %p: ", 
1276 +                      newskb);
1277 +               debug_print_hooks_ip(newskb->nf_debug);
1278 +               nf_dump_skb(PF_INET, newskb);
1279 +       }
1280 +       /* Clear to avoid confusing input check */
1281 +       newskb->nf_debug = 0;
1282 +}
1283 +
1284 +void nf_debug_ip_finish_output2(struct sk_buff *skb)
1285 +{
1286 +       /* If it's owned, it must have gone through the
1287 +        * NF_IP_LOCAL_OUT and NF_IP_POST_ROUTING.
1288 +        * Otherwise, must have gone through
1289 +        * NF_IP_PRE_ROUTING, NF_IP_FORWARD and NF_IP_POST_ROUTING.
1290 +        */
1291 +       if (skb->sk) {
1292 +               if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
1293 +                                     | (1 << NF_IP_POST_ROUTING))) {
1294 +                       printk("ip_finish_output: bad owned skb = %p: ", skb);
1295 +                       debug_print_hooks_ip(skb->nf_debug);
1296 +                       nf_dump_skb(PF_INET, skb);
1297 +               }
1298 +       } else {
1299 +               if (skb->nf_debug != ((1 << NF_IP_PRE_ROUTING)
1300 +                                     | (1 << NF_IP_FORWARD)
1301 +                                     | (1 << NF_IP_POST_ROUTING))) {
1302 +                       /* Fragments, entunnelled packets, TCP RSTs
1303 +                           generated by ipt_REJECT will have no
1304 +                           owners, but still may be local */
1305 +                       if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
1306 +                                             | (1 << NF_IP_POST_ROUTING))){
1307 +                               printk("ip_finish_output:"
1308 +                                      " bad unowned skb = %p: ",skb);
1309 +                               debug_print_hooks_ip(skb->nf_debug);
1310 +                               nf_dump_skb(PF_INET, skb);
1311 +                       }
1312 +               }
1313 +       }
1314 +}
1315 +#endif /*CONFIG_NETFILTER_DEBUG*/
1316 +
1317 +/* Call get/setsockopt() */
1318 +static int nf_sockopt(struct sock *sk, int pf, int val, 
1319 +                     char *opt, int *len, int get)
1320 +{
1321 +       struct list_head *i;
1322 +       struct nf_sockopt_ops *ops;
1323 +       int ret;
1324 +
1325 +       if (down_interruptible(&nf_sockopt_mutex) != 0)
1326 +               return -EINTR;
1327 +
1328 +       list_for_each(i, &nf_sockopts) {
1329 +               ops = (struct nf_sockopt_ops *)i;
1330 +               if (ops->pf == pf) {
1331 +                       if (get) {
1332 +                               if (val >= ops->get_optmin
1333 +                                   && val < ops->get_optmax) {
1334 +                                       ops->use++;
1335 +                                       up(&nf_sockopt_mutex);
1336 +                                       ret = ops->get(sk, val, opt, len);
1337 +                                       goto out;
1338 +                               }
1339 +                       } else {
1340 +                               if (val >= ops->set_optmin
1341 +                                   && val < ops->set_optmax) {
1342 +                                       ops->use++;
1343 +                                       up(&nf_sockopt_mutex);
1344 +                                       ret = ops->set(sk, val, opt, *len);
1345 +                                       goto out;
1346 +                               }
1347 +                       }
1348 +               }
1349 +       }
1350 +       up(&nf_sockopt_mutex);
1351 +       return -ENOPROTOOPT;
1352 +       
1353 + out:
1354 +       down(&nf_sockopt_mutex);
1355 +       ops->use--;
1356 +       if (ops->cleanup_task)
1357 +               wake_up_process(ops->cleanup_task);
1358 +       up(&nf_sockopt_mutex);
1359 +       return ret;
1360 +}
1361 +
1362 +int nf_setsockopt(struct sock *sk, int pf, int val, char *opt,
1363 +                 int len)
1364 +{
1365 +       return nf_sockopt(sk, pf, val, opt, &len, 0);
1366 +}
1367 +
1368 +int nf_getsockopt(struct sock *sk, int pf, int val, char *opt, int *len)
1369 +{
1370 +       return nf_sockopt(sk, pf, val, opt, len, 1);
1371 +}
1372 +
1373 +static unsigned int nf_iterate(struct list_head *head,
1374 +                              struct sk_buff **skb,
1375 +                              int hook,
1376 +                              const struct net_device *indev,
1377 +                              const struct net_device *outdev,
1378 +                              struct list_head **i,
1379 +                              int (*okfn)(struct sk_buff *),
1380 +                              int hook_thresh)
1381 +{
1382 +       /*
1383 +        * The caller must not block between calls to this
1384 +        * function because of risk of continuing from deleted element.
1385 +        */
1386 +       list_for_each_continue_rcu(*i, head) {
1387 +               struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
1388 +
1389 +               if (hook_thresh > elem->priority)
1390 +                       continue;
1391 +
1392 +               /* Optimization: we don't need to hold module
1393 +                   reference here, since function can't sleep. --RR */
1394 +               switch (elem->hook(hook, skb, indev, outdev, okfn)) {
1395 +               case NF_QUEUE:
1396 +                       return NF_QUEUE;
1397 +
1398 +               case NF_STOLEN:
1399 +                       return NF_STOLEN;
1400 +
1401 +               case NF_DROP:
1402 +                       return NF_DROP;
1403 +
1404 +               case NF_REPEAT:
1405 +                       *i = (*i)->prev;
1406 +                       break;
1407 +
1408 +#ifdef CONFIG_NETFILTER_DEBUG
1409 +               case NF_ACCEPT:
1410 +                       break;
1411 +
1412 +               default:
1413 +                       NFDEBUG("Evil return from %p(%u).\n", 
1414 +                               elem->hook, hook);
1415 +#endif
1416 +               }
1417 +       }
1418 +       return NF_ACCEPT;
1419 +}
1420 +
1421 +int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
1422 +{      
1423 +       int ret;
1424 +
1425 +       write_lock_bh(&queue_handler_lock);
1426 +       if (queue_handler[pf].outfn)
1427 +               ret = -EBUSY;
1428 +       else {
1429 +               queue_handler[pf].outfn = outfn;
1430 +               queue_handler[pf].data = data;
1431 +               ret = 0;
1432 +       }
1433 +       write_unlock_bh(&queue_handler_lock);
1434 +
1435 +       return ret;
1436 +}
1437 +
1438 +/* The caller must flush their queue before this */
1439 +int nf_unregister_queue_handler(int pf)
1440 +{
1441 +       write_lock_bh(&queue_handler_lock);
1442 +       queue_handler[pf].outfn = NULL;
1443 +       queue_handler[pf].data = NULL;
1444 +       write_unlock_bh(&queue_handler_lock);
1445 +       
1446 +       return 0;
1447 +}
1448 +
1449 +/* 
1450 + * Any packet that leaves via this function must come back 
1451 + * through nf_reinject().
1452 + */
1453 +static int nf_queue(struct sk_buff *skb, 
1454 +                   struct list_head *elem, 
1455 +                   int pf, unsigned int hook,
1456 +                   struct net_device *indev,
1457 +                   struct net_device *outdev,
1458 +                   int (*okfn)(struct sk_buff *))
1459 +{
1460 +       int status;
1461 +       struct nf_info *info;
1462 +#ifdef CONFIG_BRIDGE_NETFILTER
1463 +       struct net_device *physindev = NULL;
1464 +       struct net_device *physoutdev = NULL;
1465 +#endif
1466 +
1467 +       /* QUEUE == DROP if noone is waiting, to be safe. */
1468 +       read_lock(&queue_handler_lock);
1469 +       if (!queue_handler[pf].outfn) {
1470 +               read_unlock(&queue_handler_lock);
1471 +               kfree_skb(skb);
1472 +               return 1;
1473 +       }
1474 +
1475 +       info = kmalloc(sizeof(*info), GFP_ATOMIC);
1476 +       if (!info) {
1477 +               if (net_ratelimit())
1478 +                       printk(KERN_ERR "OOM queueing packet %p\n",
1479 +                              skb);
1480 +               read_unlock(&queue_handler_lock);
1481 +               kfree_skb(skb);
1482 +               return 1;
1483 +       }
1484 +
1485 +       *info = (struct nf_info) { 
1486 +               (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
1487 +
1488 +       /* If it's going away, ignore hook. */
1489 +       if (!try_module_get(info->elem->owner)) {
1490 +               read_unlock(&queue_handler_lock);
1491 +               kfree(info);
1492 +               return 0;
1493 +       }
1494 +
1495 +       /* Bump dev refs so they don't vanish while packet is out */
1496 +       if (indev) dev_hold(indev);
1497 +       if (outdev) dev_hold(outdev);
1498 +
1499 +#ifdef CONFIG_BRIDGE_NETFILTER
1500 +       if (skb->nf_bridge) {
1501 +               physindev = skb->nf_bridge->physindev;
1502 +               if (physindev) dev_hold(physindev);
1503 +               physoutdev = skb->nf_bridge->physoutdev;
1504 +               if (physoutdev) dev_hold(physoutdev);
1505 +       }
1506 +#endif
1507 +
1508 +       status = queue_handler[pf].outfn(skb, info, queue_handler[pf].data);
1509 +       read_unlock(&queue_handler_lock);
1510 +
1511 +       if (status < 0) {
1512 +               /* James M doesn't say fuck enough. */
1513 +               if (indev) dev_put(indev);
1514 +               if (outdev) dev_put(outdev);
1515 +#ifdef CONFIG_BRIDGE_NETFILTER
1516 +               if (physindev) dev_put(physindev);
1517 +               if (physoutdev) dev_put(physoutdev);
1518 +#endif
1519 +               module_put(info->elem->owner);
1520 +               kfree(info);
1521 +               kfree_skb(skb);
1522 +               return 1;
1523 +       }
1524 +       return 1;
1525 +}
1526 +
1527 +int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
1528 +                struct net_device *indev,
1529 +                struct net_device *outdev,
1530 +                int (*okfn)(struct sk_buff *),
1531 +                int hook_thresh)
1532 +{
1533 +       struct list_head *elem;
1534 +       unsigned int verdict;
1535 +       int ret = 0;
1536 +
1537 +       if (skb->ip_summed == CHECKSUM_HW) {
1538 +               if (outdev == NULL) {
1539 +                       skb->ip_summed = CHECKSUM_NONE;
1540 +               } else {
1541 +                       skb_checksum_help(skb);
1542 +               }
1543 +       }
1544 +
1545 +       /* We may already have this, but read-locks nest anyway */
1546 +       rcu_read_lock();
1547 +
1548 +#ifdef CONFIG_NETFILTER_DEBUG
1549 +       if (skb->nf_debug & (1 << hook)) {
1550 +               printk("nf_hook: hook %i already set.\n", hook);
1551 +               nf_dump_skb(pf, skb);
1552 +       }
1553 +       skb->nf_debug |= (1 << hook);
1554 +#endif
1555 +
1556 +       elem = &nf_hooks[pf][hook];
1557 + next_hook:
1558 +       verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev,
1559 +                            outdev, &elem, okfn, hook_thresh);
1560 +       if (verdict == NF_QUEUE) {
1561 +               NFDEBUG("nf_hook: Verdict = QUEUE.\n");
1562 +               if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn))
1563 +                       goto next_hook;
1564 +       }
1565 +
1566 +       switch (verdict) {
1567 +       case NF_ACCEPT:
1568 +               ret = okfn(skb);
1569 +               break;
1570 +
1571 +       case NF_DROP:
1572 +               kfree_skb(skb);
1573 +               ret = -EPERM;
1574 +               break;
1575 +       }
1576 +
1577 +       rcu_read_unlock();
1578 +       return ret;
1579 +}
1580 +
1581 +void nf_reinject(struct sk_buff *skb, struct nf_info *info,
1582 +                unsigned int verdict)
1583 +{
1584 +       struct list_head *elem = &info->elem->list;
1585 +       struct list_head *i;
1586 +
1587 +       rcu_read_lock();
1588 +
1589 +       /* Release those devices we held, or Alexey will kill me. */
1590 +       if (info->indev) dev_put(info->indev);
1591 +       if (info->outdev) dev_put(info->outdev);
1592 +#ifdef CONFIG_BRIDGE_NETFILTER
1593 +       if (skb->nf_bridge) {
1594 +               if (skb->nf_bridge->physindev)
1595 +                       dev_put(skb->nf_bridge->physindev);
1596 +               if (skb->nf_bridge->physoutdev)
1597 +                       dev_put(skb->nf_bridge->physoutdev);
1598 +       }
1599 +#endif
1600 +
1601 +       /* Drop reference to owner of hook which queued us. */
1602 +       module_put(info->elem->owner);
1603 +
1604 +       list_for_each_rcu(i, &nf_hooks[info->pf][info->hook]) {
1605 +               if (i == elem) 
1606 +                       break;
1607 +       }
1608 +  
1609 +       if (elem == &nf_hooks[info->pf][info->hook]) {
1610 +               /* The module which sent it to userspace is gone. */
1611 +               NFDEBUG("%s: module disappeared, dropping packet.\n",
1612 +                       __FUNCTION__);
1613 +               verdict = NF_DROP;
1614 +       }
1615 +
1616 +       /* Continue traversal iff userspace said ok... */
1617 +       if (verdict == NF_REPEAT) {
1618 +               elem = elem->prev;
1619 +               verdict = NF_ACCEPT;
1620 +       }
1621 +
1622 +       if (verdict == NF_ACCEPT) {
1623 +       next_hook:
1624 +               verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
1625 +                                    &skb, info->hook, 
1626 +                                    info->indev, info->outdev, &elem,
1627 +                                    info->okfn, INT_MIN);
1628 +       }
1629 +
1630 +       switch (verdict) {
1631 +       case NF_ACCEPT:
1632 +               info->okfn(skb);
1633 +               break;
1634 +
1635 +       case NF_QUEUE:
1636 +               if (!nf_queue(skb, elem, info->pf, info->hook, 
1637 +                             info->indev, info->outdev, info->okfn))
1638 +                       goto next_hook;
1639 +               break;
1640 +       }
1641 +       rcu_read_unlock();
1642 +
1643 +       if (verdict == NF_DROP)
1644 +               kfree_skb(skb);
1645 +
1646 +       kfree(info);
1647 +       return;
1648 +}
1649 +
1650 +#ifdef CONFIG_INET
1651 +/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
1652 +int ip_route_me_harder(struct sk_buff **pskb)
1653 +{
1654 +       struct iphdr *iph = (*pskb)->nh.iph;
1655 +       struct rtable *rt;
1656 +       struct flowi fl = {};
1657 +       struct dst_entry *odst;
1658 +       unsigned int hh_len;
1659 +
1660 +       /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
1661 +        * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook.
1662 +        */
1663 +       if (inet_addr_type(iph->saddr) == RTN_LOCAL) {
1664 +               fl.nl_u.ip4_u.daddr = iph->daddr;
1665 +               fl.nl_u.ip4_u.saddr = iph->saddr;
1666 +               fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
1667 +               fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
1668 +#ifdef CONFIG_IP_ROUTE_FWMARK
1669 +               fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
1670 +#endif
1671 +               if (ip_route_output_key(&rt, &fl) != 0)
1672 +                       return -1;
1673 +
1674 +               /* Drop old route. */
1675 +               dst_release((*pskb)->dst);
1676 +               (*pskb)->dst = &rt->u.dst;
1677 +       } else {
1678 +               /* non-local src, find valid iif to satisfy
1679 +                * rp-filter when calling ip_route_input. */
1680 +               fl.nl_u.ip4_u.daddr = iph->saddr;
1681 +               if (ip_route_output_key(&rt, &fl) != 0)
1682 +                       return -1;
1683 +
1684 +               odst = (*pskb)->dst;
1685 +               if (ip_route_input(*pskb, iph->daddr, iph->saddr,
1686 +                                  RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
1687 +                       dst_release(&rt->u.dst);
1688 +                       return -1;
1689 +               }
1690 +               dst_release(&rt->u.dst);
1691 +               dst_release(odst);
1692 +       }
1693 +       
1694 +       if ((*pskb)->dst->error)
1695 +               return -1;
1696 +
1697 +       /* Change in oif may mean change in hh_len. */
1698 +       hh_len = (*pskb)->dst->dev->hard_header_len;
1699 +       if (skb_headroom(*pskb) < hh_len) {
1700 +               struct sk_buff *nskb;
1701 +
1702 +               nskb = skb_realloc_headroom(*pskb, hh_len);
1703 +               if (!nskb) 
1704 +                       return -1;
1705 +               if ((*pskb)->sk)
1706 +                       skb_set_owner_w(nskb, (*pskb)->sk);
1707 +               kfree_skb(*pskb);
1708 +               *pskb = nskb;
1709 +       }
1710 +
1711 +       return 0;
1712 +}
1713 +
1714 +int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
1715 +{
1716 +       struct sk_buff *nskb;
1717 +       unsigned int iplen;
1718 +
1719 +       if (writable_len > (*pskb)->len)
1720 +               return 0;
1721 +
1722 +       /* Not exclusive use of packet?  Must copy. */
1723 +       if (skb_shared(*pskb) || skb_cloned(*pskb))
1724 +               goto copy_skb;
1725 +
1726 +       /* Alexey says IP hdr is always modifiable and linear, so ok. */
1727 +       if (writable_len <= (*pskb)->nh.iph->ihl*4)
1728 +               return 1;
1729 +
1730 +       iplen = writable_len - (*pskb)->nh.iph->ihl*4;
1731 +
1732 +       /* DaveM says protocol headers are also modifiable. */
1733 +       switch ((*pskb)->nh.iph->protocol) {
1734 +       case IPPROTO_TCP: {
1735 +               struct tcphdr hdr;
1736 +               if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4,
1737 +                                 &hdr, sizeof(hdr)) != 0)
1738 +                       goto copy_skb;
1739 +               if (writable_len <= (*pskb)->nh.iph->ihl*4 + hdr.doff*4)
1740 +                       goto pull_skb;
1741 +               goto copy_skb;
1742 +       }
1743 +       case IPPROTO_UDP:
1744 +               if (writable_len<=(*pskb)->nh.iph->ihl*4+sizeof(struct udphdr))
1745 +                       goto pull_skb;
1746 +               goto copy_skb;
1747 +       case IPPROTO_ICMP:
1748 +               if (writable_len
1749 +                   <= (*pskb)->nh.iph->ihl*4 + sizeof(struct icmphdr))
1750 +                       goto pull_skb;
1751 +               goto copy_skb;
1752 +       /* Insert other cases here as desired */
1753 +       }
1754 +
1755 +copy_skb:
1756 +       nskb = skb_copy(*pskb, GFP_ATOMIC);
1757 +       if (!nskb)
1758 +               return 0;
1759 +       BUG_ON(skb_is_nonlinear(nskb));
1760 +
1761 +       /* Rest of kernel will get very unhappy if we pass it a
1762 +          suddenly-orphaned skbuff */
1763 +       if ((*pskb)->sk)
1764 +               skb_set_owner_w(nskb, (*pskb)->sk);
1765 +       kfree_skb(*pskb);
1766 +       *pskb = nskb;
1767 +       return 1;
1768 +
1769 +pull_skb:
1770 +       return pskb_may_pull(*pskb, writable_len);
1771 +}
1772 +EXPORT_SYMBOL(skb_ip_make_writable);
1773 +#endif /*CONFIG_INET*/
1774 +
1775 +/* Internal logging interface, which relies on the real 
1776 +   LOG target modules */
1777 +
1778 +#define NF_LOG_PREFIXLEN               128
1779 +
1780 +static nf_logfn *nf_logging[NPROTO]; /* = NULL */
1781 +static int reported = 0;
1782 +static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;
1783 +
1784 +int nf_log_register(int pf, nf_logfn *logfn)
1785 +{
1786 +       int ret = -EBUSY;
1787 +
1788 +       /* Any setup of logging members must be done before
1789 +        * substituting pointer. */
1790 +       smp_wmb();
1791 +       spin_lock(&nf_log_lock);
1792 +       if (!nf_logging[pf]) {
1793 +               nf_logging[pf] = logfn;
1794 +               ret = 0;
1795 +       }
1796 +       spin_unlock(&nf_log_lock);
1797 +       return ret;
1798 +}              
1799 +
1800 +void nf_log_unregister(int pf, nf_logfn *logfn)
1801 +{
1802 +       spin_lock(&nf_log_lock);
1803 +       if (nf_logging[pf] == logfn)
1804 +               nf_logging[pf] = NULL;
1805 +       spin_unlock(&nf_log_lock);
1806 +
1807 +       /* Give time to concurrent readers. */
1808 +       synchronize_net();
1809 +}              
1810 +
1811 +void nf_log_packet(int pf,
1812 +                  unsigned int hooknum,
1813 +                  const struct sk_buff *skb,
1814 +                  const struct net_device *in,
1815 +                  const struct net_device *out,
1816 +                  const char *fmt, ...)
1817 +{
1818 +       va_list args;
1819 +       char prefix[NF_LOG_PREFIXLEN];
1820 +       nf_logfn *logfn;
1821 +       
1822 +       rcu_read_lock();
1823 +       logfn = nf_logging[pf];
1824 +       if (logfn) {
1825 +               va_start(args, fmt);
1826 +               vsnprintf(prefix, sizeof(prefix), fmt, args);
1827 +               va_end(args);
1828 +               /* We must read logging before nf_logfn[pf] */
1829 +               smp_read_barrier_depends();
1830 +               logfn(hooknum, skb, in, out, prefix);
1831 +       } else if (!reported) {
1832 +               printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
1833 +                      "no backend logging module loaded in!\n");
1834 +               reported++;
1835 +       }
1836 +       rcu_read_unlock();
1837 +}
1838
1839 +/* This does not belong here, but ipt_REJECT needs it if connection
1840 +   tracking in use: without this, connection may not be in hash table,
1841 +   and hence manufactured ICMP or RST packets will not be associated
1842 +   with it. */
1843 +void (*ip_ct_attach)(struct sk_buff *, struct nf_ct_info *);
1844 +
1845 +void __init netfilter_init(void)
1846 +{
1847 +       int i, h;
1848 +
1849 +       for (i = 0; i < NPROTO; i++) {
1850 +               for (h = 0; h < NF_MAX_HOOKS; h++)
1851 +                       INIT_LIST_HEAD(&nf_hooks[i][h]);
1852 +       }
1853 +}
1854 +
1855 +EXPORT_SYMBOL(ip_ct_attach);
1856 +EXPORT_SYMBOL(ip_route_me_harder);
1857 +EXPORT_SYMBOL(nf_getsockopt);
1858 +EXPORT_SYMBOL(nf_hook_slow);
1859 +EXPORT_SYMBOL(nf_hooks);
1860 +EXPORT_SYMBOL(nf_register_hook);
1861 +EXPORT_SYMBOL(nf_register_queue_handler);
1862 +EXPORT_SYMBOL(nf_register_sockopt);
1863 +EXPORT_SYMBOL(nf_reinject);
1864 +EXPORT_SYMBOL(nf_setsockopt);
1865 +EXPORT_SYMBOL(nf_unregister_hook);
1866 +EXPORT_SYMBOL(nf_unregister_queue_handler);
1867 +EXPORT_SYMBOL(nf_unregister_sockopt);
1868 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/Kconfig linux-2.6.0-test9/net/ipv4/netfilter/Kconfig
1869 --- linux-2.6.0-test9.org/net/ipv4/netfilter/Kconfig    2003-11-13 11:07:50.000000000 +0100
1870 +++ linux-2.6.0-test9/net/ipv4/netfilter/Kconfig        2003-11-13 11:01:48.000000000 +0100
1871 @@ -197,6 +197,15 @@
1872  
1873           To compile it as a module, choose M here.  If unsure, say N.
1874  
1875 +config IP_NF_MATCH_SCTP
1876 +       tristate "SCTP match support"
1877 +       depends on IP_NF_IPTABLES
1878 +       help
1879 +         This match allows iptables to match on the SCTP header.
1880 +
1881 +         If you want to compile it as a module, say M here and read
1882 +         <file:Documentation/modules.txt>. If unsure, say `N'.
1883 +
1884  config IP_NF_MATCH_LENGTH
1885         tristate "LENGTH match support"
1886         depends on IP_NF_IPTABLES
1887 @@ -527,6 +536,42 @@
1888  
1889           To compile it as a module, choose M here.  If unsure, say N.
1890  
1891 +config IP_NF_RAW
1892 +       tristate "Raw table"
1893 +       depends on IP_NF_IPTABLES
1894 +       help
1895 +         This option adds a `raw' table to iptables: see the man page for
1896 +         iptables(8).  This table is the very first in the netfilter
1897 +         framework and hooks in at the PREROUTING and OUTPUT chains.
1898 +         The TRACE and NOTRACK targets can be used in this table only.
1899 +
1900 +         To compile it as a module, choose M here.  If unsure, say N.
1901 +
1902 +config IP_NF_TARGET_TRACE
1903 +       tristate "TRACE target support"
1904 +       depends on IP_NF_RAW
1905 +       help
1906 +         The TRACE target allows packets to be traced as those matches
1907 +         any subsequent rule in any table/rule. The matched rule and
1908 +         the packet is logged with the prefix
1909 +         
1910 +         TRACE: tablename/chainname/rulenum
1911 +         
1912 +         if the ipt_LOG or ipt_ULOG targets are loaded in.
1913 +
1914 +         To compile it as a module, choose M here.  If unsure, say N.
1915 +
1916 +config IP_NF_TARGET_NOTRACK
1917 +       tristate "NOTRACK target support"
1918 +       depends on IP_NF_RAW
1919 +       help
1920 +         The NOTRACK target allows a select rule to specify which
1921 +         packets *not* to enter the conntrack/NAT subsystems
1922 +         with all the consequences (no ICMP error tracking,
1923 +         no protocol helpers for the selected packets).
1924 +
1925 +         To compile it as a module, choose M here.  If unsure, say N.
1926 +
1927  config IP_NF_ARPTABLES
1928         tristate "ARP tables support"
1929  
1930 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/Kconfig.orig linux-2.6.0-test9/net/ipv4/netfilter/Kconfig.orig
1931 --- linux-2.6.0-test9.org/net/ipv4/netfilter/Kconfig.orig       1970-01-01 01:00:00.000000000 +0100
1932 +++ linux-2.6.0-test9/net/ipv4/netfilter/Kconfig.orig   2003-11-13 11:01:38.000000000 +0100
1933 @@ -0,0 +1,606 @@
1934 +#
1935 +# IP netfilter configuration
1936 +#
1937 +
1938 +menu "IP: Netfilter Configuration"
1939 +       depends on INET && NETFILTER
1940 +
1941 +config IP_NF_CONNTRACK
1942 +       tristate "Connection tracking (required for masq/NAT)"
1943 +       ---help---
1944 +         Connection tracking keeps a record of what packets have passed
1945 +         through your machine, in order to figure out how they are related
1946 +         into connections.
1947 +
1948 +         This is required to do Masquerading or other kinds of Network
1949 +         Address Translation (except for Fast NAT).  It can also be used to
1950 +         enhance packet filtering (see `Connection state match support'
1951 +         below).
1952 +
1953 +         To compile it as a module, choose M here.  If unsure, say N.
1954 +
1955 +config IP_NF_FTP
1956 +       tristate "FTP protocol support"
1957 +       depends on IP_NF_CONNTRACK
1958 +       help
1959 +         Tracking FTP connections is problematic: special helpers are
1960 +         required for tracking them, and doing masquerading and other forms
1961 +         of Network Address Translation on them.
1962 +
1963 +         To compile it as a module, choose M here.  If unsure, say Y.
1964 +
1965 +config IP_NF_IRC
1966 +       tristate "IRC protocol support"
1967 +       depends on IP_NF_CONNTRACK
1968 +       ---help---
1969 +         There is a commonly-used extension to IRC called
1970 +         Direct Client-to-Client Protocol (DCC).  This enables users to send
1971 +         files to each other, and also chat to each other without the need
1972 +         of a server.  DCC Sending is used anywhere you send files over IRC,
1973 +         and DCC Chat is most commonly used by Eggdrop bots.  If you are
1974 +         using NAT, this extension will enable you to send files and initiate
1975 +         chats.  Note that you do NOT need this extension to get files or
1976 +         have others initiate chats, or everything else in IRC.
1977 +
1978 +         To compile it as a module, choose M here.  If unsure, say Y.
1979 +
1980 +config IP_NF_TFTP
1981 +       tristate "TFTP protocol support"
1982 +       depends on IP_NF_CONNTRACK
1983 +       help
1984 +         TFTP connection tracking helper, this is required depending
1985 +         on how restrictive your ruleset is.
1986 +         If you are using a tftp client behind -j SNAT or -j MASQUERADING
1987 +         you will need this.
1988 +
1989 +         To compile it as a module, choose M here.  If unsure, say Y.
1990 +
1991 +config IP_NF_AMANDA
1992 +       tristate "Amanda backup protocol support"
1993 +       depends on IP_NF_CONNTRACK
1994 +       help
1995 +         If you are running the Amanda backup package <http://www.amanda.org/>
1996 +         on this machine or machines that will be MASQUERADED through this
1997 +         machine, then you may want to enable this feature.  This allows the
1998 +         connection tracking and natting code to allow the sub-channels that
1999 +         Amanda requires for communication of the backup data, messages and
2000 +         index.
2001 +
2002 +         To compile it as a module, choose M here.  If unsure, say Y.
2003 +
2004 +config IP_NF_QUEUE
2005 +       tristate "Userspace queueing via NETLINK"
2006 +       help
2007 +         Netfilter has the ability to queue packets to user space: the
2008 +         netlink device can be used to access them using this driver.
2009 +
2010 +         To compile it as a module, choose M here.  If unsure, say N.
2011 +
2012 +config IP_NF_IPTABLES
2013 +       tristate "IP tables support (required for filtering/masq/NAT)"
2014 +       help
2015 +         iptables is a general, extensible packet identification framework.
2016 +         The packet filtering and full NAT (masquerading, port forwarding,
2017 +         etc) subsystems now use this: say `Y' or `M' here if you want to use
2018 +         either of those.
2019 +
2020 +         To compile it as a module, choose M here.  If unsure, say N.
2021 +
2022 +# The simple matches.
2023 +config IP_NF_MATCH_LIMIT
2024 +       tristate "limit match support"
2025 +       depends on IP_NF_IPTABLES
2026 +       help
2027 +         limit matching allows you to control the rate at which a rule can be
2028 +         matched: mainly useful in combination with the LOG target ("LOG
2029 +         target support", below) and to avoid some Denial of Service attacks.
2030 +
2031 +         To compile it as a module, choose M here.  If unsure, say N.
2032 +
2033 +config IP_NF_MATCH_IPRANGE
2034 +       tristate "IP range match support"
2035 +       depends on IP_NF_IPTABLES
2036 +       help
2037 +         This option makes possible to match IP addresses against IP address
2038 +         ranges.
2039 +
2040 +         To compile it as a module, choose M here.  If unsure, say N.
2041 +
2042 +config IP_NF_MATCH_MAC
2043 +       tristate "MAC address match support"
2044 +       depends on IP_NF_IPTABLES
2045 +       help
2046 +         MAC matching allows you to match packets based on the source
2047 +         Ethernet address of the packet.
2048 +
2049 +         To compile it as a module, choose M here.  If unsure, say N.
2050 +
2051 +config IP_NF_MATCH_PKTTYPE
2052 +       tristate "Packet type match support"
2053 +       depends on IP_NF_IPTABLES
2054 +       help
2055 +         Packet type matching allows you to match a packet by
2056 +         its "class", eg. BROADCAST, MULTICAST, ...
2057 +
2058 +         Typical usage:
2059 +         iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
2060 +
2061 +         To compile it as a module, choose M here.  If unsure, say N.
2062 +
2063 +config IP_NF_MATCH_MARK
2064 +       tristate "netfilter MARK match support"
2065 +       depends on IP_NF_IPTABLES
2066 +       help
2067 +         Netfilter mark matching allows you to match packets based on the
2068 +         `nfmark' value in the packet.  This can be set by the MARK target
2069 +         (see below).
2070 +
2071 +         To compile it as a module, choose M here.  If unsure, say N.
2072 +
2073 +config IP_NF_MATCH_MULTIPORT
2074 +       tristate "Multiple port match support"
2075 +       depends on IP_NF_IPTABLES
2076 +       help
2077 +         Multiport matching allows you to match TCP or UDP packets based on
2078 +         a series of source or destination ports: normally a rule can only
2079 +         match a single range of ports.
2080 +
2081 +         To compile it as a module, choose M here.  If unsure, say N.
2082 +
2083 +config IP_NF_MATCH_TOS
2084 +       tristate "TOS match support"
2085 +       depends on IP_NF_IPTABLES
2086 +       help
2087 +         TOS matching allows you to match packets based on the Type Of
2088 +         Service fields of the IP packet.
2089 +
2090 +         To compile it as a module, choose M here.  If unsure, say N.
2091 +
2092 +config IP_NF_MATCH_RECENT
2093 +       tristate "recent match support"
2094 +       depends on IP_NF_IPTABLES
2095 +       help
2096 +         This match is used for creating one or many lists of recently
2097 +         used addresses and then matching against that/those list(s).
2098 +
2099 +         Short options are available by using 'iptables -m recent -h'
2100 +         Official Website: <http://snowman.net/projects/ipt_recent/>
2101 +
2102 +         To compile it as a module, choose M here.  If unsure, say N.
2103 +
2104 +config IP_NF_MATCH_ECN
2105 +       tristate "ECN match support"
2106 +       depends on IP_NF_IPTABLES
2107 +       help
2108 +         This option adds a `ECN' match, which allows you to match against
2109 +         the IPv4 and TCP header ECN fields.
2110 +
2111 +         To compile it as a module, choose M here.  If unsure, say N.
2112 +
2113 +config IP_NF_MATCH_DSCP
2114 +       tristate "DSCP match support"
2115 +       depends on IP_NF_IPTABLES
2116 +       help
2117 +         This option adds a `DSCP' match, which allows you to match against
2118 +         the IPv4 header DSCP field (DSCP codepoint).
2119 +
2120 +         The DSCP codepoint can have any value between 0x0 and 0x4f.
2121 +
2122 +         To compile it as a module, choose M here.  If unsure, say N.
2123 +
2124 +config IP_NF_MATCH_AH_ESP
2125 +       tristate "AH/ESP match support"
2126 +       depends on IP_NF_IPTABLES
2127 +       help
2128 +         These two match extensions (`ah' and `esp') allow you to match a
2129 +         range of SPIs inside AH or ESP headers of IPSec packets.
2130 +
2131 +         To compile it as a module, choose M here.  If unsure, say N.
2132 +
2133 +config IP_NF_MATCH_LENGTH
2134 +       tristate "LENGTH match support"
2135 +       depends on IP_NF_IPTABLES
2136 +       help
2137 +         This option allows you to match the length of a packet against a
2138 +         specific value or range of values.
2139 +
2140 +         To compile it as a module, choose M here.  If unsure, say N.
2141 +
2142 +config IP_NF_MATCH_TTL
2143 +       tristate "TTL match support"
2144 +       depends on IP_NF_IPTABLES
2145 +       help
2146 +         This adds CONFIG_IP_NF_MATCH_TTL option, which enabled the user
2147 +         to match packets by their TTL value.
2148 +
2149 +         To compile it as a module, choose M here.  If unsure, say N.
2150 +
2151 +config IP_NF_MATCH_TCPMSS
2152 +       tristate "tcpmss match support"
2153 +       depends on IP_NF_IPTABLES
2154 +       help
2155 +         This option adds a `tcpmss' match, which allows you to examine the
2156 +         MSS value of TCP SYN packets, which control the maximum packet size
2157 +         for that connection.
2158 +
2159 +         To compile it as a module, choose M here.  If unsure, say N.
2160 +
2161 +config IP_NF_MATCH_HELPER
2162 +       tristate "Helper match support"
2163 +       depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
2164 +       help
2165 +         Helper matching allows you to match packets in dynamic connections
2166 +         tracked by a conntrack-helper, ie. ip_conntrack_ftp
2167 +
2168 +         To compile it as a module, choose M here.  If unsure, say Y.
2169 +
2170 +config IP_NF_MATCH_STATE
2171 +       tristate "Connection state match support"
2172 +       depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
2173 +       help
2174 +         Connection state matching allows you to match packets based on their
2175 +         relationship to a tracked connection (ie. previous packets).  This
2176 +         is a powerful tool for packet classification.
2177 +
2178 +         To compile it as a module, choose M here.  If unsure, say N.
2179 +
2180 +config IP_NF_MATCH_CONNTRACK
2181 +       tristate "Connection tracking match support"
2182 +       depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
2183 +       help
2184 +         This is a general conntrack match module, a superset of the state match.
2185 +
2186 +         It allows matching on additional conntrack information, which is
2187 +         useful in complex configurations, such as NAT gateways with multiple
2188 +         internet links or tunnels.
2189 +
2190 +         To compile it as a module, choose M here.  If unsure, say N.
2191 +
2192 +config IP_NF_MATCH_OWNER
2193 +       tristate "Owner match support"
2194 +       depends on IP_NF_IPTABLES
2195 +       help
2196 +         Packet owner matching allows you to match locally-generated packets
2197 +         based on who created them: the user, group, process or session.
2198 +
2199 +         To compile it as a module, choose M here.  If unsure, say N.
2200 +
2201 +config IP_NF_MATCH_PHYSDEV
2202 +       tristate "Physdev match support"
2203 +       depends on IP_NF_IPTABLES && BRIDGE_NETFILTER
2204 +       help
2205 +         Physdev packet matching matches against the physical bridge ports
2206 +         the IP packet arrived on or will leave by.
2207 +
2208 +         To compile it as a module, choose M here.  If unsure, say N.
2209 +
2210 +# The targets
2211 +config IP_NF_FILTER
2212 +       tristate "Packet filtering"
2213 +       depends on IP_NF_IPTABLES
2214 +       help
2215 +         Packet filtering defines a table `filter', which has a series of
2216 +         rules for simple packet filtering at local input, forwarding and
2217 +         local output.  See the man page for iptables(8).
2218 +
2219 +         To compile it as a module, choose M here.  If unsure, say N.
2220 +
2221 +config IP_NF_TARGET_REJECT
2222 +       tristate "REJECT target support"
2223 +       depends on IP_NF_FILTER
2224 +       help
2225 +         The REJECT target allows a filtering rule to specify that an ICMP
2226 +         error should be issued in response to an incoming packet, rather
2227 +         than silently being dropped.
2228 +
2229 +         To compile it as a module, choose M here.  If unsure, say N.
2230 +
2231 +config IP_NF_NAT
2232 +       tristate "Full NAT"
2233 +       depends on IP_NF_IPTABLES && IP_NF_CONNTRACK
2234 +       help
2235 +         The Full NAT option allows masquerading, port forwarding and other
2236 +         forms of full Network Address Port Translation.  It is controlled by
2237 +         the `nat' table in iptables: see the man page for iptables(8).
2238 +
2239 +         To compile it as a module, choose M here.  If unsure, say N.
2240 +
2241 +config IP_NF_NAT_NEEDED
2242 +       bool
2243 +       depends on IP_NF_CONNTRACK!=y && IP_NF_IPTABLES!=y && (IP_NF_COMPAT_IPCHAINS!=y && IP_NF_COMPAT_IPFWADM || IP_NF_COMPAT_IPCHAINS) || IP_NF_IPTABLES && IP_NF_CONNTRACK && IP_NF_NAT
2244 +       default y
2245 +
2246 +config IP_NF_TARGET_MASQUERADE
2247 +       tristate "MASQUERADE target support"
2248 +       depends on IP_NF_NAT
2249 +       help
2250 +         Masquerading is a special case of NAT: all outgoing connections are
2251 +         changed to seem to come from a particular interface's address, and
2252 +         if the interface goes down, those connections are lost.  This is
2253 +         only useful for dialup accounts with dynamic IP address (ie. your IP
2254 +         address will be different on next dialup).
2255 +
2256 +         To compile it as a module, choose M here.  If unsure, say N.
2257 +
2258 +config IP_NF_TARGET_REDIRECT
2259 +       tristate "REDIRECT target support"
2260 +       depends on IP_NF_NAT
2261 +       help
2262 +         REDIRECT is a special case of NAT: all incoming connections are
2263 +         mapped onto the incoming interface's address, causing the packets to
2264 +         come to the local machine instead of passing through.  This is
2265 +         useful for transparent proxies.
2266 +
2267 +         To compile it as a module, choose M here.  If unsure, say N.
2268 +
2269 +config IP_NF_TARGET_NETMAP
2270 +       tristate "NETMAP target support"
2271 +       depends on IP_NF_NAT
2272 +       help
2273 +         NETMAP is an implementation of static 1:1 NAT mapping of network
2274 +         addresses. It maps the network address part, while keeping the host
2275 +         address part intact. It is similar to Fast NAT, except that
2276 +         Netfilter's connection tracking doesn't work well with Fast NAT.
2277 +
2278 +         To compile it as a module, choose M here.  If unsure, say N.
2279 +
2280 +config IP_NF_TARGET_SAME
2281 +       tristate "SAME target support"
2282 +       depends on IP_NF_NAT
2283 +       help
2284 +         This option adds a `SAME' target, which works like the standard SNAT
2285 +         target, but attempts to give clients the same IP for all connections.
2286 +
2287 +         To compile it as a module, choose M here.  If unsure, say N.
2288 +
2289 +config IP_NF_NAT_LOCAL
2290 +       bool "NAT of local connections (READ HELP)"
2291 +       depends on IP_NF_NAT
2292 +       help
2293 +         This option enables support for NAT of locally originated connections. 
2294 +         Enable this if you need to use destination NAT on connections
2295 +         originating from local processes on the nat box itself.
2296 +
2297 +         Please note that you will need a recent version (>= 1.2.6a)
2298 +         of the iptables userspace program in order to use this feature.
2299 +         See http://www.iptables.org/ for download instructions.
2300 +
2301 +         If unsure, say 'N'.
2302 +
2303 +config IP_NF_NAT_SNMP_BASIC
2304 +       tristate "Basic SNMP-ALG support (EXPERIMENTAL)"
2305 +       depends on EXPERIMENTAL && IP_NF_NAT
2306 +       ---help---
2307 +
2308 +         This module implements an Application Layer Gateway (ALG) for
2309 +         SNMP payloads.  In conjunction with NAT, it allows a network
2310 +         management system to access multiple private networks with
2311 +         conflicting addresses.  It works by modifying IP addresses
2312 +         inside SNMP payloads to match IP-layer NAT mapping.
2313 +
2314 +         This is the "basic" form of SNMP-ALG, as described in RFC 2962
2315 +
2316 +         To compile it as a module, choose M here.  If unsure, say N.
2317 +
2318 +config IP_NF_NAT_IRC
2319 +       tristate
2320 +       depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2321 +       default IP_NF_NAT if IP_NF_IRC=y
2322 +       default m if IP_NF_IRC=m
2323 +
2324 +# If they want FTP, set to $CONFIG_IP_NF_NAT (m or y), 
2325 +# or $CONFIG_IP_NF_FTP (m or y), whichever is weaker.  Argh.
2326 +config IP_NF_NAT_FTP
2327 +       tristate
2328 +       depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2329 +       default IP_NF_NAT if IP_NF_FTP=y
2330 +       default m if IP_NF_FTP=m
2331 +
2332 +config IP_NF_NAT_TFTP
2333 +       tristate
2334 +       depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2335 +       default IP_NF_NAT if IP_NF_TFTP=y
2336 +       default m if IP_NF_TFTP=m
2337 +
2338 +config IP_NF_NAT_AMANDA
2339 +       tristate
2340 +       depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2341 +       default IP_NF_NAT if IP_NF_AMANDA=y
2342 +       default m if IP_NF_AMANDA=m
2343 +
2344 +config IP_NF_MANGLE
2345 +       tristate "Packet mangling"
2346 +       depends on IP_NF_IPTABLES
2347 +       help
2348 +         This option adds a `mangle' table to iptables: see the man page for
2349 +         iptables(8).  This table is used for various packet alterations
2350 +         which can effect how the packet is routed.
2351 +
2352 +         To compile it as a module, choose M here.  If unsure, say N.
2353 +
2354 +config IP_NF_TARGET_TOS
2355 +       tristate "TOS target support"
2356 +       depends on IP_NF_MANGLE
2357 +       help
2358 +         This option adds a `TOS' target, which allows you to create rules in
2359 +         the `mangle' table which alter the Type Of Service field of an IP
2360 +         packet prior to routing.
2361 +
2362 +         To compile it as a module, choose M here.  If unsure, say N.
2363 +
2364 +config IP_NF_TARGET_ECN
2365 +       tristate "ECN target support"
2366 +       depends on IP_NF_MANGLE
2367 +       ---help---
2368 +         This option adds a `ECN' target, which can be used in the iptables mangle
2369 +         table.  
2370 +
2371 +         You can use this target to remove the ECN bits from the IPv4 header of
2372 +         an IP packet.  This is particularly useful, if you need to work around
2373 +         existing ECN blackholes on the internet, but don't want to disable
2374 +         ECN support in general.
2375 +
2376 +         To compile it as a module, choose M here.  If unsure, say N.
2377 +
2378 +config IP_NF_TARGET_DSCP
2379 +       tristate "DSCP target support"
2380 +       depends on IP_NF_MANGLE
2381 +       help
2382 +         This option adds a `DSCP' match, which allows you to match against
2383 +         the IPv4 header DSCP field (DSCP codepoint).
2384 +
2385 +         The DSCP codepoint can have any value between 0x0 and 0x4f.
2386 +
2387 +         To compile it as a module, choose M here.  If unsure, say N.
2388 +
2389 +config IP_NF_TARGET_MARK
2390 +       tristate "MARK target support"
2391 +       depends on IP_NF_MANGLE
2392 +       help
2393 +         This option adds a `MARK' target, which allows you to create rules
2394 +         in the `mangle' table which alter the netfilter mark (nfmark) field
2395 +         associated with the packet prior to routing. This can change
2396 +         the routing method (see `Use netfilter MARK value as routing
2397 +         key') and can also be used by other subsystems to change their
2398 +         behavior.
2399 +
2400 +         To compile it as a module, choose M here.  If unsure, say N.
2401 +
2402 +config IP_NF_TARGET_CLASSIFY
2403 +       tristate "CLASSIFY target support"
2404 +       depends on IP_NF_MANGLE
2405 +       help
2406 +         This option adds a `CLASSIFY' target, which enables the user to set
2407 +         the priority of a packet. Some qdiscs can use this value for
2408 +         classification, among these are:
2409 +
2410 +         atm, cbq, dsmark, pfifo_fast, htb, prio
2411 +
2412 +         To compile it as a module, choose M here.  If unsure, say N.
2413 +
2414 +config IP_NF_TARGET_LOG
2415 +       tristate "LOG target support"
2416 +       depends on IP_NF_IPTABLES
2417 +       help
2418 +         This option adds a `LOG' target, which allows you to create rules in
2419 +         any iptables table which records the packet header to the syslog.
2420 +
2421 +         To compile it as a module, choose M here.  If unsure, say N.
2422 +
2423 +config IP_NF_TARGET_ULOG
2424 +       tristate "ULOG target support"
2425 +       depends on IP_NF_IPTABLES
2426 +       ---help---
2427 +         This option adds a `ULOG' target, which allows you to create rules in
2428 +         any iptables table. The packet is passed to a userspace logging
2429 +         daemon using netlink multicast sockets; unlike the LOG target
2430 +         which can only be viewed through syslog.
2431 +
2432 +         The apropriate userspace logging daemon (ulogd) may be obtained from
2433 +         http://www.gnumonks.org/projects/ulogd
2434 +
2435 +         To compile it as a module, choose M here.  If unsure, say N.
2436 +
2437 +config IP_NF_TARGET_TCPMSS
2438 +       tristate "TCPMSS target support"
2439 +       depends on IP_NF_IPTABLES
2440 +       ---help---
2441 +         This option adds a `TCPMSS' target, which allows you to alter the
2442 +         MSS value of TCP SYN packets, to control the maximum size for that
2443 +         connection (usually limiting it to your outgoing interface's MTU
2444 +         minus 40).
2445 +
2446 +         This is used to overcome criminally braindead ISPs or servers which
2447 +         block ICMP Fragmentation Needed packets.  The symptoms of this
2448 +         problem are that everything works fine from your Linux
2449 +         firewall/router, but machines behind it can never exchange large
2450 +         packets:
2451 +               1) Web browsers connect, then hang with no data received.
2452 +               2) Small mail works fine, but large emails hang.
2453 +               3) ssh works fine, but scp hangs after initial handshaking.
2454 +
2455 +         Workaround: activate this option and add a rule to your firewall
2456 +         configuration like:
2457 +
2458 +         iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
2459 +                        -j TCPMSS --clamp-mss-to-pmtu
2460 +
2461 +         To compile it as a module, choose M here.  If unsure, say N.
2462 +
2463 +config IP_NF_RAW
2464 +       tristate "Raw table"
2465 +       depends on IP_NF_IPTABLES
2466 +       help
2467 +         This option adds a `raw' table to iptables: see the man page for
2468 +         iptables(8).  This table is the very first in the netfilter
2469 +         framework and hooks in at the PREROUTING and OUTPUT chains.
2470 +         The TRACE and NOTRACK targets can be used in this table only.
2471 +
2472 +         To compile it as a module, choose M here.  If unsure, say N.
2473 +
2474 +config IP_NF_TARGET_TRACE
2475 +       tristate "TRACE target support"
2476 +       depends on IP_NF_RAW
2477 +       help
2478 +         The TRACE target allows packets to be traced as those matches
2479 +         any subsequent rule in any table/rule. The matched rule and
2480 +         the packet is logged with the prefix
2481 +         
2482 +         TRACE: tablename/chainname/rulenum
2483 +         
2484 +         if the ipt_LOG or ipt_ULOG targets are loaded in.
2485 +
2486 +         To compile it as a module, choose M here.  If unsure, say N.
2487 +
2488 +config IP_NF_TARGET_NOTRACK
2489 +       tristate "NOTRACK target support"
2490 +       depends on IP_NF_RAW
2491 +       help
2492 +         The NOTRACK target allows a select rule to specify which
2493 +         packets *not* to enter the conntrack/NAT subsystems
2494 +         with all the consequences (no ICMP error tracking,
2495 +         no protocol helpers for the selected packets).
2496 +
2497 +         To compile it as a module, choose M here.  If unsure, say N.
2498 +
2499 +config IP_NF_ARPTABLES
2500 +       tristate "ARP tables support"
2501 +
2502 +config IP_NF_ARPFILTER
2503 +       tristate "ARP packet filtering"
2504 +       depends on IP_NF_ARPTABLES
2505 +
2506 +config IP_NF_ARP_MANGLE
2507 +       tristate "ARP payload mangling"
2508 +       depends on IP_NF_ARPTABLES
2509 +       help
2510 +         Allows altering the ARP packet payload: source and destination
2511 +         hardware and network addresses.
2512 +
2513 +# Backwards compatibility modules: only if you don't build in the others.
2514 +config IP_NF_COMPAT_IPCHAINS
2515 +       tristate "ipchains (2.2-style) support"
2516 +       depends on IP_NF_CONNTRACK!=y && IP_NF_IPTABLES!=y
2517 +       help
2518 +         This option places ipchains (with masquerading and redirection
2519 +         support) back into the kernel, using the new netfilter
2520 +         infrastructure.  It is not recommended for new installations (see
2521 +         `Packet filtering').  With this enabled, you should be able to use
2522 +         the ipchains tool exactly as in 2.2 kernels.
2523 +
2524 +         To compile it as a module, choose M here.  If unsure, say N.
2525 +
2526 +config IP_NF_COMPAT_IPFWADM
2527 +       tristate "ipfwadm (2.0-style) support"
2528 +       depends on IP_NF_CONNTRACK!=y && IP_NF_IPTABLES!=y && IP_NF_COMPAT_IPCHAINS!=y
2529 +       help
2530 +         This option places ipfwadm (with masquerading and redirection
2531 +         support) back into the kernel, using the new netfilter
2532 +         infrastructure.  It is not recommended for new installations (see
2533 +         `Packet filtering').  With this enabled, you should be able to use
2534 +         the ipfwadm tool exactly as in 2.0 kernels.
2535 +
2536 +         To compile it as a module, choose M here.  If unsure, say N.
2537 +
2538 +endmenu
2539 +
2540 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/Makefile linux-2.6.0-test9/net/ipv4/netfilter/Makefile
2541 --- linux-2.6.0-test9.org/net/ipv4/netfilter/Makefile   2003-10-25 20:43:07.000000000 +0200
2542 +++ linux-2.6.0-test9/net/ipv4/netfilter/Makefile       2003-11-13 11:01:48.000000000 +0100
2543 @@ -34,12 +34,14 @@
2544  # generic IP tables 
2545  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
2546  
2547 -# the three instances of ip_tables
2548 +# the four instances of ip_tables
2549  obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
2550  obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
2551  obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
2552 +obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
2553  
2554  # matches
2555 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
2556  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
2557  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
2558  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
2559 @@ -81,6 +83,8 @@
2560  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
2561  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
2562  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
2563 +obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
2564 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
2565  
2566  # generic ARP tables
2567  obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
2568 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.0-test9/net/ipv4/netfilter/ip_conntrack_core.c
2569 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_conntrack_core.c        2003-10-25 20:42:41.000000000 +0200
2570 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_conntrack_core.c    2003-11-13 11:01:39.000000000 +0100
2571 @@ -29,8 +29,7 @@
2572  #include <linux/slab.h>
2573  #include <linux/random.h>
2574  #include <linux/jhash.h>
2575 -/* For ERR_PTR().  Yeah, I know... --RR */
2576 -#include <linux/fs.h>
2577 +#include <linux/err.h>
2578  
2579  /* This rwlock protects the main hash table, protocol/helper/expected
2580     registrations, conntrack timers*/
2581 @@ -63,6 +62,7 @@
2582  static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
2583  struct list_head *ip_conntrack_hash;
2584  static kmem_cache_t *ip_conntrack_cachep;
2585 +struct ip_conntrack ip_conntrack_untracked;
2586  
2587  extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
2588  
2589 @@ -808,18 +808,10 @@
2590         }
2591  #endif
2592  
2593 -       /* Previously seen (loopback)?  Ignore.  Do this before
2594 -           fragment check. */
2595 +       /* Previously seen (loopback or untracked)?  Ignore. */
2596         if ((*pskb)->nfct)
2597                 return NF_ACCEPT;
2598  
2599 -       /* Gather fragments. */
2600 -       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
2601 -               *pskb = ip_ct_gather_frags(*pskb);
2602 -               if (!*pskb)
2603 -                       return NF_STOLEN;
2604 -       }
2605 -
2606         proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
2607  
2608         /* It may be an icmp error... */
2609 @@ -953,7 +945,6 @@
2610                 }
2611         } else if (related_to->helper->max_expected && 
2612                    related_to->expecting >= related_to->helper->max_expected) {
2613 -               struct list_head *cur_item;
2614                 /* old == NULL */
2615                 if (!(related_to->helper->flags & 
2616                       IP_CT_HELPER_F_REUSE_EXPECT)) {
2617 @@ -978,21 +969,14 @@
2618                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
2619   
2620                 /* choose the the oldest expectation to evict */
2621 -               list_for_each(cur_item, &related_to->sibling_list) { 
2622 -                       struct ip_conntrack_expect *cur;
2623 -
2624 -                       cur = list_entry(cur_item, 
2625 -                                        struct ip_conntrack_expect,
2626 -                                        expected_list);
2627 -                       if (cur->sibling == NULL) {
2628 -                               old = cur;
2629 +               list_for_each_entry(old, &related_to->sibling_list, 
2630 +                                                     expected_list)
2631 +                       if (old->sibling == NULL)
2632                                 break;
2633 -                       }
2634 -               }
2635  
2636 -               /* (!old) cannot happen, since related_to->expecting is the
2637 -                * number of unconfirmed expects */
2638 -               IP_NF_ASSERT(old);
2639 +               /* We cannot fail since related_to->expecting is the number
2640 +                * of unconfirmed expectations */
2641 +               IP_NF_ASSERT(old && old->sibling == NULL);
2642  
2643                 /* newnat14 does not reuse the real allocated memory
2644                  * structures but rather unexpects the old and
2645 @@ -1024,7 +1008,7 @@
2646         atomic_set(&new->use, 1);
2647         
2648         /* add to expected list for this connection */  
2649 -       list_add(&new->expected_list, &related_to->sibling_list);
2650 +       list_add_tail(&new->expected_list, &related_to->sibling_list);
2651         /* add to global list of expectations */
2652         list_prepend(&ip_conntrack_expect_list, &new->list);
2653         /* add and start timer if required */
2654 @@ -1419,6 +1403,15 @@
2655  
2656         /* For use by ipt_REJECT */
2657         ip_ct_attach = ip_conntrack_attach;
2658 +
2659 +       /* Set up fake conntrack:
2660 +           - to never be deleted, not in any hashes */
2661 +       atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
2662 +       /*  - and look it like as a confirmed connection */
2663 +       set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
2664 +       /*  - and prepare the ctinfo field for NAT. */
2665 +       ip_conntrack_untracked.infos[IP_CT_NEW].master = &ip_conntrack_untracked.ct_general;
2666 +
2667         return ret;
2668  
2669  err_free_hash:
2670 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_conntrack_core.c.orig linux-2.6.0-test9/net/ipv4/netfilter/ip_conntrack_core.c.orig
2671 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_conntrack_core.c.orig   1970-01-01 01:00:00.000000000 +0100
2672 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_conntrack_core.c.orig       2003-11-13 11:01:27.000000000 +0100
2673 @@ -0,0 +1,1421 @@
2674 +/* Connection state tracking for netfilter.  This is separated from,
2675 +   but required by, the NAT layer; it can also be used by an iptables
2676 +   extension. */
2677 +
2678 +/* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
2679 + * Public Licence. 
2680 + *
2681 + * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
2682 + *     - new API and handling of conntrack/nat helpers
2683 + *     - now capable of multiple expectations for one master
2684 + * 16 Jul 2002: Harald Welte <laforge@gnumonks.org>
2685 + *     - add usage/reference counts to ip_conntrack_expect
2686 + *     - export ip_conntrack[_expect]_{find_get,put} functions
2687 + * */
2688 +
2689 +#include <linux/config.h>
2690 +#include <linux/types.h>
2691 +#include <linux/icmp.h>
2692 +#include <linux/ip.h>
2693 +#include <linux/netfilter.h>
2694 +#include <linux/netfilter_ipv4.h>
2695 +#include <linux/module.h>
2696 +#include <linux/skbuff.h>
2697 +#include <linux/proc_fs.h>
2698 +#include <linux/vmalloc.h>
2699 +#include <net/checksum.h>
2700 +#include <linux/stddef.h>
2701 +#include <linux/sysctl.h>
2702 +#include <linux/slab.h>
2703 +#include <linux/random.h>
2704 +#include <linux/jhash.h>
2705 +#include <linux/err.h>
2706 +
2707 +/* This rwlock protects the main hash table, protocol/helper/expected
2708 +   registrations, conntrack timers*/
2709 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
2710 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
2711 +
2712 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2713 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
2714 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2715 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2716 +#include <linux/netfilter_ipv4/listhelp.h>
2717 +
2718 +#define IP_CONNTRACK_VERSION   "2.1"
2719 +
2720 +#if 0
2721 +#define DEBUGP printk
2722 +#else
2723 +#define DEBUGP(format, args...)
2724 +#endif
2725 +
2726 +DECLARE_RWLOCK(ip_conntrack_lock);
2727 +DECLARE_RWLOCK(ip_conntrack_expect_tuple_lock);
2728 +
2729 +void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL;
2730 +LIST_HEAD(ip_conntrack_expect_list);
2731 +LIST_HEAD(protocol_list);
2732 +static LIST_HEAD(helpers);
2733 +unsigned int ip_conntrack_htable_size = 0;
2734 +int ip_conntrack_max;
2735 +static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
2736 +struct list_head *ip_conntrack_hash;
2737 +static kmem_cache_t *ip_conntrack_cachep;
2738 +
2739 +extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
2740 +
2741 +static inline int proto_cmpfn(const struct ip_conntrack_protocol *curr,
2742 +                             u_int8_t protocol)
2743 +{
2744 +       return protocol == curr->proto;
2745 +}
2746 +
2747 +struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol)
2748 +{
2749 +       struct ip_conntrack_protocol *p;
2750 +
2751 +       MUST_BE_READ_LOCKED(&ip_conntrack_lock);
2752 +       p = LIST_FIND(&protocol_list, proto_cmpfn,
2753 +                     struct ip_conntrack_protocol *, protocol);
2754 +       if (!p)
2755 +               p = &ip_conntrack_generic_protocol;
2756 +
2757 +       return p;
2758 +}
2759 +
2760 +struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
2761 +{
2762 +       struct ip_conntrack_protocol *p;
2763 +
2764 +       READ_LOCK(&ip_conntrack_lock);
2765 +       p = __ip_ct_find_proto(protocol);
2766 +       READ_UNLOCK(&ip_conntrack_lock);
2767 +       return p;
2768 +}
2769 +
2770 +inline void 
2771 +ip_conntrack_put(struct ip_conntrack *ct)
2772 +{
2773 +       IP_NF_ASSERT(ct);
2774 +       IP_NF_ASSERT(ct->infos[0].master);
2775 +       /* nf_conntrack_put wants to go via an info struct, so feed it
2776 +           one at random. */
2777 +       nf_conntrack_put(&ct->infos[0]);
2778 +}
2779 +
2780 +static int ip_conntrack_hash_rnd_initted;
2781 +static unsigned int ip_conntrack_hash_rnd;
2782 +
2783 +static u_int32_t
2784 +hash_conntrack(const struct ip_conntrack_tuple *tuple)
2785 +{
2786 +#if 0
2787 +       dump_tuple(tuple);
2788 +#endif
2789 +       return (jhash_3words(tuple->src.ip,
2790 +                            (tuple->dst.ip ^ tuple->dst.protonum),
2791 +                            (tuple->src.u.all | (tuple->dst.u.all << 16)),
2792 +                            ip_conntrack_hash_rnd) % ip_conntrack_htable_size);
2793 +}
2794 +
2795 +int
2796 +get_tuple(const struct iphdr *iph,
2797 +         const struct sk_buff *skb,
2798 +         unsigned int dataoff,
2799 +         struct ip_conntrack_tuple *tuple,
2800 +         const struct ip_conntrack_protocol *protocol)
2801 +{
2802 +       /* Never happen */
2803 +       if (iph->frag_off & htons(IP_OFFSET)) {
2804 +               printk("ip_conntrack_core: Frag of proto %u.\n",
2805 +                      iph->protocol);
2806 +               return 0;
2807 +       }
2808 +
2809 +       tuple->src.ip = iph->saddr;
2810 +       tuple->dst.ip = iph->daddr;
2811 +       tuple->dst.protonum = iph->protocol;
2812 +
2813 +       return protocol->pkt_to_tuple(skb, dataoff, tuple);
2814 +}
2815 +
2816 +static int
2817 +invert_tuple(struct ip_conntrack_tuple *inverse,
2818 +            const struct ip_conntrack_tuple *orig,
2819 +            const struct ip_conntrack_protocol *protocol)
2820 +{
2821 +       inverse->src.ip = orig->dst.ip;
2822 +       inverse->dst.ip = orig->src.ip;
2823 +       inverse->dst.protonum = orig->dst.protonum;
2824 +
2825 +       return protocol->invert_tuple(inverse, orig);
2826 +}
2827 +
2828 +
2829 +/* ip_conntrack_expect helper functions */
2830 +
2831 +/* Compare tuple parts depending on mask. */
2832 +static inline int expect_cmp(const struct ip_conntrack_expect *i,
2833 +                            const struct ip_conntrack_tuple *tuple)
2834 +{
2835 +       MUST_BE_READ_LOCKED(&ip_conntrack_expect_tuple_lock);
2836 +       return ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask);
2837 +}
2838 +
2839 +static void
2840 +destroy_expect(struct ip_conntrack_expect *exp)
2841 +{
2842 +       DEBUGP("destroy_expect(%p) use=%d\n", exp, atomic_read(&exp->use));
2843 +       IP_NF_ASSERT(atomic_read(&exp->use));
2844 +       IP_NF_ASSERT(!timer_pending(&exp->timeout));
2845 +
2846 +       kfree(exp);
2847 +}
2848 +
2849 +
2850 +inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
2851 +{
2852 +       IP_NF_ASSERT(exp);
2853 +
2854 +       if (atomic_dec_and_test(&exp->use)) {
2855 +               /* usage count dropped to zero */
2856 +               destroy_expect(exp);
2857 +       }
2858 +}
2859 +
2860 +static inline struct ip_conntrack_expect *
2861 +__ip_ct_expect_find(const struct ip_conntrack_tuple *tuple)
2862 +{
2863 +       MUST_BE_READ_LOCKED(&ip_conntrack_lock);
2864 +       MUST_BE_READ_LOCKED(&ip_conntrack_expect_tuple_lock);
2865 +       return LIST_FIND(&ip_conntrack_expect_list, expect_cmp, 
2866 +                        struct ip_conntrack_expect *, tuple);
2867 +}
2868 +
2869 +/* Find a expectation corresponding to a tuple. */
2870 +struct ip_conntrack_expect *
2871 +ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
2872 +{
2873 +       struct ip_conntrack_expect *exp;
2874 +
2875 +       READ_LOCK(&ip_conntrack_lock);
2876 +       READ_LOCK(&ip_conntrack_expect_tuple_lock);
2877 +       exp = __ip_ct_expect_find(tuple);
2878 +       if (exp)
2879 +               atomic_inc(&exp->use);
2880 +       READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
2881 +       READ_UNLOCK(&ip_conntrack_lock);
2882 +
2883 +       return exp;
2884 +}
2885 +
2886 +/* remove one specific expectation from all lists and drop refcount,
2887 + * does _NOT_ delete the timer. */
2888 +static void __unexpect_related(struct ip_conntrack_expect *expect)
2889 +{
2890 +       DEBUGP("unexpect_related(%p)\n", expect);
2891 +       MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
2892 +
2893 +       /* we're not allowed to unexpect a confirmed expectation! */
2894 +       IP_NF_ASSERT(!expect->sibling);
2895 +
2896 +       /* delete from global and local lists */
2897 +       list_del(&expect->list);
2898 +       list_del(&expect->expected_list);
2899 +
2900 +       /* decrement expect-count of master conntrack */
2901 +       if (expect->expectant)
2902 +               expect->expectant->expecting--;
2903 +
2904 +       ip_conntrack_expect_put(expect);
2905 +}
2906 +
2907 +/* remove one specific expecatation from all lists, drop refcount
2908 + * and expire timer. 
2909 + * This function can _NOT_ be called for confirmed expects! */
2910 +static void unexpect_related(struct ip_conntrack_expect *expect)
2911 +{
2912 +       IP_NF_ASSERT(expect->expectant);
2913 +       IP_NF_ASSERT(expect->expectant->helper);
2914 +       /* if we are supposed to have a timer, but we can't delete
2915 +        * it: race condition.  __unexpect_related will
2916 +        * be calledd by timeout function */
2917 +       if (expect->expectant->helper->timeout
2918 +           && !del_timer(&expect->timeout))
2919 +               return;
2920 +
2921 +       __unexpect_related(expect);
2922 +}
2923 +
2924 +/* delete all unconfirmed expectations for this conntrack */
2925 +static void remove_expectations(struct ip_conntrack *ct, int drop_refcount)
2926 +{
2927 +       struct list_head *exp_entry, *next;
2928 +       struct ip_conntrack_expect *exp;
2929 +
2930 +       DEBUGP("remove_expectations(%p)\n", ct);
2931 +
2932 +       list_for_each_safe(exp_entry, next, &ct->sibling_list) {
2933 +               exp = list_entry(exp_entry, struct ip_conntrack_expect,
2934 +                                expected_list);
2935 +
2936 +               /* we skip established expectations, as we want to delete
2937 +                * the un-established ones only */
2938 +               if (exp->sibling) {
2939 +                       DEBUGP("remove_expectations: skipping established %p of %p\n", exp->sibling, ct);
2940 +                       if (drop_refcount) {
2941 +                               /* Indicate that this expectations parent is dead */
2942 +                               ip_conntrack_put(exp->expectant);
2943 +                               exp->expectant = NULL;
2944 +                       }
2945 +                       continue;
2946 +               }
2947 +
2948 +               IP_NF_ASSERT(list_inlist(&ip_conntrack_expect_list, exp));
2949 +               IP_NF_ASSERT(exp->expectant == ct);
2950 +
2951 +               /* delete expectation from global and private lists */
2952 +               unexpect_related(exp);
2953 +       }
2954 +}
2955 +
2956 +static void
2957 +clean_from_lists(struct ip_conntrack *ct)
2958 +{
2959 +       unsigned int ho, hr;
2960 +       
2961 +       DEBUGP("clean_from_lists(%p)\n", ct);
2962 +       MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
2963 +
2964 +       ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
2965 +       hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
2966 +       LIST_DELETE(&ip_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
2967 +       LIST_DELETE(&ip_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
2968 +
2969 +       /* Destroy all un-established, pending expectations */
2970 +       remove_expectations(ct, 1);
2971 +}
2972 +
2973 +static void
2974 +destroy_conntrack(struct nf_conntrack *nfct)
2975 +{
2976 +       struct ip_conntrack *ct = (struct ip_conntrack *)nfct, *master = NULL;
2977 +       struct ip_conntrack_protocol *proto;
2978 +
2979 +       DEBUGP("destroy_conntrack(%p)\n", ct);
2980 +       IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
2981 +       IP_NF_ASSERT(!timer_pending(&ct->timeout));
2982 +
2983 +       /* To make sure we don't get any weird locking issues here:
2984 +        * destroy_conntrack() MUST NOT be called with a write lock
2985 +        * to ip_conntrack_lock!!! -HW */
2986 +       proto = ip_ct_find_proto(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
2987 +       if (proto && proto->destroy)
2988 +               proto->destroy(ct);
2989 +
2990 +       if (ip_conntrack_destroyed)
2991 +               ip_conntrack_destroyed(ct);
2992 +
2993 +       WRITE_LOCK(&ip_conntrack_lock);
2994 +       /* Delete us from our own list to prevent corruption later */
2995 +       list_del(&ct->sibling_list);
2996 +
2997 +       /* Delete our master expectation */
2998 +       if (ct->master) {
2999 +               if (ct->master->expectant) {
3000 +                       /* can't call __unexpect_related here,
3001 +                        * since it would screw up expect_list */
3002 +                       list_del(&ct->master->expected_list);
3003 +                       master = ct->master->expectant;
3004 +               }
3005 +               kfree(ct->master);
3006 +       }
3007 +       WRITE_UNLOCK(&ip_conntrack_lock);
3008 +
3009 +       if (master)
3010 +               ip_conntrack_put(master);
3011 +
3012 +       DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
3013 +       kmem_cache_free(ip_conntrack_cachep, ct);
3014 +       atomic_dec(&ip_conntrack_count);
3015 +}
3016 +
3017 +static void death_by_timeout(unsigned long ul_conntrack)
3018 +{
3019 +       struct ip_conntrack *ct = (void *)ul_conntrack;
3020 +
3021 +       WRITE_LOCK(&ip_conntrack_lock);
3022 +       clean_from_lists(ct);
3023 +       WRITE_UNLOCK(&ip_conntrack_lock);
3024 +       ip_conntrack_put(ct);
3025 +}
3026 +
3027 +static inline int
3028 +conntrack_tuple_cmp(const struct ip_conntrack_tuple_hash *i,
3029 +                   const struct ip_conntrack_tuple *tuple,
3030 +                   const struct ip_conntrack *ignored_conntrack)
3031 +{
3032 +       MUST_BE_READ_LOCKED(&ip_conntrack_lock);
3033 +       return i->ctrack != ignored_conntrack
3034 +               && ip_ct_tuple_equal(tuple, &i->tuple);
3035 +}
3036 +
3037 +static struct ip_conntrack_tuple_hash *
3038 +__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
3039 +                   const struct ip_conntrack *ignored_conntrack)
3040 +{
3041 +       struct ip_conntrack_tuple_hash *h;
3042 +       unsigned int hash = hash_conntrack(tuple);
3043 +
3044 +       MUST_BE_READ_LOCKED(&ip_conntrack_lock);
3045 +       h = LIST_FIND(&ip_conntrack_hash[hash],
3046 +                     conntrack_tuple_cmp,
3047 +                     struct ip_conntrack_tuple_hash *,
3048 +                     tuple, ignored_conntrack);
3049 +       return h;
3050 +}
3051 +
3052 +/* Find a connection corresponding to a tuple. */
3053 +struct ip_conntrack_tuple_hash *
3054 +ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
3055 +                     const struct ip_conntrack *ignored_conntrack)
3056 +{
3057 +       struct ip_conntrack_tuple_hash *h;
3058 +
3059 +       READ_LOCK(&ip_conntrack_lock);
3060 +       h = __ip_conntrack_find(tuple, ignored_conntrack);
3061 +       if (h)
3062 +               atomic_inc(&h->ctrack->ct_general.use);
3063 +       READ_UNLOCK(&ip_conntrack_lock);
3064 +
3065 +       return h;
3066 +}
3067 +
3068 +static inline struct ip_conntrack *
3069 +__ip_conntrack_get(struct nf_ct_info *nfct, enum ip_conntrack_info *ctinfo)
3070 +{
3071 +       struct ip_conntrack *ct
3072 +               = (struct ip_conntrack *)nfct->master;
3073 +
3074 +       /* ctinfo is the index of the nfct inside the conntrack */
3075 +       *ctinfo = nfct - ct->infos;
3076 +       IP_NF_ASSERT(*ctinfo >= 0 && *ctinfo < IP_CT_NUMBER);
3077 +       return ct;
3078 +}
3079 +
3080 +/* Return conntrack and conntrack_info given skb->nfct->master */
3081 +struct ip_conntrack *
3082 +ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
3083 +{
3084 +       if (skb->nfct) 
3085 +               return __ip_conntrack_get(skb->nfct, ctinfo);
3086 +       return NULL;
3087 +}
3088 +
3089 +/* Confirm a connection given skb->nfct; places it in hash table */
3090 +int
3091 +__ip_conntrack_confirm(struct nf_ct_info *nfct)
3092 +{
3093 +       unsigned int hash, repl_hash;
3094 +       struct ip_conntrack *ct;
3095 +       enum ip_conntrack_info ctinfo;
3096 +
3097 +       ct = __ip_conntrack_get(nfct, &ctinfo);
3098 +
3099 +       /* ipt_REJECT uses ip_conntrack_attach to attach related
3100 +          ICMP/TCP RST packets in other direction.  Actual packet
3101 +          which created connection will be IP_CT_NEW or for an
3102 +          expected connection, IP_CT_RELATED. */
3103 +       if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
3104 +               return NF_ACCEPT;
3105 +
3106 +       hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
3107 +       repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
3108 +
3109 +       /* We're not in hash table, and we refuse to set up related
3110 +          connections for unconfirmed conns.  But packet copies and
3111 +          REJECT will give spurious warnings here. */
3112 +       /* IP_NF_ASSERT(atomic_read(&ct->ct_general.use) == 1); */
3113 +
3114 +       /* No external references means noone else could have
3115 +           confirmed us. */
3116 +       IP_NF_ASSERT(!is_confirmed(ct));
3117 +       DEBUGP("Confirming conntrack %p\n", ct);
3118 +
3119 +       WRITE_LOCK(&ip_conntrack_lock);
3120 +       /* See if there's one in the list already, including reverse:
3121 +           NAT could have grabbed it without realizing, since we're
3122 +           not in the hash.  If there is, we lost race. */
3123 +       if (!LIST_FIND(&ip_conntrack_hash[hash],
3124 +                      conntrack_tuple_cmp,
3125 +                      struct ip_conntrack_tuple_hash *,
3126 +                      &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, NULL)
3127 +           && !LIST_FIND(&ip_conntrack_hash[repl_hash],
3128 +                         conntrack_tuple_cmp,
3129 +                         struct ip_conntrack_tuple_hash *,
3130 +                         &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) {
3131 +               list_prepend(&ip_conntrack_hash[hash],
3132 +                            &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
3133 +               list_prepend(&ip_conntrack_hash[repl_hash],
3134 +                            &ct->tuplehash[IP_CT_DIR_REPLY]);
3135 +               /* Timer relative to confirmation time, not original
3136 +                  setting time, otherwise we'd get timer wrap in
3137 +                  weird delay cases. */
3138 +               ct->timeout.expires += jiffies;
3139 +               add_timer(&ct->timeout);
3140 +               atomic_inc(&ct->ct_general.use);
3141 +               set_bit(IPS_CONFIRMED_BIT, &ct->status);
3142 +               WRITE_UNLOCK(&ip_conntrack_lock);
3143 +               return NF_ACCEPT;
3144 +       }
3145 +
3146 +       WRITE_UNLOCK(&ip_conntrack_lock);
3147 +       return NF_DROP;
3148 +}
3149 +
3150 +/* Returns true if a connection correspondings to the tuple (required
3151 +   for NAT). */
3152 +int
3153 +ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
3154 +                        const struct ip_conntrack *ignored_conntrack)
3155 +{
3156 +       struct ip_conntrack_tuple_hash *h;
3157 +
3158 +       READ_LOCK(&ip_conntrack_lock);
3159 +       h = __ip_conntrack_find(tuple, ignored_conntrack);
3160 +       READ_UNLOCK(&ip_conntrack_lock);
3161 +
3162 +       return h != NULL;
3163 +}
3164 +
3165 +/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
3166 +struct ip_conntrack *
3167 +icmp_error_track(struct sk_buff *skb,
3168 +                enum ip_conntrack_info *ctinfo,
3169 +                unsigned int hooknum)
3170 +{
3171 +       struct ip_conntrack_tuple innertuple, origtuple;
3172 +       struct {
3173 +               struct icmphdr icmp;
3174 +               struct iphdr ip;
3175 +       } inside;
3176 +       struct ip_conntrack_protocol *innerproto;
3177 +       struct ip_conntrack_tuple_hash *h;
3178 +       int dataoff;
3179 +
3180 +       IP_NF_ASSERT(skb->nfct == NULL);
3181 +
3182 +       /* Not enough header? */
3183 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
3184 +               return NULL;
3185 +
3186 +       if (inside.icmp.type != ICMP_DEST_UNREACH
3187 +           && inside.icmp.type != ICMP_SOURCE_QUENCH
3188 +           && inside.icmp.type != ICMP_TIME_EXCEEDED
3189 +           && inside.icmp.type != ICMP_PARAMETERPROB
3190 +           && inside.icmp.type != ICMP_REDIRECT)
3191 +               return NULL;
3192 +
3193 +       /* Ignore ICMP's containing fragments (shouldn't happen) */
3194 +       if (inside.ip.frag_off & htons(IP_OFFSET)) {
3195 +               DEBUGP("icmp_error_track: fragment of proto %u\n",
3196 +                      inside.ip.protocol);
3197 +               return NULL;
3198 +       }
3199 +
3200 +       innerproto = ip_ct_find_proto(inside.ip.protocol);
3201 +       dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
3202 +       /* Are they talking about one of our connections? */
3203 +       if (!get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
3204 +               DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
3205 +               return NULL;
3206 +       }
3207 +
3208 +       /* Ordinarily, we'd expect the inverted tupleproto, but it's
3209 +          been preserved inside the ICMP. */
3210 +       if (!invert_tuple(&innertuple, &origtuple, innerproto)) {
3211 +               DEBUGP("icmp_error_track: Can't invert tuple\n");
3212 +               return NULL;
3213 +       }
3214 +
3215 +       *ctinfo = IP_CT_RELATED;
3216 +
3217 +       h = ip_conntrack_find_get(&innertuple, NULL);
3218 +       if (!h) {
3219 +               /* Locally generated ICMPs will match inverted if they
3220 +                  haven't been SNAT'ed yet */
3221 +               /* FIXME: NAT code has to handle half-done double NAT --RR */
3222 +               if (hooknum == NF_IP_LOCAL_OUT)
3223 +                       h = ip_conntrack_find_get(&origtuple, NULL);
3224 +
3225 +               if (!h) {
3226 +                       DEBUGP("icmp_error_track: no match\n");
3227 +                       return NULL;
3228 +               }
3229 +               /* Reverse direction from that found */
3230 +               if (DIRECTION(h) != IP_CT_DIR_REPLY)
3231 +                       *ctinfo += IP_CT_IS_REPLY;
3232 +       } else {
3233 +               if (DIRECTION(h) == IP_CT_DIR_REPLY)
3234 +                       *ctinfo += IP_CT_IS_REPLY;
3235 +       }
3236 +
3237 +       /* Update skb to refer to this connection */
3238 +       skb->nfct = &h->ctrack->infos[*ctinfo];
3239 +       return h->ctrack;
3240 +}
3241 +
3242 +/* There's a small race here where we may free a just-assured
3243 +   connection.  Too bad: we're in trouble anyway. */
3244 +static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
3245 +{
3246 +       return !(test_bit(IPS_ASSURED_BIT, &i->ctrack->status));
3247 +}
3248 +
3249 +static int early_drop(struct list_head *chain)
3250 +{
3251 +       /* Traverse backwards: gives us oldest, which is roughly LRU */
3252 +       struct ip_conntrack_tuple_hash *h;
3253 +       int dropped = 0;
3254 +
3255 +       READ_LOCK(&ip_conntrack_lock);
3256 +       h = LIST_FIND_B(chain, unreplied, struct ip_conntrack_tuple_hash *);
3257 +       if (h)
3258 +               atomic_inc(&h->ctrack->ct_general.use);
3259 +       READ_UNLOCK(&ip_conntrack_lock);
3260 +
3261 +       if (!h)
3262 +               return dropped;
3263 +
3264 +       if (del_timer(&h->ctrack->timeout)) {
3265 +               death_by_timeout((unsigned long)h->ctrack);
3266 +               dropped = 1;
3267 +       }
3268 +       ip_conntrack_put(h->ctrack);
3269 +       return dropped;
3270 +}
3271 +
3272 +static inline int helper_cmp(const struct ip_conntrack_helper *i,
3273 +                            const struct ip_conntrack_tuple *rtuple)
3274 +{
3275 +       return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
3276 +}
3277 +
3278 +struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
3279 +{
3280 +       return LIST_FIND(&helpers, helper_cmp,
3281 +                        struct ip_conntrack_helper *,
3282 +                        tuple);
3283 +}
3284 +
3285 +/* Allocate a new conntrack: we return -ENOMEM if classification
3286 +   failed due to stress.  Otherwise it really is unclassifiable. */
3287 +static struct ip_conntrack_tuple_hash *
3288 +init_conntrack(const struct ip_conntrack_tuple *tuple,
3289 +              struct ip_conntrack_protocol *protocol,
3290 +              struct sk_buff *skb)
3291 +{
3292 +       struct ip_conntrack *conntrack;
3293 +       struct ip_conntrack_tuple repl_tuple;
3294 +       size_t hash;
3295 +       struct ip_conntrack_expect *expected;
3296 +       int i;
3297 +       static unsigned int drop_next;
3298 +
3299 +       if (!ip_conntrack_hash_rnd_initted) {
3300 +               get_random_bytes(&ip_conntrack_hash_rnd, 4);
3301 +               ip_conntrack_hash_rnd_initted = 1;
3302 +       }
3303 +
3304 +       hash = hash_conntrack(tuple);
3305 +
3306 +       if (ip_conntrack_max &&
3307 +           atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
3308 +               /* Try dropping from random chain, or else from the
3309 +                   chain about to put into (in case they're trying to
3310 +                   bomb one hash chain). */
3311 +               unsigned int next = (drop_next++)%ip_conntrack_htable_size;
3312 +
3313 +               if (!early_drop(&ip_conntrack_hash[next])
3314 +                   && !early_drop(&ip_conntrack_hash[hash])) {
3315 +                       if (net_ratelimit())
3316 +                               printk(KERN_WARNING
3317 +                                      "ip_conntrack: table full, dropping"
3318 +                                      " packet.\n");
3319 +                       return ERR_PTR(-ENOMEM);
3320 +               }
3321 +       }
3322 +
3323 +       if (!invert_tuple(&repl_tuple, tuple, protocol)) {
3324 +               DEBUGP("Can't invert tuple.\n");
3325 +               return NULL;
3326 +       }
3327 +
3328 +       conntrack = kmem_cache_alloc(ip_conntrack_cachep, GFP_ATOMIC);
3329 +       if (!conntrack) {
3330 +               DEBUGP("Can't allocate conntrack.\n");
3331 +               return ERR_PTR(-ENOMEM);
3332 +       }
3333 +
3334 +       memset(conntrack, 0, sizeof(*conntrack));
3335 +       atomic_set(&conntrack->ct_general.use, 1);
3336 +       conntrack->ct_general.destroy = destroy_conntrack;
3337 +       conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple;
3338 +       conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack;
3339 +       conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
3340 +       conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack;
3341 +       for (i=0; i < IP_CT_NUMBER; i++)
3342 +               conntrack->infos[i].master = &conntrack->ct_general;
3343 +
3344 +       if (!protocol->new(conntrack, skb)) {
3345 +               kmem_cache_free(ip_conntrack_cachep, conntrack);
3346 +               return NULL;
3347 +       }
3348 +       /* Don't set timer yet: wait for confirmation */
3349 +       init_timer(&conntrack->timeout);
3350 +       conntrack->timeout.data = (unsigned long)conntrack;
3351 +       conntrack->timeout.function = death_by_timeout;
3352 +
3353 +       INIT_LIST_HEAD(&conntrack->sibling_list);
3354 +
3355 +       WRITE_LOCK(&ip_conntrack_lock);
3356 +       /* Need finding and deleting of expected ONLY if we win race */
3357 +       READ_LOCK(&ip_conntrack_expect_tuple_lock);
3358 +       expected = LIST_FIND(&ip_conntrack_expect_list, expect_cmp,
3359 +                            struct ip_conntrack_expect *, tuple);
3360 +       READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
3361 +
3362 +       /* If master is not in hash table yet (ie. packet hasn't left
3363 +          this machine yet), how can other end know about expected?
3364 +          Hence these are not the droids you are looking for (if
3365 +          master ct never got confirmed, we'd hold a reference to it
3366 +          and weird things would happen to future packets). */
3367 +       if (expected && !is_confirmed(expected->expectant))
3368 +               expected = NULL;
3369 +
3370 +       /* Look up the conntrack helper for master connections only */
3371 +       if (!expected)
3372 +               conntrack->helper = ip_ct_find_helper(&repl_tuple);
3373 +
3374 +       /* If the expectation is dying, then this is a loser. */
3375 +       if (expected
3376 +           && expected->expectant->helper->timeout
3377 +           && ! del_timer(&expected->timeout))
3378 +               expected = NULL;
3379 +
3380 +       if (expected) {
3381 +               DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3382 +                       conntrack, expected);
3383 +               /* Welcome, Mr. Bond.  We've been expecting you... */
3384 +               IP_NF_ASSERT(master_ct(conntrack));
3385 +               __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3386 +               conntrack->master = expected;
3387 +               expected->sibling = conntrack;
3388 +               LIST_DELETE(&ip_conntrack_expect_list, expected);
3389 +               expected->expectant->expecting--;
3390 +               nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3391 +       }
3392 +       atomic_inc(&ip_conntrack_count);
3393 +       WRITE_UNLOCK(&ip_conntrack_lock);
3394 +
3395 +       if (expected && expected->expectfn)
3396 +               expected->expectfn(conntrack);
3397 +       return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3398 +}
3399 +
3400 +/* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
3401 +static inline struct ip_conntrack *
3402 +resolve_normal_ct(struct sk_buff *skb,
3403 +                 struct ip_conntrack_protocol *proto,
3404 +                 int *set_reply,
3405 +                 unsigned int hooknum,
3406 +                 enum ip_conntrack_info *ctinfo)
3407 +{
3408 +       struct ip_conntrack_tuple tuple;
3409 +       struct ip_conntrack_tuple_hash *h;
3410 +
3411 +       IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
3412 +
3413 +       if (!get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, &tuple, proto))
3414 +               return NULL;
3415 +
3416 +       /* look for tuple match */
3417 +       h = ip_conntrack_find_get(&tuple, NULL);
3418 +       if (!h) {
3419 +               h = init_conntrack(&tuple, proto, skb);
3420 +               if (!h)
3421 +                       return NULL;
3422 +               if (IS_ERR(h))
3423 +                       return (void *)h;
3424 +       }
3425 +
3426 +       /* It exists; we have (non-exclusive) reference. */
3427 +       if (DIRECTION(h) == IP_CT_DIR_REPLY) {
3428 +               *ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY;
3429 +               /* Please set reply bit if this packet OK */
3430 +               *set_reply = 1;
3431 +       } else {
3432 +               /* Once we've had two way comms, always ESTABLISHED. */
3433 +               if (test_bit(IPS_SEEN_REPLY_BIT, &h->ctrack->status)) {
3434 +                       DEBUGP("ip_conntrack_in: normal packet for %p\n",
3435 +                              h->ctrack);
3436 +                       *ctinfo = IP_CT_ESTABLISHED;
3437 +               } else if (test_bit(IPS_EXPECTED_BIT, &h->ctrack->status)) {
3438 +                       DEBUGP("ip_conntrack_in: related packet for %p\n",
3439 +                              h->ctrack);
3440 +                       *ctinfo = IP_CT_RELATED;
3441 +               } else {
3442 +                       DEBUGP("ip_conntrack_in: new packet for %p\n",
3443 +                              h->ctrack);
3444 +                       *ctinfo = IP_CT_NEW;
3445 +               }
3446 +               *set_reply = 0;
3447 +       }
3448 +       skb->nfct = &h->ctrack->infos[*ctinfo];
3449 +       return h->ctrack;
3450 +}
3451 +
3452 +/* Netfilter hook itself. */
3453 +unsigned int ip_conntrack_in(unsigned int hooknum,
3454 +                            struct sk_buff **pskb,
3455 +                            const struct net_device *in,
3456 +                            const struct net_device *out,
3457 +                            int (*okfn)(struct sk_buff *))
3458 +{
3459 +       struct ip_conntrack *ct;
3460 +       enum ip_conntrack_info ctinfo;
3461 +       struct ip_conntrack_protocol *proto;
3462 +       int set_reply;
3463 +       int ret;
3464 +
3465 +       /* FIXME: Do this right please. --RR */
3466 +       (*pskb)->nfcache |= NFC_UNKNOWN;
3467 +
3468 +/* Doesn't cover locally-generated broadcast, so not worth it. */
3469 +#if 0
3470 +       /* Ignore broadcast: no `connection'. */
3471 +       if ((*pskb)->pkt_type == PACKET_BROADCAST) {
3472 +               printk("Broadcast packet!\n");
3473 +               return NF_ACCEPT;
3474 +       } else if (((*pskb)->nh.iph->daddr & htonl(0x000000FF)) 
3475 +                  == htonl(0x000000FF)) {
3476 +               printk("Should bcast: %u.%u.%u.%u->%u.%u.%u.%u (sk=%p, ptype=%u)\n",
3477 +                      NIPQUAD((*pskb)->nh.iph->saddr),
3478 +                      NIPQUAD((*pskb)->nh.iph->daddr),
3479 +                      (*pskb)->sk, (*pskb)->pkt_type);
3480 +       }
3481 +#endif
3482 +
3483 +       /* Previously seen (loopback)?  Ignore.  Do this before
3484 +           fragment check. */
3485 +       if ((*pskb)->nfct)
3486 +               return NF_ACCEPT;
3487 +
3488 +       /* Gather fragments. */
3489 +       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
3490 +               *pskb = ip_ct_gather_frags(*pskb);
3491 +               if (!*pskb)
3492 +                       return NF_STOLEN;
3493 +       }
3494 +
3495 +       proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
3496 +
3497 +       /* It may be an icmp error... */
3498 +       if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP 
3499 +           && icmp_error_track(*pskb, &ctinfo, hooknum))
3500 +               return NF_ACCEPT;
3501 +
3502 +       if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo)))
3503 +               /* Not valid part of a connection */
3504 +               return NF_ACCEPT;
3505 +
3506 +       if (IS_ERR(ct))
3507 +               /* Too stressed to deal. */
3508 +               return NF_DROP;
3509 +
3510 +       IP_NF_ASSERT((*pskb)->nfct);
3511 +
3512 +       ret = proto->packet(ct, *pskb, ctinfo);
3513 +       if (ret == -1) {
3514 +               /* Invalid */
3515 +               nf_conntrack_put((*pskb)->nfct);
3516 +               (*pskb)->nfct = NULL;
3517 +               return NF_ACCEPT;
3518 +       }
3519 +
3520 +       if (ret != NF_DROP && ct->helper) {
3521 +               ret = ct->helper->help(*pskb, ct, ctinfo);
3522 +               if (ret == -1) {
3523 +                       /* Invalid */
3524 +                       nf_conntrack_put((*pskb)->nfct);
3525 +                       (*pskb)->nfct = NULL;
3526 +                       return NF_ACCEPT;
3527 +               }
3528 +       }
3529 +       if (set_reply)
3530 +               set_bit(IPS_SEEN_REPLY_BIT, &ct->status);
3531 +
3532 +       return ret;
3533 +}
3534 +
3535 +int invert_tuplepr(struct ip_conntrack_tuple *inverse,
3536 +                  const struct ip_conntrack_tuple *orig)
3537 +{
3538 +       return invert_tuple(inverse, orig, ip_ct_find_proto(orig->dst.protonum));
3539 +}
3540 +
3541 +static inline int resent_expect(const struct ip_conntrack_expect *i,
3542 +                               const struct ip_conntrack_tuple *tuple,
3543 +                               const struct ip_conntrack_tuple *mask)
3544 +{
3545 +       DEBUGP("resent_expect\n");
3546 +       DEBUGP("   tuple:   "); DUMP_TUPLE(&i->tuple);
3547 +       DEBUGP("ct_tuple:   "); DUMP_TUPLE(&i->ct_tuple);
3548 +       DEBUGP("test tuple: "); DUMP_TUPLE(tuple);
3549 +       return (((i->ct_tuple.dst.protonum == 0 && ip_ct_tuple_equal(&i->tuple, tuple))
3550 +                || (i->ct_tuple.dst.protonum && ip_ct_tuple_equal(&i->ct_tuple, tuple)))
3551 +               && ip_ct_tuple_equal(&i->mask, mask));
3552 +}
3553 +
3554 +/* Would two expected things clash? */
3555 +static inline int expect_clash(const struct ip_conntrack_expect *i,
3556 +                              const struct ip_conntrack_tuple *tuple,
3557 +                              const struct ip_conntrack_tuple *mask)
3558 +{
3559 +       /* Part covered by intersection of masks must be unequal,
3560 +           otherwise they clash */
3561 +       struct ip_conntrack_tuple intersect_mask
3562 +               = { { i->mask.src.ip & mask->src.ip,
3563 +                     { i->mask.src.u.all & mask->src.u.all } },
3564 +                   { i->mask.dst.ip & mask->dst.ip,
3565 +                     { i->mask.dst.u.all & mask->dst.u.all },
3566 +                     i->mask.dst.protonum & mask->dst.protonum } };
3567 +
3568 +       return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
3569 +}
3570 +
3571 +inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
3572 +{
3573 +       WRITE_LOCK(&ip_conntrack_lock);
3574 +       unexpect_related(expect);
3575 +       WRITE_UNLOCK(&ip_conntrack_lock);
3576 +}
3577 +       
3578 +static void expectation_timed_out(unsigned long ul_expect)
3579 +{
3580 +       struct ip_conntrack_expect *expect = (void *) ul_expect;
3581 +
3582 +       DEBUGP("expectation %p timed out\n", expect);   
3583 +       WRITE_LOCK(&ip_conntrack_lock);
3584 +       __unexpect_related(expect);
3585 +       WRITE_UNLOCK(&ip_conntrack_lock);
3586 +}
3587 +
3588 +/* Add a related connection. */
3589 +int ip_conntrack_expect_related(struct ip_conntrack *related_to,
3590 +                               struct ip_conntrack_expect *expect)
3591 +{
3592 +       struct ip_conntrack_expect *old, *new;
3593 +       int ret = 0;
3594 +
3595 +       WRITE_LOCK(&ip_conntrack_lock);
3596 +       /* Because of the write lock, no reader can walk the lists,
3597 +        * so there is no need to use the tuple lock too */
3598 +
3599 +       DEBUGP("ip_conntrack_expect_related %p\n", related_to);
3600 +       DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
3601 +       DEBUGP("mask:  "); DUMP_TUPLE(&expect->mask);
3602 +
3603 +       old = LIST_FIND(&ip_conntrack_expect_list, resent_expect,
3604 +                       struct ip_conntrack_expect *, &expect->tuple, 
3605 +                       &expect->mask);
3606 +       if (old) {
3607 +               /* Helper private data may contain offsets but no pointers
3608 +                  pointing into the payload - otherwise we should have to copy 
3609 +                  the data filled out by the helper over the old one */
3610 +               DEBUGP("expect_related: resent packet\n");
3611 +               if (related_to->helper->timeout) {
3612 +                       if (!del_timer(&old->timeout)) {
3613 +                               /* expectation is dying. Fall through */
3614 +                               old = NULL;
3615 +                       } else {
3616 +                               old->timeout.expires = jiffies + 
3617 +                                       related_to->helper->timeout * HZ;
3618 +                               add_timer(&old->timeout);
3619 +                       }
3620 +               }
3621 +
3622 +               if (old) {
3623 +                       WRITE_UNLOCK(&ip_conntrack_lock);
3624 +                       return -EEXIST;
3625 +               }
3626 +       } else if (related_to->helper->max_expected && 
3627 +                  related_to->expecting >= related_to->helper->max_expected) {
3628 +               /* old == NULL */
3629 +               if (!(related_to->helper->flags & 
3630 +                     IP_CT_HELPER_F_REUSE_EXPECT)) {
3631 +                       WRITE_UNLOCK(&ip_conntrack_lock);
3632 +                       if (net_ratelimit())
3633 +                               printk(KERN_WARNING
3634 +                                      "ip_conntrack: max number of expected "
3635 +                                      "connections %i of %s reached for "
3636 +                                      "%u.%u.%u.%u->%u.%u.%u.%u\n",
3637 +                                      related_to->helper->max_expected,
3638 +                                      related_to->helper->name,
3639 +                                      NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
3640 +                                      NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3641 +                       return -EPERM;
3642 +               }
3643 +               DEBUGP("ip_conntrack: max number of expected "
3644 +                      "connections %i of %s reached for "
3645 +                      "%u.%u.%u.%u->%u.%u.%u.%u, reusing\n",
3646 +                      related_to->helper->max_expected,
3647 +                      related_to->helper->name,
3648 +                      NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
3649 +                      NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3650
3651 +               /* choose the the oldest expectation to evict */
3652 +               list_for_each_entry(old, &related_to->sibling_list, 
3653 +                                                     expected_list)
3654 +                       if (old->sibling == NULL)
3655 +                               break;
3656 +
3657 +               /* We cannot fail since related_to->expecting is the number
3658 +                * of unconfirmed expectations */
3659 +               IP_NF_ASSERT(old && old->sibling == NULL);
3660 +
3661 +               /* newnat14 does not reuse the real allocated memory
3662 +                * structures but rather unexpects the old and
3663 +                * allocates a new.  unexpect_related will decrement
3664 +                * related_to->expecting. 
3665 +                */
3666 +               unexpect_related(old);
3667 +               ret = -EPERM;
3668 +       } else if (LIST_FIND(&ip_conntrack_expect_list, expect_clash,
3669 +                            struct ip_conntrack_expect *, &expect->tuple, 
3670 +                            &expect->mask)) {
3671 +               WRITE_UNLOCK(&ip_conntrack_lock);
3672 +               DEBUGP("expect_related: busy!\n");
3673 +               return -EBUSY;
3674 +       }
3675 +       
3676 +       new = (struct ip_conntrack_expect *) 
3677 +             kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
3678 +       if (!new) {
3679 +               WRITE_UNLOCK(&ip_conntrack_lock);
3680 +               DEBUGP("expect_relaed: OOM allocating expect\n");
3681 +               return -ENOMEM;
3682 +       }
3683 +       
3684 +       DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
3685 +       memcpy(new, expect, sizeof(*expect));
3686 +       new->expectant = related_to;
3687 +       new->sibling = NULL;
3688 +       atomic_set(&new->use, 1);
3689 +       
3690 +       /* add to expected list for this connection */  
3691 +       list_add_tail(&new->expected_list, &related_to->sibling_list);
3692 +       /* add to global list of expectations */
3693 +       list_prepend(&ip_conntrack_expect_list, &new->list);
3694 +       /* add and start timer if required */
3695 +       if (related_to->helper->timeout) {
3696 +               init_timer(&new->timeout);
3697 +               new->timeout.data = (unsigned long)new;
3698 +               new->timeout.function = expectation_timed_out;
3699 +               new->timeout.expires = jiffies + 
3700 +                                       related_to->helper->timeout * HZ;
3701 +               add_timer(&new->timeout);
3702 +       }
3703 +       related_to->expecting++;
3704 +
3705 +       WRITE_UNLOCK(&ip_conntrack_lock);
3706 +
3707 +       return ret;
3708 +}
3709 +
3710 +/* Change tuple in an existing expectation */
3711 +int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
3712 +                              struct ip_conntrack_tuple *newtuple)
3713 +{
3714 +       int ret;
3715 +
3716 +       MUST_BE_READ_LOCKED(&ip_conntrack_lock);
3717 +       WRITE_LOCK(&ip_conntrack_expect_tuple_lock);
3718 +
3719 +       DEBUGP("change_expect:\n");
3720 +       DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple);
3721 +       DEBUGP("exp mask:  "); DUMP_TUPLE(&expect->mask);
3722 +       DEBUGP("newtuple:  "); DUMP_TUPLE(newtuple);
3723 +       if (expect->ct_tuple.dst.protonum == 0) {
3724 +               /* Never seen before */
3725 +               DEBUGP("change expect: never seen before\n");
3726 +               if (!ip_ct_tuple_equal(&expect->tuple, newtuple) 
3727 +                   && LIST_FIND(&ip_conntrack_expect_list, expect_clash,
3728 +                                struct ip_conntrack_expect *, newtuple, &expect->mask)) {
3729 +                       /* Force NAT to find an unused tuple */
3730 +                       ret = -1;
3731 +               } else {
3732 +                       memcpy(&expect->ct_tuple, &expect->tuple, sizeof(expect->tuple));
3733 +                       memcpy(&expect->tuple, newtuple, sizeof(expect->tuple));
3734 +                       ret = 0;
3735 +               }
3736 +       } else {
3737 +               /* Resent packet */
3738 +               DEBUGP("change expect: resent packet\n");
3739 +               if (ip_ct_tuple_equal(&expect->tuple, newtuple)) {
3740 +                       ret = 0;
3741 +               } else {
3742 +                       /* Force NAT to choose again the same port */
3743 +                       ret = -1;
3744 +               }
3745 +       }
3746 +       WRITE_UNLOCK(&ip_conntrack_expect_tuple_lock);
3747 +       
3748 +       return ret;
3749 +}
3750 +
3751 +/* Alter reply tuple (maybe alter helper).  If it's already taken,
3752 +   return 0 and don't do alteration. */
3753 +int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
3754 +                            const struct ip_conntrack_tuple *newreply)
3755 +{
3756 +       WRITE_LOCK(&ip_conntrack_lock);
3757 +       if (__ip_conntrack_find(newreply, conntrack)) {
3758 +               WRITE_UNLOCK(&ip_conntrack_lock);
3759 +               return 0;
3760 +       }
3761 +       /* Should be unconfirmed, so not in hash table yet */
3762 +       IP_NF_ASSERT(!is_confirmed(conntrack));
3763 +
3764 +       DEBUGP("Altering reply tuple of %p to ", conntrack);
3765 +       DUMP_TUPLE(newreply);
3766 +
3767 +       conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
3768 +       if (!conntrack->master)
3769 +               conntrack->helper = LIST_FIND(&helpers, helper_cmp,
3770 +                                             struct ip_conntrack_helper *,
3771 +                                             newreply);
3772 +       WRITE_UNLOCK(&ip_conntrack_lock);
3773 +
3774 +       return 1;
3775 +}
3776 +
3777 +int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
3778 +{
3779 +       WRITE_LOCK(&ip_conntrack_lock);
3780 +       list_prepend(&helpers, me);
3781 +       WRITE_UNLOCK(&ip_conntrack_lock);
3782 +
3783 +       return 0;
3784 +}
3785 +
3786 +static inline int unhelp(struct ip_conntrack_tuple_hash *i,
3787 +                        const struct ip_conntrack_helper *me)
3788 +{
3789 +       if (i->ctrack->helper == me) {
3790 +               /* Get rid of any expected. */
3791 +               remove_expectations(i->ctrack, 0);
3792 +               /* And *then* set helper to NULL */
3793 +               i->ctrack->helper = NULL;
3794 +       }
3795 +       return 0;
3796 +}
3797 +
3798 +void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
3799 +{
3800 +       unsigned int i;
3801 +
3802 +       /* Need write lock here, to delete helper. */
3803 +       WRITE_LOCK(&ip_conntrack_lock);
3804 +       LIST_DELETE(&helpers, me);
3805 +
3806 +       /* Get rid of expecteds, set helpers to NULL. */
3807 +       for (i = 0; i < ip_conntrack_htable_size; i++)
3808 +               LIST_FIND_W(&ip_conntrack_hash[i], unhelp,
3809 +                           struct ip_conntrack_tuple_hash *, me);
3810 +       WRITE_UNLOCK(&ip_conntrack_lock);
3811 +
3812 +       /* Someone could be still looking at the helper in a bh. */
3813 +       synchronize_net();
3814 +}
3815 +
3816 +/* Refresh conntrack for this many jiffies. */
3817 +void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
3818 +{
3819 +       IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
3820 +
3821 +       WRITE_LOCK(&ip_conntrack_lock);
3822 +       /* If not in hash table, timer will not be active yet */
3823 +       if (!is_confirmed(ct))
3824 +               ct->timeout.expires = extra_jiffies;
3825 +       else {
3826 +               /* Need del_timer for race avoidance (may already be dying). */
3827 +               if (del_timer(&ct->timeout)) {
3828 +                       ct->timeout.expires = jiffies + extra_jiffies;
3829 +                       add_timer(&ct->timeout);
3830 +               }
3831 +       }
3832 +       WRITE_UNLOCK(&ip_conntrack_lock);
3833 +}
3834 +
3835 +/* Returns new sk_buff, or NULL */
3836 +struct sk_buff *
3837 +ip_ct_gather_frags(struct sk_buff *skb)
3838 +{
3839 +       struct sock *sk = skb->sk;
3840 +#ifdef CONFIG_NETFILTER_DEBUG
3841 +       unsigned int olddebug = skb->nf_debug;
3842 +#endif
3843 +       if (sk) {
3844 +               sock_hold(sk);
3845 +               skb_orphan(skb);
3846 +       }
3847 +
3848 +       local_bh_disable(); 
3849 +       skb = ip_defrag(skb);
3850 +       local_bh_enable();
3851 +
3852 +       if (!skb) {
3853 +               if (sk)
3854 +                       sock_put(sk);
3855 +               return skb;
3856 +       }
3857 +
3858 +       if (sk) {
3859 +               skb_set_owner_w(skb, sk);
3860 +               sock_put(sk);
3861 +       }
3862 +
3863 +       ip_send_check(skb->nh.iph);
3864 +       skb->nfcache |= NFC_ALTERED;
3865 +#ifdef CONFIG_NETFILTER_DEBUG
3866 +       /* Packet path as if nothing had happened. */
3867 +       skb->nf_debug = olddebug;
3868 +#endif
3869 +       return skb;
3870 +}
3871 +
3872 +/* Used by ipt_REJECT. */
3873 +static void ip_conntrack_attach(struct sk_buff *nskb, struct nf_ct_info *nfct)
3874 +{
3875 +       struct ip_conntrack *ct;
3876 +       enum ip_conntrack_info ctinfo;
3877 +
3878 +       ct = __ip_conntrack_get(nfct, &ctinfo);
3879 +
3880 +       /* This ICMP is in reverse direction to the packet which
3881 +           caused it */
3882 +       if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
3883 +               ctinfo = IP_CT_RELATED + IP_CT_IS_REPLY;
3884 +       else
3885 +               ctinfo = IP_CT_RELATED;
3886 +
3887 +       /* Attach new skbuff, and increment count */
3888 +       nskb->nfct = &ct->infos[ctinfo];
3889 +       atomic_inc(&ct->ct_general.use);
3890 +}
3891 +
3892 +static inline int
3893 +do_kill(const struct ip_conntrack_tuple_hash *i,
3894 +       int (*kill)(const struct ip_conntrack *i, void *data),
3895 +       void *data)
3896 +{
3897 +       return kill(i->ctrack, data);
3898 +}
3899 +
3900 +/* Bring out ya dead! */
3901 +static struct ip_conntrack_tuple_hash *
3902 +get_next_corpse(int (*kill)(const struct ip_conntrack *i, void *data),
3903 +               void *data)
3904 +{
3905 +       struct ip_conntrack_tuple_hash *h = NULL;
3906 +       unsigned int i;
3907 +
3908 +       READ_LOCK(&ip_conntrack_lock);
3909 +       for (i = 0; !h && i < ip_conntrack_htable_size; i++) {
3910 +               h = LIST_FIND(&ip_conntrack_hash[i], do_kill,
3911 +                             struct ip_conntrack_tuple_hash *, kill, data);
3912 +       }
3913 +       if (h)
3914 +               atomic_inc(&h->ctrack->ct_general.use);
3915 +       READ_UNLOCK(&ip_conntrack_lock);
3916 +
3917 +       return h;
3918 +}
3919 +
3920 +void
3921 +ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
3922 +                       void *data)
3923 +{
3924 +       struct ip_conntrack_tuple_hash *h;
3925 +
3926 +       /* This is order n^2, by the way. */
3927 +       while ((h = get_next_corpse(kill, data)) != NULL) {
3928 +               /* Time to push up daises... */
3929 +               if (del_timer(&h->ctrack->timeout))
3930 +                       death_by_timeout((unsigned long)h->ctrack);
3931 +               /* ... else the timer will get him soon. */
3932 +
3933 +               ip_conntrack_put(h->ctrack);
3934 +       }
3935 +}
3936 +
3937 +/* Fast function for those who don't want to parse /proc (and I don't
3938 +   blame them). */
3939 +/* Reversing the socket's dst/src point of view gives us the reply
3940 +   mapping. */
3941 +static int
3942 +getorigdst(struct sock *sk, int optval, void *user, int *len)
3943 +{
3944 +       struct inet_opt *inet = inet_sk(sk);
3945 +       struct ip_conntrack_tuple_hash *h;
3946 +       struct ip_conntrack_tuple tuple;
3947 +       
3948 +       IP_CT_TUPLE_U_BLANK(&tuple);
3949 +       tuple.src.ip = inet->rcv_saddr;
3950 +       tuple.src.u.tcp.port = inet->sport;
3951 +       tuple.dst.ip = inet->daddr;
3952 +       tuple.dst.u.tcp.port = inet->dport;
3953 +       tuple.dst.protonum = IPPROTO_TCP;
3954 +
3955 +       /* We only do TCP at the moment: is there a better way? */
3956 +       if (strcmp(sk->sk_prot->name, "TCP")) {
3957 +               DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n");
3958 +               return -ENOPROTOOPT;
3959 +       }
3960 +
3961 +       if ((unsigned int) *len < sizeof(struct sockaddr_in)) {
3962 +               DEBUGP("SO_ORIGINAL_DST: len %u not %u\n",
3963 +                      *len, sizeof(struct sockaddr_in));
3964 +               return -EINVAL;
3965 +       }
3966 +
3967 +       h = ip_conntrack_find_get(&tuple, NULL);
3968 +       if (h) {
3969 +               struct sockaddr_in sin;
3970 +
3971 +               sin.sin_family = AF_INET;
3972 +               sin.sin_port = h->ctrack->tuplehash[IP_CT_DIR_ORIGINAL]
3973 +                       .tuple.dst.u.tcp.port;
3974 +               sin.sin_addr.s_addr = h->ctrack->tuplehash[IP_CT_DIR_ORIGINAL]
3975 +                       .tuple.dst.ip;
3976 +
3977 +               DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
3978 +                      NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
3979 +               ip_conntrack_put(h->ctrack);
3980 +               if (copy_to_user(user, &sin, sizeof(sin)) != 0)
3981 +                       return -EFAULT;
3982 +               else
3983 +                       return 0;
3984 +       }
3985 +       DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
3986 +              NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
3987 +              NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
3988 +       return -ENOENT;
3989 +}
3990 +
3991 +static struct nf_sockopt_ops so_getorigdst = {
3992 +       .pf             = PF_INET,
3993 +       .get_optmin     = SO_ORIGINAL_DST,
3994 +       .get_optmax     = SO_ORIGINAL_DST+1,
3995 +       .get            = &getorigdst,
3996 +};
3997 +
3998 +static int kill_all(const struct ip_conntrack *i, void *data)
3999 +{
4000 +       return 1;
4001 +}
4002 +
4003 +/* Mishearing the voices in his head, our hero wonders how he's
4004 +   supposed to kill the mall. */
4005 +void ip_conntrack_cleanup(void)
4006 +{
4007 +       ip_ct_attach = NULL;
4008 +       /* This makes sure all current packets have passed through
4009 +           netfilter framework.  Roll on, two-stage module
4010 +           delete... */
4011 +       synchronize_net();
4012
4013 + i_see_dead_people:
4014 +       ip_ct_selective_cleanup(kill_all, NULL);
4015 +       if (atomic_read(&ip_conntrack_count) != 0) {
4016 +               schedule();
4017 +               goto i_see_dead_people;
4018 +       }
4019 +
4020 +       kmem_cache_destroy(ip_conntrack_cachep);
4021 +       vfree(ip_conntrack_hash);
4022 +       nf_unregister_sockopt(&so_getorigdst);
4023 +}
4024 +
4025 +static int hashsize;
4026 +MODULE_PARM(hashsize, "i");
4027 +
4028 +int __init ip_conntrack_init(void)
4029 +{
4030 +       unsigned int i;
4031 +       int ret;
4032 +
4033 +       /* Idea from tcp.c: use 1/16384 of memory.  On i386: 32MB
4034 +        * machine has 256 buckets.  >= 1GB machines have 8192 buckets. */
4035 +       if (hashsize) {
4036 +               ip_conntrack_htable_size = hashsize;
4037 +       } else {
4038 +               ip_conntrack_htable_size
4039 +                       = (((num_physpages << PAGE_SHIFT) / 16384)
4040 +                          / sizeof(struct list_head));
4041 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
4042 +                       ip_conntrack_htable_size = 8192;
4043 +               if (ip_conntrack_htable_size < 16)
4044 +                       ip_conntrack_htable_size = 16;
4045 +       }
4046 +       ip_conntrack_max = 8 * ip_conntrack_htable_size;
4047 +
4048 +       printk("ip_conntrack version %s (%u buckets, %d max)"
4049 +              " - %Zd bytes per conntrack\n", IP_CONNTRACK_VERSION,
4050 +              ip_conntrack_htable_size, ip_conntrack_max,
4051 +              sizeof(struct ip_conntrack));
4052 +
4053 +       ret = nf_register_sockopt(&so_getorigdst);
4054 +       if (ret != 0) {
4055 +               printk(KERN_ERR "Unable to register netfilter socket option\n");
4056 +               return ret;
4057 +       }
4058 +
4059 +       ip_conntrack_hash = vmalloc(sizeof(struct list_head)
4060 +                                   * ip_conntrack_htable_size);
4061 +       if (!ip_conntrack_hash) {
4062 +               printk(KERN_ERR "Unable to create ip_conntrack_hash\n");
4063 +               goto err_unreg_sockopt;
4064 +       }
4065 +
4066 +       ip_conntrack_cachep = kmem_cache_create("ip_conntrack",
4067 +                                               sizeof(struct ip_conntrack), 0,
4068 +                                               SLAB_HWCACHE_ALIGN, NULL, NULL);
4069 +       if (!ip_conntrack_cachep) {
4070 +               printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
4071 +               goto err_free_hash;
4072 +       }
4073 +       /* Don't NEED lock here, but good form anyway. */
4074 +       WRITE_LOCK(&ip_conntrack_lock);
4075 +       /* Sew in builtin protocols. */
4076 +       list_append(&protocol_list, &ip_conntrack_protocol_tcp);
4077 +       list_append(&protocol_list, &ip_conntrack_protocol_udp);
4078 +       list_append(&protocol_list, &ip_conntrack_protocol_icmp);
4079 +       WRITE_UNLOCK(&ip_conntrack_lock);
4080 +
4081 +       for (i = 0; i < ip_conntrack_htable_size; i++)
4082 +               INIT_LIST_HEAD(&ip_conntrack_hash[i]);
4083 +
4084 +       /* For use by ipt_REJECT */
4085 +       ip_ct_attach = ip_conntrack_attach;
4086 +       return ret;
4087 +
4088 +err_free_hash:
4089 +       vfree(ip_conntrack_hash);
4090 +err_unreg_sockopt:
4091 +       nf_unregister_sockopt(&so_getorigdst);
4092 +
4093 +       return -ENOMEM;
4094 +}
4095 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.0-test9/net/ipv4/netfilter/ip_conntrack_standalone.c
4096 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_conntrack_standalone.c  2003-10-25 20:43:32.000000000 +0200
4097 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_conntrack_standalone.c      2003-11-13 11:01:39.000000000 +0100
4098 @@ -186,6 +186,26 @@
4099         return ip_conntrack_confirm(*pskb);
4100  }
4101  
4102 +static unsigned int ip_conntrack_defrag(unsigned int hooknum,
4103 +                                       struct sk_buff **pskb,
4104 +                                       const struct net_device *in,
4105 +                                       const struct net_device *out,
4106 +                                       int (*okfn)(struct sk_buff *))
4107 +{
4108 +       /* Previously seen (loopback)?  Ignore.  Do this before
4109 +           fragment check. */
4110 +       if ((*pskb)->nfct)
4111 +               return NF_ACCEPT;
4112 +
4113 +       /* Gather fragments. */
4114 +       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
4115 +               *pskb = ip_ct_gather_frags(*pskb);
4116 +               if (!*pskb)
4117 +                       return NF_STOLEN;
4118 +       }
4119 +       return NF_ACCEPT;
4120 +}
4121 +
4122  static unsigned int ip_refrag(unsigned int hooknum,
4123                               struct sk_buff **pskb,
4124                               const struct net_device *in,
4125 @@ -225,6 +245,15 @@
4126         return ip_conntrack_in(hooknum, pskb, in, out, okfn);
4127  }
4128  
4129 +/* At the very first: defragment */
4130 +static struct nf_hook_ops ip_conntrack_defrag_ops = {
4131 +       .hook           = ip_conntrack_defrag,
4132 +       .owner          = THIS_MODULE,
4133 +       .pf             = PF_INET,
4134 +       .hooknum        = NF_IP_PRE_ROUTING,
4135 +       .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
4136 +};
4137 +
4138  /* Connection tracking may drop packets, but never alters them, so
4139     make it the first hook. */
4140  static struct nf_hook_ops ip_conntrack_in_ops = {
4141 @@ -367,10 +396,15 @@
4142         if (!proc) goto cleanup_init;
4143         proc->owner = THIS_MODULE;
4144  
4145 +       ret = nf_register_hook(&ip_conntrack_defrag_ops);
4146 +       if (ret < 0) {
4147 +               printk("ip_conntrack: can't register pre-routing hook to defrag.\n");
4148 +               goto cleanup_proc;
4149 +       }
4150         ret = nf_register_hook(&ip_conntrack_in_ops);
4151         if (ret < 0) {
4152                 printk("ip_conntrack: can't register pre-routing hook.\n");
4153 -               goto cleanup_proc;
4154 +               goto cleanup_defragops;
4155         }
4156         ret = nf_register_hook(&ip_conntrack_local_out_ops);
4157         if (ret < 0) {
4158 @@ -408,6 +442,8 @@
4159         nf_unregister_hook(&ip_conntrack_local_out_ops);
4160   cleanup_inops:
4161         nf_unregister_hook(&ip_conntrack_in_ops);
4162 + cleanup_defragops:
4163 +       nf_unregister_hook(&ip_conntrack_defrag_ops);
4164   cleanup_proc:
4165         proc_net_remove("ip_conntrack");
4166   cleanup_init:
4167 @@ -499,5 +535,6 @@
4168  EXPORT_SYMBOL(ip_conntrack_expect_list);
4169  EXPORT_SYMBOL(ip_conntrack_lock);
4170  EXPORT_SYMBOL(ip_conntrack_hash);
4171 +EXPORT_SYMBOL(ip_conntrack_untracked);
4172  EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
4173  EXPORT_SYMBOL_GPL(ip_conntrack_put);
4174 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_conntrack_standalone.c.orig linux-2.6.0-test9/net/ipv4/netfilter/ip_conntrack_standalone.c.orig
4175 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_conntrack_standalone.c.orig     1970-01-01 01:00:00.000000000 +0100
4176 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_conntrack_standalone.c.orig 2003-10-25 20:43:32.000000000 +0200
4177 @@ -0,0 +1,503 @@
4178 +/* This file contains all the functions required for the standalone
4179 +   ip_conntrack module.
4180 +
4181 +   These are not required by the compatibility layer.
4182 +*/
4183 +
4184 +/* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
4185 +   Public Licence. */
4186 +
4187 +#include <linux/config.h>
4188 +#include <linux/types.h>
4189 +#include <linux/ip.h>
4190 +#include <linux/netfilter.h>
4191 +#include <linux/netfilter_ipv4.h>
4192 +#include <linux/module.h>
4193 +#include <linux/skbuff.h>
4194 +#include <linux/proc_fs.h>
4195 +#ifdef CONFIG_SYSCTL
4196 +#include <linux/sysctl.h>
4197 +#endif
4198 +#include <net/checksum.h>
4199 +
4200 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
4201 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
4202 +
4203 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4204 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4205 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4206 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4207 +#include <linux/netfilter_ipv4/listhelp.h>
4208 +
4209 +#if 0
4210 +#define DEBUGP printk
4211 +#else
4212 +#define DEBUGP(format, args...)
4213 +#endif
4214 +
4215 +MODULE_LICENSE("GPL");
4216 +
4217 +static int kill_proto(const struct ip_conntrack *i, void *data)
4218 +{
4219 +       return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == 
4220 +                       *((u_int8_t *) data));
4221 +}
4222 +
4223 +static unsigned int
4224 +print_tuple(char *buffer, const struct ip_conntrack_tuple *tuple,
4225 +           struct ip_conntrack_protocol *proto)
4226 +{
4227 +       int len;
4228 +
4229 +       len = sprintf(buffer, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
4230 +                     NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
4231 +
4232 +       len += proto->print_tuple(buffer + len, tuple);
4233 +
4234 +       return len;
4235 +}
4236 +
4237 +/* FIXME: Don't print source proto part. --RR */
4238 +static unsigned int
4239 +print_expect(char *buffer, const struct ip_conntrack_expect *expect)
4240 +{
4241 +       unsigned int len;
4242 +
4243 +       if (expect->expectant->helper->timeout)
4244 +               len = sprintf(buffer, "EXPECTING: %lu ",
4245 +                             timer_pending(&expect->timeout)
4246 +                             ? (expect->timeout.expires - jiffies)/HZ : 0);
4247 +       else
4248 +               len = sprintf(buffer, "EXPECTING: - ");
4249 +       len += sprintf(buffer + len, "use=%u proto=%u ",
4250 +                     atomic_read(&expect->use), expect->tuple.dst.protonum);
4251 +       len += print_tuple(buffer + len, &expect->tuple,
4252 +                          __ip_ct_find_proto(expect->tuple.dst.protonum));
4253 +       len += sprintf(buffer + len, "\n");
4254 +       return len;
4255 +}
4256 +
4257 +static unsigned int
4258 +print_conntrack(char *buffer, struct ip_conntrack *conntrack)
4259 +{
4260 +       unsigned int len;
4261 +       struct ip_conntrack_protocol *proto
4262 +               = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
4263 +                              .tuple.dst.protonum);
4264 +
4265 +       len = sprintf(buffer, "%-8s %u %lu ",
4266 +                     proto->name,
4267 +                     conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
4268 +                     .tuple.dst.protonum,
4269 +                     timer_pending(&conntrack->timeout)
4270 +                     ? (conntrack->timeout.expires - jiffies)/HZ : 0);
4271 +
4272 +       len += proto->print_conntrack(buffer + len, conntrack);
4273 +       len += print_tuple(buffer + len,
4274 +                          &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
4275 +                          proto);
4276 +       if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
4277 +               len += sprintf(buffer + len, "[UNREPLIED] ");
4278 +       len += print_tuple(buffer + len,
4279 +                          &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
4280 +                          proto);
4281 +       if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
4282 +               len += sprintf(buffer + len, "[ASSURED] ");
4283 +       len += sprintf(buffer + len, "use=%u ",
4284 +                      atomic_read(&conntrack->ct_general.use));
4285 +       len += sprintf(buffer + len, "\n");
4286 +
4287 +       return len;
4288 +}
4289 +
4290 +/* Returns true when finished. */
4291 +static inline int
4292 +conntrack_iterate(const struct ip_conntrack_tuple_hash *hash,
4293 +                 char *buffer, off_t offset, off_t *upto,
4294 +                 unsigned int *len, unsigned int maxlen)
4295 +{
4296 +       unsigned int newlen;
4297 +       IP_NF_ASSERT(hash->ctrack);
4298 +
4299 +       MUST_BE_READ_LOCKED(&ip_conntrack_lock);
4300 +
4301 +       /* Only count originals */
4302 +       if (DIRECTION(hash))
4303 +               return 0;
4304 +
4305 +       if ((*upto)++ < offset)
4306 +               return 0;
4307 +
4308 +       newlen = print_conntrack(buffer + *len, hash->ctrack);
4309 +       if (*len + newlen > maxlen)
4310 +               return 1;
4311 +       else *len += newlen;
4312 +
4313 +       return 0;
4314 +}
4315 +
4316 +static int
4317 +list_conntracks(char *buffer, char **start, off_t offset, int length)
4318 +{
4319 +       unsigned int i;
4320 +       unsigned int len = 0;
4321 +       off_t upto = 0;
4322 +       struct list_head *e;
4323 +
4324 +       READ_LOCK(&ip_conntrack_lock);
4325 +       /* Traverse hash; print originals then reply. */
4326 +       for (i = 0; i < ip_conntrack_htable_size; i++) {
4327 +               if (LIST_FIND(&ip_conntrack_hash[i], conntrack_iterate,
4328 +                             struct ip_conntrack_tuple_hash *,
4329 +                             buffer, offset, &upto, &len, length))
4330 +                       goto finished;
4331 +       }
4332 +
4333 +       /* Now iterate through expecteds. */
4334 +       list_for_each(e, &ip_conntrack_expect_list) {
4335 +               unsigned int last_len;
4336 +               struct ip_conntrack_expect *expect
4337 +                       = (struct ip_conntrack_expect *)e;
4338 +               if (upto++ < offset) continue;
4339 +
4340 +               last_len = len;
4341 +               len += print_expect(buffer + len, expect);
4342 +               if (len > length) {
4343 +                       len = last_len;
4344 +                       goto finished;
4345 +               }
4346 +       }
4347 +
4348 + finished:
4349 +       READ_UNLOCK(&ip_conntrack_lock);
4350 +
4351 +       /* `start' hack - see fs/proc/generic.c line ~165 */
4352 +       *start = (char *)((unsigned int)upto - offset);
4353 +       return len;
4354 +}
4355 +
4356 +static unsigned int ip_confirm(unsigned int hooknum,
4357 +                              struct sk_buff **pskb,
4358 +                              const struct net_device *in,
4359 +                              const struct net_device *out,
4360 +                              int (*okfn)(struct sk_buff *))
4361 +{
4362 +       /* We've seen it coming out the other side: confirm it */
4363 +       return ip_conntrack_confirm(*pskb);
4364 +}
4365 +
4366 +static unsigned int ip_refrag(unsigned int hooknum,
4367 +                             struct sk_buff **pskb,
4368 +                             const struct net_device *in,
4369 +                             const struct net_device *out,
4370 +                             int (*okfn)(struct sk_buff *))
4371 +{
4372 +       struct rtable *rt = (struct rtable *)(*pskb)->dst;
4373 +
4374 +       /* We've seen it coming out the other side: confirm */
4375 +       if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
4376 +               return NF_DROP;
4377 +
4378 +       /* Local packets are never produced too large for their
4379 +          interface.  We degfragment them at LOCAL_OUT, however,
4380 +          so we have to refragment them here. */
4381 +       if ((*pskb)->len > dst_pmtu(&rt->u.dst)) {
4382 +               /* No hook can be after us, so this should be OK. */
4383 +               ip_fragment(*pskb, okfn);
4384 +               return NF_STOLEN;
4385 +       }
4386 +       return NF_ACCEPT;
4387 +}
4388 +
4389 +static unsigned int ip_conntrack_local(unsigned int hooknum,
4390 +                                      struct sk_buff **pskb,
4391 +                                      const struct net_device *in,
4392 +                                      const struct net_device *out,
4393 +                                      int (*okfn)(struct sk_buff *))
4394 +{
4395 +       /* root is playing with raw sockets. */
4396 +       if ((*pskb)->len < sizeof(struct iphdr)
4397 +           || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
4398 +               if (net_ratelimit())
4399 +                       printk("ipt_hook: happy cracking.\n");
4400 +               return NF_ACCEPT;
4401 +       }
4402 +       return ip_conntrack_in(hooknum, pskb, in, out, okfn);
4403 +}
4404 +
4405 +/* Connection tracking may drop packets, but never alters them, so
4406 +   make it the first hook. */
4407 +static struct nf_hook_ops ip_conntrack_in_ops = {
4408 +       .hook           = ip_conntrack_in,
4409 +       .owner          = THIS_MODULE,
4410 +       .pf             = PF_INET,
4411 +       .hooknum        = NF_IP_PRE_ROUTING,
4412 +       .priority       = NF_IP_PRI_CONNTRACK,
4413 +};
4414 +
4415 +static struct nf_hook_ops ip_conntrack_local_out_ops = {
4416 +       .hook           = ip_conntrack_local,
4417 +       .owner          = THIS_MODULE,
4418 +       .pf             = PF_INET,
4419 +       .hooknum        = NF_IP_LOCAL_OUT,
4420 +       .priority       = NF_IP_PRI_CONNTRACK,
4421 +};
4422 +
4423 +/* Refragmenter; last chance. */
4424 +static struct nf_hook_ops ip_conntrack_out_ops = {
4425 +       .hook           = ip_refrag,
4426 +       .owner          = THIS_MODULE,
4427 +       .pf             = PF_INET,
4428 +       .hooknum        = NF_IP_POST_ROUTING,
4429 +       .priority       = NF_IP_PRI_LAST,
4430 +};
4431 +
4432 +static struct nf_hook_ops ip_conntrack_local_in_ops = {
4433 +       .hook           = ip_confirm,
4434 +       .owner          = THIS_MODULE,
4435 +       .pf             = PF_INET,
4436 +       .hooknum        = NF_IP_LOCAL_IN,
4437 +       .priority       = NF_IP_PRI_LAST-1,
4438 +};
4439 +
4440 +/* Sysctl support */
4441 +
4442 +#ifdef CONFIG_SYSCTL
4443 +
4444 +/* From ip_conntrack_core.c */
4445 +extern int ip_conntrack_max;
4446 +
4447 +/* From ip_conntrack_proto_tcp.c */
4448 +extern unsigned long ip_ct_tcp_timeout_syn_sent;
4449 +extern unsigned long ip_ct_tcp_timeout_syn_recv;
4450 +extern unsigned long ip_ct_tcp_timeout_established;
4451 +extern unsigned long ip_ct_tcp_timeout_fin_wait;
4452 +extern unsigned long ip_ct_tcp_timeout_close_wait;
4453 +extern unsigned long ip_ct_tcp_timeout_last_ack;
4454 +extern unsigned long ip_ct_tcp_timeout_time_wait;
4455 +extern unsigned long ip_ct_tcp_timeout_close;
4456 +
4457 +/* From ip_conntrack_proto_udp.c */
4458 +extern unsigned long ip_ct_udp_timeout;
4459 +extern unsigned long ip_ct_udp_timeout_stream;
4460 +
4461 +/* From ip_conntrack_proto_icmp.c */
4462 +extern unsigned long ip_ct_icmp_timeout;
4463 +
4464 +/* From ip_conntrack_proto_icmp.c */
4465 +extern unsigned long ip_ct_generic_timeout;
4466 +
4467 +static struct ctl_table_header *ip_ct_sysctl_header;
4468 +
4469 +static ctl_table ip_ct_sysctl_table[] = {
4470 +       {NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max",
4471 +        &ip_conntrack_max, sizeof(int), 0644, NULL,
4472 +        &proc_dointvec},
4473 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent",
4474 +        &ip_ct_tcp_timeout_syn_sent, sizeof(unsigned int), 0644, NULL,
4475 +        &proc_dointvec_jiffies},
4476 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "ip_conntrack_tcp_timeout_syn_recv",
4477 +        &ip_ct_tcp_timeout_syn_recv, sizeof(unsigned int), 0644, NULL,
4478 +        &proc_dointvec_jiffies},
4479 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "ip_conntrack_tcp_timeout_established",
4480 +        &ip_ct_tcp_timeout_established, sizeof(unsigned int), 0644, NULL,
4481 +        &proc_dointvec_jiffies},
4482 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "ip_conntrack_tcp_timeout_fin_wait",
4483 +        &ip_ct_tcp_timeout_fin_wait, sizeof(unsigned int), 0644, NULL,
4484 +        &proc_dointvec_jiffies},
4485 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "ip_conntrack_tcp_timeout_close_wait",
4486 +        &ip_ct_tcp_timeout_close_wait, sizeof(unsigned int), 0644, NULL,
4487 +        &proc_dointvec_jiffies},
4488 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "ip_conntrack_tcp_timeout_last_ack",
4489 +        &ip_ct_tcp_timeout_last_ack, sizeof(unsigned int), 0644, NULL,
4490 +        &proc_dointvec_jiffies},
4491 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "ip_conntrack_tcp_timeout_time_wait",
4492 +        &ip_ct_tcp_timeout_time_wait, sizeof(unsigned int), 0644, NULL,
4493 +        &proc_dointvec_jiffies},
4494 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "ip_conntrack_tcp_timeout_close",
4495 +        &ip_ct_tcp_timeout_close, sizeof(unsigned int), 0644, NULL,
4496 +        &proc_dointvec_jiffies},
4497 +       {NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, "ip_conntrack_udp_timeout",
4498 +        &ip_ct_udp_timeout, sizeof(unsigned int), 0644, NULL,
4499 +        &proc_dointvec_jiffies},
4500 +       {NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "ip_conntrack_udp_timeout_stream",
4501 +        &ip_ct_udp_timeout_stream, sizeof(unsigned int), 0644, NULL,
4502 +        &proc_dointvec_jiffies},
4503 +       {NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, "ip_conntrack_icmp_timeout",
4504 +        &ip_ct_icmp_timeout, sizeof(unsigned int), 0644, NULL,
4505 +        &proc_dointvec_jiffies},
4506 +       {NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout",
4507 +        &ip_ct_generic_timeout, sizeof(unsigned int), 0644, NULL,
4508 +        &proc_dointvec_jiffies},
4509 +       {0}
4510 +};
4511 +
4512 +#define NET_IP_CONNTRACK_MAX 2089
4513 +
4514 +static ctl_table ip_ct_netfilter_table[] = {
4515 +       {NET_IPV4_NETFILTER, "netfilter", NULL, 0, 0555, ip_ct_sysctl_table, 0, 0, 0, 0, 0},
4516 +       {NET_IP_CONNTRACK_MAX, "ip_conntrack_max",
4517 +        &ip_conntrack_max, sizeof(int), 0644, NULL,
4518 +        &proc_dointvec},
4519 +       {0}
4520 +};
4521 +
4522 +static ctl_table ip_ct_ipv4_table[] = {
4523 +       {NET_IPV4, "ipv4", NULL, 0, 0555, ip_ct_netfilter_table, 0, 0, 0, 0, 0},
4524 +       {0}
4525 +};
4526 +
4527 +static ctl_table ip_ct_net_table[] = {
4528 +       {CTL_NET, "net", NULL, 0, 0555, ip_ct_ipv4_table, 0, 0, 0, 0, 0},
4529 +       {0}
4530 +};
4531 +#endif
4532 +static int init_or_cleanup(int init)
4533 +{
4534 +       struct proc_dir_entry *proc;
4535 +       int ret = 0;
4536 +
4537 +       if (!init) goto cleanup;
4538 +
4539 +       ret = ip_conntrack_init();
4540 +       if (ret < 0)
4541 +               goto cleanup_nothing;
4542 +
4543 +       proc = proc_net_create("ip_conntrack",0,list_conntracks);
4544 +       if (!proc) goto cleanup_init;
4545 +       proc->owner = THIS_MODULE;
4546 +
4547 +       ret = nf_register_hook(&ip_conntrack_in_ops);
4548 +       if (ret < 0) {
4549 +               printk("ip_conntrack: can't register pre-routing hook.\n");
4550 +               goto cleanup_proc;
4551 +       }
4552 +       ret = nf_register_hook(&ip_conntrack_local_out_ops);
4553 +       if (ret < 0) {
4554 +               printk("ip_conntrack: can't register local out hook.\n");
4555 +               goto cleanup_inops;
4556 +       }
4557 +       ret = nf_register_hook(&ip_conntrack_out_ops);
4558 +       if (ret < 0) {
4559 +               printk("ip_conntrack: can't register post-routing hook.\n");
4560 +               goto cleanup_inandlocalops;
4561 +       }
4562 +       ret = nf_register_hook(&ip_conntrack_local_in_ops);
4563 +       if (ret < 0) {
4564 +               printk("ip_conntrack: can't register local in hook.\n");
4565 +               goto cleanup_inoutandlocalops;
4566 +       }
4567 +#ifdef CONFIG_SYSCTL
4568 +       ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
4569 +       if (ip_ct_sysctl_header == NULL) {
4570 +               printk("ip_conntrack: can't register to sysctl.\n");
4571 +               goto cleanup;
4572 +       }
4573 +#endif
4574 +
4575 +       return ret;
4576 +
4577 + cleanup:
4578 +#ifdef CONFIG_SYSCTL
4579 +       unregister_sysctl_table(ip_ct_sysctl_header);
4580 +#endif
4581 +       nf_unregister_hook(&ip_conntrack_local_in_ops);
4582 + cleanup_inoutandlocalops:
4583 +       nf_unregister_hook(&ip_conntrack_out_ops);
4584 + cleanup_inandlocalops:
4585 +       nf_unregister_hook(&ip_conntrack_local_out_ops);
4586 + cleanup_inops:
4587 +       nf_unregister_hook(&ip_conntrack_in_ops);
4588 + cleanup_proc:
4589 +       proc_net_remove("ip_conntrack");
4590 + cleanup_init:
4591 +       ip_conntrack_cleanup();
4592 + cleanup_nothing:
4593 +       return ret;
4594 +}
4595 +
4596 +/* FIXME: Allow NULL functions and sub in pointers to generic for
4597 +   them. --RR */
4598 +int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
4599 +{
4600 +       int ret = 0;
4601 +       struct list_head *i;
4602 +
4603 +       WRITE_LOCK(&ip_conntrack_lock);
4604 +       list_for_each(i, &protocol_list) {
4605 +               if (((struct ip_conntrack_protocol *)i)->proto
4606 +                   == proto->proto) {
4607 +                       ret = -EBUSY;
4608 +                       goto out;
4609 +               }
4610 +       }
4611 +
4612 +       list_prepend(&protocol_list, proto);
4613 +
4614 + out:
4615 +       WRITE_UNLOCK(&ip_conntrack_lock);
4616 +       return ret;
4617 +}
4618 +
4619 +void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
4620 +{
4621 +       WRITE_LOCK(&ip_conntrack_lock);
4622 +
4623 +       /* ip_ct_find_proto() returns proto_generic in case there is no protocol 
4624 +        * helper. So this should be enough - HW */
4625 +       LIST_DELETE(&protocol_list, proto);
4626 +       WRITE_UNLOCK(&ip_conntrack_lock);
4627 +       
4628 +       /* Somebody could be still looking at the proto in bh. */
4629 +       synchronize_net();
4630 +
4631 +       /* Remove all contrack entries for this protocol */
4632 +       ip_ct_selective_cleanup(kill_proto, &proto->proto);
4633 +}
4634 +
4635 +static int __init init(void)
4636 +{
4637 +       return init_or_cleanup(1);
4638 +}
4639 +
4640 +static void __exit fini(void)
4641 +{
4642 +       init_or_cleanup(0);
4643 +}
4644 +
4645 +module_init(init);
4646 +module_exit(fini);
4647 +
4648 +/* Some modules need us, but don't depend directly on any symbol.
4649 +   They should call this. */
4650 +void need_ip_conntrack(void)
4651 +{
4652 +}
4653 +
4654 +EXPORT_SYMBOL(ip_conntrack_protocol_register);
4655 +EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
4656 +EXPORT_SYMBOL(invert_tuplepr);
4657 +EXPORT_SYMBOL(ip_conntrack_alter_reply);
4658 +EXPORT_SYMBOL(ip_conntrack_destroyed);
4659 +EXPORT_SYMBOL(ip_conntrack_get);
4660 +EXPORT_SYMBOL(need_ip_conntrack);
4661 +EXPORT_SYMBOL(ip_conntrack_helper_register);
4662 +EXPORT_SYMBOL(ip_conntrack_helper_unregister);
4663 +EXPORT_SYMBOL(ip_ct_selective_cleanup);
4664 +EXPORT_SYMBOL(ip_ct_refresh);
4665 +EXPORT_SYMBOL(ip_ct_find_proto);
4666 +EXPORT_SYMBOL(__ip_ct_find_proto);
4667 +EXPORT_SYMBOL(ip_ct_find_helper);
4668 +EXPORT_SYMBOL(ip_conntrack_expect_related);
4669 +EXPORT_SYMBOL(ip_conntrack_change_expect);
4670 +EXPORT_SYMBOL(ip_conntrack_unexpect_related);
4671 +EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
4672 +EXPORT_SYMBOL_GPL(ip_conntrack_expect_put);
4673 +EXPORT_SYMBOL(ip_conntrack_tuple_taken);
4674 +EXPORT_SYMBOL(ip_ct_gather_frags);
4675 +EXPORT_SYMBOL(ip_conntrack_htable_size);
4676 +EXPORT_SYMBOL(ip_conntrack_expect_list);
4677 +EXPORT_SYMBOL(ip_conntrack_lock);
4678 +EXPORT_SYMBOL(ip_conntrack_hash);
4679 +EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
4680 +EXPORT_SYMBOL_GPL(ip_conntrack_put);
4681 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_conntrack_tftp.c linux-2.6.0-test9/net/ipv4/netfilter/ip_conntrack_tftp.c
4682 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_conntrack_tftp.c        2003-10-25 20:43:19.000000000 +0200
4683 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_conntrack_tftp.c    2003-11-13 11:01:08.000000000 +0100
4684 @@ -97,8 +97,6 @@
4685  
4686         for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
4687                 /* Create helper structure */
4688 -               memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
4689 -
4690                 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
4691                 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
4692                 tftp[i].mask.dst.protonum = 0xFFFF;
4693 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_nat_amanda.c linux-2.6.0-test9/net/ipv4/netfilter/ip_nat_amanda.c
4694 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_nat_amanda.c    2003-10-25 20:43:06.000000000 +0200
4695 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_nat_amanda.c        2003-11-13 11:01:08.000000000 +0100
4696 @@ -195,8 +195,6 @@
4697         struct ip_nat_helper *hlpr;
4698  
4699         hlpr = &ip_nat_amanda_helper;
4700 -       memset(hlpr, 0, sizeof(struct ip_nat_helper));
4701 -
4702         hlpr->tuple.dst.protonum = IPPROTO_UDP;
4703         hlpr->tuple.src.u.udp.port = htons(10080);
4704         hlpr->mask.src.u.udp.port = 0xFFFF;
4705 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.0-test9/net/ipv4/netfilter/ip_nat_core.c
4706 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_nat_core.c      2003-11-13 11:07:50.000000000 +0100
4707 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_nat_core.c  2003-11-13 11:01:39.000000000 +0100
4708 @@ -810,7 +810,7 @@
4709  
4710                 /* Have to grab read lock before sibling_list traversal */
4711                 READ_LOCK(&ip_conntrack_lock);
4712 -               list_for_each(cur_item, &ct->sibling_list) { 
4713 +               list_for_each_prev(cur_item, &ct->sibling_list) { 
4714                         exp = list_entry(cur_item, struct ip_conntrack_expect, 
4715                                          expected_list);
4716                                          
4717 @@ -1010,7 +1010,11 @@
4718         /* FIXME: Man, this is a hack.  <SIGH> */
4719         IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
4720         ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
4721 -
4722 +       
4723 +       /* Initialize fake conntrack so that NAT will skip it */
4724 +       ip_conntrack_untracked.nat.info.initialized |= 
4725 +               (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
4726
4727         return 0;
4728  }
4729  
4730 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_nat_core.c.orig linux-2.6.0-test9/net/ipv4/netfilter/ip_nat_core.c.orig
4731 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_nat_core.c.orig 1970-01-01 01:00:00.000000000 +0100
4732 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_nat_core.c.orig     2003-11-13 11:01:27.000000000 +0100
4733 @@ -0,0 +1,1030 @@
4734 +/* NAT for netfilter; shared with compatibility layer. */
4735 +
4736 +/* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
4737 +   Public Licence. */
4738 +#include <linux/module.h>
4739 +#include <linux/types.h>
4740 +#include <linux/timer.h>
4741 +#include <linux/skbuff.h>
4742 +#include <linux/netfilter_ipv4.h>
4743 +#include <linux/vmalloc.h>
4744 +#include <net/checksum.h>
4745 +#include <net/icmp.h>
4746 +#include <net/ip.h>
4747 +#include <net/tcp.h>  /* For tcp_prot in getorigdst */
4748 +#include <linux/icmp.h>
4749 +#include <linux/udp.h>
4750 +
4751 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
4752 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
4753 +
4754 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4755 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4756 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4757 +#include <linux/netfilter_ipv4/ip_nat.h>
4758 +#include <linux/netfilter_ipv4/ip_nat_protocol.h>
4759 +#include <linux/netfilter_ipv4/ip_nat_core.h>
4760 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
4761 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4762 +#include <linux/netfilter_ipv4/listhelp.h>
4763 +
4764 +#if 0
4765 +#define DEBUGP printk
4766 +#else
4767 +#define DEBUGP(format, args...)
4768 +#endif
4769 +
4770 +DECLARE_RWLOCK(ip_nat_lock);
4771 +DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
4772 +
4773 +/* Calculated at init based on memory size */
4774 +static unsigned int ip_nat_htable_size;
4775 +
4776 +static struct list_head *bysource;
4777 +static struct list_head *byipsproto;
4778 +LIST_HEAD(protos);
4779 +LIST_HEAD(helpers);
4780 +
4781 +extern struct ip_nat_protocol unknown_nat_protocol;
4782 +
4783 +/* We keep extra hashes for each conntrack, for fast searching. */
4784 +static inline size_t
4785 +hash_by_ipsproto(u_int32_t src, u_int32_t dst, u_int16_t proto)
4786 +{
4787 +       /* Modified src and dst, to ensure we don't create two
4788 +           identical streams. */
4789 +       return (src + dst + proto) % ip_nat_htable_size;
4790 +}
4791 +
4792 +static inline size_t
4793 +hash_by_src(const struct ip_conntrack_manip *manip, u_int16_t proto)
4794 +{
4795 +       /* Original src, to ensure we map it consistently if poss. */
4796 +       return (manip->ip + manip->u.all + proto) % ip_nat_htable_size;
4797 +}
4798 +
4799 +/* Noone using conntrack by the time this called. */
4800 +static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn)
4801 +{
4802 +       struct ip_nat_info *info = &conn->nat.info;
4803 +       unsigned int hs, hp;
4804 +
4805 +       if (!info->initialized)
4806 +               return;
4807 +
4808 +       IP_NF_ASSERT(info->bysource.conntrack);
4809 +       IP_NF_ASSERT(info->byipsproto.conntrack);
4810 +
4811 +       hs = hash_by_src(&conn->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src,
4812 +                        conn->tuplehash[IP_CT_DIR_ORIGINAL]
4813 +                        .tuple.dst.protonum);
4814 +
4815 +       hp = hash_by_ipsproto(conn->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip,
4816 +                             conn->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip,
4817 +                             conn->tuplehash[IP_CT_DIR_REPLY]
4818 +                             .tuple.dst.protonum);
4819 +
4820 +       WRITE_LOCK(&ip_nat_lock);
4821 +       LIST_DELETE(&bysource[hs], &info->bysource);
4822 +       LIST_DELETE(&byipsproto[hp], &info->byipsproto);
4823 +       WRITE_UNLOCK(&ip_nat_lock);
4824 +}
4825 +
4826 +/* We do checksum mangling, so if they were wrong before they're still
4827 + * wrong.  Also works for incomplete packets (eg. ICMP dest
4828 + * unreachables.) */
4829 +u_int16_t
4830 +ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
4831 +{
4832 +       u_int32_t diffs[] = { oldvalinv, newval };
4833 +       return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
4834 +                                     oldcheck^0xFFFF));
4835 +}
4836 +
4837 +static inline int cmp_proto(const struct ip_nat_protocol *i, int proto)
4838 +{
4839 +       return i->protonum == proto;
4840 +}
4841 +
4842 +struct ip_nat_protocol *
4843 +find_nat_proto(u_int16_t protonum)
4844 +{
4845 +       struct ip_nat_protocol *i;
4846 +
4847 +       MUST_BE_READ_LOCKED(&ip_nat_lock);
4848 +       i = LIST_FIND(&protos, cmp_proto, struct ip_nat_protocol *, protonum);
4849 +       if (!i)
4850 +               i = &unknown_nat_protocol;
4851 +       return i;
4852 +}
4853 +
4854 +/* Is this tuple already taken? (not by us) */
4855 +int
4856 +ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
4857 +                 const struct ip_conntrack *ignored_conntrack)
4858 +{
4859 +       /* Conntrack tracking doesn't keep track of outgoing tuples; only
4860 +          incoming ones.  NAT means they don't have a fixed mapping,
4861 +          so we invert the tuple and look for the incoming reply.
4862 +
4863 +          We could keep a separate hash if this proves too slow. */
4864 +       struct ip_conntrack_tuple reply;
4865 +
4866 +       invert_tuplepr(&reply, tuple);
4867 +       return ip_conntrack_tuple_taken(&reply, ignored_conntrack);
4868 +}
4869 +
4870 +/* Does tuple + the source manip come within the range mr */
4871 +static int
4872 +in_range(const struct ip_conntrack_tuple *tuple,
4873 +        const struct ip_conntrack_manip *manip,
4874 +        const struct ip_nat_multi_range *mr)
4875 +{
4876 +       struct ip_nat_protocol *proto = find_nat_proto(tuple->dst.protonum);
4877 +       unsigned int i;
4878 +       struct ip_conntrack_tuple newtuple = { *manip, tuple->dst };
4879 +
4880 +       for (i = 0; i < mr->rangesize; i++) {
4881 +               /* If we are allowed to map IPs, then we must be in the
4882 +                  range specified, otherwise we must be unchanged. */
4883 +               if (mr->range[i].flags & IP_NAT_RANGE_MAP_IPS) {
4884 +                       if (ntohl(newtuple.src.ip) < ntohl(mr->range[i].min_ip)
4885 +                           || (ntohl(newtuple.src.ip)
4886 +                               > ntohl(mr->range[i].max_ip)))
4887 +                               continue;
4888 +               } else {
4889 +                       if (newtuple.src.ip != tuple->src.ip)
4890 +                               continue;
4891 +               }
4892 +
4893 +               if (!(mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
4894 +                   || proto->in_range(&newtuple, IP_NAT_MANIP_SRC,
4895 +                                      &mr->range[i].min, &mr->range[i].max))
4896 +                       return 1;
4897 +       }
4898 +       return 0;
4899 +}
4900 +
4901 +static inline int
4902 +src_cmp(const struct ip_nat_hash *i,
4903 +       const struct ip_conntrack_tuple *tuple,
4904 +       const struct ip_nat_multi_range *mr)
4905 +{
4906 +       return (i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum
4907 +               == tuple->dst.protonum
4908 +               && i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip
4909 +               == tuple->src.ip
4910 +               && i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all
4911 +               == tuple->src.u.all
4912 +               && in_range(tuple,
4913 +                           &i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
4914 +                           .tuple.src,
4915 +                           mr));
4916 +}
4917 +
4918 +/* Only called for SRC manip */
4919 +static struct ip_conntrack_manip *
4920 +find_appropriate_src(const struct ip_conntrack_tuple *tuple,
4921 +                    const struct ip_nat_multi_range *mr)
4922 +{
4923 +       unsigned int h = hash_by_src(&tuple->src, tuple->dst.protonum);
4924 +       struct ip_nat_hash *i;
4925 +
4926 +       MUST_BE_READ_LOCKED(&ip_nat_lock);
4927 +       i = LIST_FIND(&bysource[h], src_cmp, struct ip_nat_hash *, tuple, mr);
4928 +       if (i)
4929 +               return &i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src;
4930 +       else
4931 +               return NULL;
4932 +}
4933 +
4934 +#ifdef CONFIG_IP_NF_NAT_LOCAL
4935 +/* If it's really a local destination manip, it may need to do a
4936 +   source manip too. */
4937 +static int
4938 +do_extra_mangle(u_int32_t var_ip, u_int32_t *other_ipp)
4939 +{
4940 +       struct flowi fl = { .nl_u = { .ip4_u = { .daddr = var_ip } } };
4941 +       struct rtable *rt;
4942 +
4943 +       /* FIXME: IPTOS_TOS(iph->tos) --RR */
4944 +       if (ip_route_output_key(&rt, &fl) != 0) {
4945 +               DEBUGP("do_extra_mangle: Can't get route to %u.%u.%u.%u\n",
4946 +                      NIPQUAD(var_ip));
4947 +               return 0;
4948 +       }
4949 +
4950 +       *other_ipp = rt->rt_src;
4951 +       ip_rt_put(rt);
4952 +       return 1;
4953 +}
4954 +#endif
4955 +
4956 +/* Simple way to iterate through all. */
4957 +static inline int fake_cmp(const struct ip_nat_hash *i,
4958 +                          u_int32_t src, u_int32_t dst, u_int16_t protonum,
4959 +                          unsigned int *score,
4960 +                          const struct ip_conntrack *conntrack)
4961 +{
4962 +       /* Compare backwards: we're dealing with OUTGOING tuples, and
4963 +           inside the conntrack is the REPLY tuple.  Don't count this
4964 +           conntrack. */
4965 +       if (i->conntrack != conntrack
4966 +           && i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == dst
4967 +           && i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == src
4968 +           && (i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum
4969 +               == protonum))
4970 +               (*score)++;
4971 +       return 0;
4972 +}
4973 +
4974 +static inline unsigned int
4975 +count_maps(u_int32_t src, u_int32_t dst, u_int16_t protonum,
4976 +          const struct ip_conntrack *conntrack)
4977 +{
4978 +       unsigned int score = 0;
4979 +       unsigned int h;
4980 +
4981 +       MUST_BE_READ_LOCKED(&ip_nat_lock);
4982 +       h = hash_by_ipsproto(src, dst, protonum);
4983 +       LIST_FIND(&byipsproto[h], fake_cmp, struct ip_nat_hash *,
4984 +                 src, dst, protonum, &score, conntrack);
4985 +
4986 +       return score;
4987 +}
4988 +
4989 +/* For [FUTURE] fragmentation handling, we want the least-used
4990 +   src-ip/dst-ip/proto triple.  Fairness doesn't come into it.  Thus
4991 +   if the range specifies 1.2.3.4 ports 10000-10005 and 1.2.3.5 ports
4992 +   1-65535, we don't do pro-rata allocation based on ports; we choose
4993 +   the ip with the lowest src-ip/dst-ip/proto usage.
4994 +
4995 +   If an allocation then fails (eg. all 6 ports used in the 1.2.3.4
4996 +   range), we eliminate that and try again.  This is not the most
4997 +   efficient approach, but if you're worried about that, don't hand us
4998 +   ranges you don't really have.  */
4999 +static struct ip_nat_range *
5000 +find_best_ips_proto(struct ip_conntrack_tuple *tuple,
5001 +                   const struct ip_nat_multi_range *mr,
5002 +                   const struct ip_conntrack *conntrack,
5003 +                   unsigned int hooknum)
5004 +{
5005 +       unsigned int i;
5006 +       struct {
5007 +               const struct ip_nat_range *range;
5008 +               unsigned int score;
5009 +               struct ip_conntrack_tuple tuple;
5010 +       } best = { NULL,  0xFFFFFFFF };
5011 +       u_int32_t *var_ipp, *other_ipp, saved_ip, orig_dstip;
5012 +       static unsigned int randomness;
5013 +
5014 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
5015 +               var_ipp = &tuple->src.ip;
5016 +               saved_ip = tuple->dst.ip;
5017 +               other_ipp = &tuple->dst.ip;
5018 +       } else {
5019 +               var_ipp = &tuple->dst.ip;
5020 +               saved_ip = tuple->src.ip;
5021 +               other_ipp = &tuple->src.ip;
5022 +       }
5023 +       /* Don't do do_extra_mangle unless necessary (overrides
5024 +           explicit socket bindings, for example) */
5025 +       orig_dstip = tuple->dst.ip;
5026 +
5027 +       IP_NF_ASSERT(mr->rangesize >= 1);
5028 +       for (i = 0; i < mr->rangesize; i++) {
5029 +               /* Host order */
5030 +               u_int32_t minip, maxip, j;
5031 +
5032 +               /* Don't do ranges which are already eliminated. */
5033 +               if (mr->range[i].flags & IP_NAT_RANGE_FULL) {
5034 +                       continue;
5035 +               }
5036 +
5037 +               if (mr->range[i].flags & IP_NAT_RANGE_MAP_IPS) {
5038 +                       minip = ntohl(mr->range[i].min_ip);
5039 +                       maxip = ntohl(mr->range[i].max_ip);
5040 +               } else
5041 +                       minip = maxip = ntohl(*var_ipp);
5042 +
5043 +               randomness++;
5044 +               for (j = 0; j < maxip - minip + 1; j++) {
5045 +                       unsigned int score;
5046 +
5047 +                       *var_ipp = htonl(minip + (randomness + j) 
5048 +                                        % (maxip - minip + 1));
5049 +
5050 +                       /* Reset the other ip in case it was mangled by
5051 +                        * do_extra_mangle last time. */
5052 +                       *other_ipp = saved_ip;
5053 +
5054 +#ifdef CONFIG_IP_NF_NAT_LOCAL
5055 +                       if (hooknum == NF_IP_LOCAL_OUT
5056 +                           && *var_ipp != orig_dstip
5057 +                           && !do_extra_mangle(*var_ipp, other_ipp)) {
5058 +                               DEBUGP("Range %u %u.%u.%u.%u rt failed!\n",
5059 +                                      i, NIPQUAD(*var_ipp));
5060 +                               /* Can't route?  This whole range part is
5061 +                                * probably screwed, but keep trying
5062 +                                * anyway. */
5063 +                               continue;
5064 +                       }
5065 +#endif
5066 +
5067 +                       /* Count how many others map onto this. */
5068 +                       score = count_maps(tuple->src.ip, tuple->dst.ip,
5069 +                                          tuple->dst.protonum, conntrack);
5070 +                       if (score < best.score) {
5071 +                               /* Optimization: doesn't get any better than
5072 +                                  this. */
5073 +                               if (score == 0)
5074 +                                       return (struct ip_nat_range *)
5075 +                                               &mr->range[i];
5076 +
5077 +                               best.score = score;
5078 +                               best.tuple = *tuple;
5079 +                               best.range = &mr->range[i];
5080 +                       }
5081 +               }
5082 +       }
5083 +       *tuple = best.tuple;
5084 +
5085 +       /* Discard const. */
5086 +       return (struct ip_nat_range *)best.range;
5087 +}
5088 +
5089 +/* Fast version doesn't iterate through hash chains, but only handles
5090 +   common case of single IP address (null NAT, masquerade) */
5091 +static struct ip_nat_range *
5092 +find_best_ips_proto_fast(struct ip_conntrack_tuple *tuple,
5093 +                        const struct ip_nat_multi_range *mr,
5094 +                        const struct ip_conntrack *conntrack,
5095 +                        unsigned int hooknum)
5096 +{
5097 +       if (mr->rangesize != 1
5098 +           || (mr->range[0].flags & IP_NAT_RANGE_FULL)
5099 +           || ((mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
5100 +               && mr->range[0].min_ip != mr->range[0].max_ip))
5101 +               return find_best_ips_proto(tuple, mr, conntrack, hooknum);
5102 +
5103 +       if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
5104 +               if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
5105 +                       tuple->src.ip = mr->range[0].min_ip;
5106 +               else {
5107 +                       /* Only do extra mangle when required (breaks
5108 +                           socket binding) */
5109 +#ifdef CONFIG_IP_NF_NAT_LOCAL
5110 +                       if (tuple->dst.ip != mr->range[0].min_ip
5111 +                           && hooknum == NF_IP_LOCAL_OUT
5112 +                           && !do_extra_mangle(mr->range[0].min_ip,
5113 +                                               &tuple->src.ip))
5114 +                               return NULL;
5115 +#endif
5116 +                       tuple->dst.ip = mr->range[0].min_ip;
5117 +               }
5118 +       }
5119 +
5120 +       /* Discard const. */
5121 +       return (struct ip_nat_range *)&mr->range[0];
5122 +}
5123 +
5124 +static int
5125 +get_unique_tuple(struct ip_conntrack_tuple *tuple,
5126 +                const struct ip_conntrack_tuple *orig_tuple,
5127 +                const struct ip_nat_multi_range *mrr,
5128 +                struct ip_conntrack *conntrack,
5129 +                unsigned int hooknum)
5130 +{
5131 +       struct ip_nat_protocol *proto
5132 +               = find_nat_proto(orig_tuple->dst.protonum);
5133 +       struct ip_nat_range *rptr;
5134 +       unsigned int i;
5135 +       int ret;
5136 +
5137 +       /* We temporarily use flags for marking full parts, but we
5138 +          always clean up afterwards */
5139 +       struct ip_nat_multi_range *mr = (void *)mrr;
5140 +
5141 +       /* 1) If this srcip/proto/src-proto-part is currently mapped,
5142 +          and that same mapping gives a unique tuple within the given
5143 +          range, use that.
5144 +
5145 +          This is only required for source (ie. NAT/masq) mappings.
5146 +          So far, we don't do local source mappings, so multiple
5147 +          manips not an issue.  */
5148 +       if (hooknum == NF_IP_POST_ROUTING) {
5149 +               struct ip_conntrack_manip *manip;
5150 +
5151 +               manip = find_appropriate_src(orig_tuple, mr);
5152 +               if (manip) {
5153 +                       /* Apply same source manipulation. */
5154 +                       *tuple = ((struct ip_conntrack_tuple)
5155 +                                 { *manip, orig_tuple->dst });
5156 +                       DEBUGP("get_unique_tuple: Found current src map\n");
5157 +                       if (!ip_nat_used_tuple(tuple, conntrack))
5158 +                               return 1;
5159 +               }
5160 +       }
5161 +
5162 +       /* 2) Select the least-used IP/proto combination in the given
5163 +          range.
5164 +       */
5165 +       *tuple = *orig_tuple;
5166 +       while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum))
5167 +              != NULL) {
5168 +               DEBUGP("Found best for "); DUMP_TUPLE(tuple);
5169 +               /* 3) The per-protocol part of the manip is made to
5170 +                  map into the range to make a unique tuple. */
5171 +
5172 +               /* Only bother mapping if it's not already in range
5173 +                  and unique */
5174 +               if ((!(rptr->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
5175 +                    || proto->in_range(tuple, HOOK2MANIP(hooknum),
5176 +                                       &rptr->min, &rptr->max))
5177 +                   && !ip_nat_used_tuple(tuple, conntrack)) {
5178 +                       ret = 1;
5179 +                       goto clear_fulls;
5180 +               } else {
5181 +                       if (proto->unique_tuple(tuple, rptr,
5182 +                                               HOOK2MANIP(hooknum),
5183 +                                               conntrack)) {
5184 +                               /* Must be unique. */
5185 +                               IP_NF_ASSERT(!ip_nat_used_tuple(tuple,
5186 +                                                               conntrack));
5187 +                               ret = 1;
5188 +                               goto clear_fulls;
5189 +                       } else if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
5190 +                               /* Try implicit source NAT; protocol
5191 +                                   may be able to play with ports to
5192 +                                   make it unique. */
5193 +                               struct ip_nat_range r
5194 +                                       = { IP_NAT_RANGE_MAP_IPS, 
5195 +                                           tuple->src.ip, tuple->src.ip,
5196 +                                           { 0 }, { 0 } };
5197 +                               DEBUGP("Trying implicit mapping\n");
5198 +                               if (proto->unique_tuple(tuple, &r,
5199 +                                                       IP_NAT_MANIP_SRC,
5200 +                                                       conntrack)) {
5201 +                                       /* Must be unique. */
5202 +                                       IP_NF_ASSERT(!ip_nat_used_tuple
5203 +                                                    (tuple, conntrack));
5204 +                                       ret = 1;
5205 +                                       goto clear_fulls;
5206 +                               }
5207 +                       }
5208 +                       DEBUGP("Protocol can't get unique tuple %u.\n",
5209 +                              hooknum);
5210 +               }
5211 +
5212 +               /* Eliminate that from range, and try again. */
5213 +               rptr->flags |= IP_NAT_RANGE_FULL;
5214 +               *tuple = *orig_tuple;
5215 +       }
5216 +
5217 +       ret = 0;
5218 +
5219 + clear_fulls:
5220 +       /* Clear full flags. */
5221 +       IP_NF_ASSERT(mr->rangesize >= 1);
5222 +       for (i = 0; i < mr->rangesize; i++)
5223 +               mr->range[i].flags &= ~IP_NAT_RANGE_FULL;
5224 +
5225 +       return ret;
5226 +}
5227 +
5228 +static inline int
5229 +helper_cmp(const struct ip_nat_helper *helper,
5230 +          const struct ip_conntrack_tuple *tuple)
5231 +{
5232 +       return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
5233 +}
5234 +
5235 +/* Where to manip the reply packets (will be reverse manip). */
5236 +static unsigned int opposite_hook[NF_IP_NUMHOOKS]
5237 += { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
5238 +    [NF_IP_POST_ROUTING] = NF_IP_PRE_ROUTING,
5239 +#ifdef CONFIG_IP_NF_NAT_LOCAL
5240 +    [NF_IP_LOCAL_OUT] = NF_IP_LOCAL_IN,
5241 +    [NF_IP_LOCAL_IN] = NF_IP_LOCAL_OUT,
5242 +#endif
5243 +};
5244 +
5245 +unsigned int
5246 +ip_nat_setup_info(struct ip_conntrack *conntrack,
5247 +                 const struct ip_nat_multi_range *mr,
5248 +                 unsigned int hooknum)
5249 +{
5250 +       struct ip_conntrack_tuple new_tuple, inv_tuple, reply;
5251 +       struct ip_conntrack_tuple orig_tp;
5252 +       struct ip_nat_info *info = &conntrack->nat.info;
5253 +       int in_hashes = info->initialized;
5254 +
5255 +       MUST_BE_WRITE_LOCKED(&ip_nat_lock);
5256 +       IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
5257 +                    || hooknum == NF_IP_POST_ROUTING
5258 +                    || hooknum == NF_IP_LOCAL_OUT);
5259 +       IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS);
5260 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
5261 +
5262 +       /* What we've got will look like inverse of reply. Normally
5263 +          this is what is in the conntrack, except for prior
5264 +          manipulations (future optimization: if num_manips == 0,
5265 +          orig_tp =
5266 +          conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple) */
5267 +       invert_tuplepr(&orig_tp,
5268 +                      &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple);
5269 +
5270 +#if 0
5271 +       {
5272 +       unsigned int i;
5273 +
5274 +       DEBUGP("Hook %u (%s), ", hooknum,
5275 +              HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST");
5276 +       DUMP_TUPLE(&orig_tp);
5277 +       DEBUGP("Range %p: ", mr);
5278 +       for (i = 0; i < mr->rangesize; i++) {
5279 +               DEBUGP("%u:%s%s%s %u.%u.%u.%u - %u.%u.%u.%u %u - %u\n",
5280 +                      i,
5281 +                      (mr->range[i].flags & IP_NAT_RANGE_MAP_IPS)
5282 +                      ? " MAP_IPS" : "",
5283 +                      (mr->range[i].flags
5284 +                       & IP_NAT_RANGE_PROTO_SPECIFIED)
5285 +                      ? " PROTO_SPECIFIED" : "",
5286 +                      (mr->range[i].flags & IP_NAT_RANGE_FULL)
5287 +                      ? " FULL" : "",
5288 +                      NIPQUAD(mr->range[i].min_ip),
5289 +                      NIPQUAD(mr->range[i].max_ip),
5290 +                      mr->range[i].min.all,
5291 +                      mr->range[i].max.all);
5292 +       }
5293 +       }
5294 +#endif
5295 +
5296 +       do {
5297 +               if (!get_unique_tuple(&new_tuple, &orig_tp, mr, conntrack,
5298 +                                     hooknum)) {
5299 +                       DEBUGP("ip_nat_setup_info: Can't get unique for %p.\n",
5300 +                              conntrack);
5301 +                       return NF_DROP;
5302 +               }
5303 +
5304 +#if 0
5305 +               DEBUGP("Hook %u (%s) %p\n", hooknum,
5306 +                      HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST",
5307 +                      conntrack);
5308 +               DEBUGP("Original: ");
5309 +               DUMP_TUPLE(&orig_tp);
5310 +               DEBUGP("New: ");
5311 +               DUMP_TUPLE(&new_tuple);
5312 +#endif
5313 +
5314 +               /* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):
5315 +                  the original (A/B/C/D') and the mangled one (E/F/G/H').
5316 +
5317 +                  We're only allowed to work with the SRC per-proto
5318 +                  part, so we create inverses of both to start, then
5319 +                  derive the other fields we need.  */
5320 +
5321 +               /* Reply connection: simply invert the new tuple
5322 +                   (G/H/E/F') */
5323 +               invert_tuplepr(&reply, &new_tuple);
5324 +
5325 +               /* Alter conntrack table so it recognizes replies.
5326 +                   If fail this race (reply tuple now used), repeat. */
5327 +       } while (!ip_conntrack_alter_reply(conntrack, &reply));
5328 +
5329 +       /* FIXME: We can simply used existing conntrack reply tuple
5330 +           here --RR */
5331 +       /* Create inverse of original: C/D/A/B' */
5332 +       invert_tuplepr(&inv_tuple, &orig_tp);
5333 +
5334 +       /* Has source changed?. */
5335 +       if (!ip_ct_tuple_src_equal(&new_tuple, &orig_tp)) {
5336 +               /* In this direction, a source manip. */
5337 +               info->manips[info->num_manips++] =
5338 +                       ((struct ip_nat_info_manip)
5339 +                        { IP_CT_DIR_ORIGINAL, hooknum,
5340 +                          IP_NAT_MANIP_SRC, new_tuple.src });
5341 +
5342 +               IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS);
5343 +
5344 +               /* In the reverse direction, a destination manip. */
5345 +               info->manips[info->num_manips++] =
5346 +                       ((struct ip_nat_info_manip)
5347 +                        { IP_CT_DIR_REPLY, opposite_hook[hooknum],
5348 +                          IP_NAT_MANIP_DST, orig_tp.src });
5349 +               IP_NF_ASSERT(info->num_manips <= IP_NAT_MAX_MANIPS);
5350 +       }
5351 +
5352 +       /* Has destination changed? */
5353 +       if (!ip_ct_tuple_dst_equal(&new_tuple, &orig_tp)) {
5354 +               /* In this direction, a destination manip */
5355 +               info->manips[info->num_manips++] =
5356 +                       ((struct ip_nat_info_manip)
5357 +                        { IP_CT_DIR_ORIGINAL, hooknum,
5358 +                          IP_NAT_MANIP_DST, reply.src });
5359 +
5360 +               IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS);
5361 +
5362 +               /* In the reverse direction, a source manip. */
5363 +               info->manips[info->num_manips++] =
5364 +                       ((struct ip_nat_info_manip)
5365 +                        { IP_CT_DIR_REPLY, opposite_hook[hooknum],
5366 +                          IP_NAT_MANIP_SRC, inv_tuple.src });
5367 +               IP_NF_ASSERT(info->num_manips <= IP_NAT_MAX_MANIPS);
5368 +       }
5369 +
5370 +       /* If there's a helper, assign it; based on new tuple. */
5371 +       if (!conntrack->master)
5372 +               info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
5373 +                                        &reply);
5374 +
5375 +       /* It's done. */
5376 +       info->initialized |= (1 << HOOK2MANIP(hooknum));
5377 +
5378 +       if (in_hashes) {
5379 +               IP_NF_ASSERT(info->bysource.conntrack);
5380 +               replace_in_hashes(conntrack, info);
5381 +       } else {
5382 +               place_in_hashes(conntrack, info);
5383 +       }
5384 +
5385 +       return NF_ACCEPT;
5386 +}
5387 +
5388 +void replace_in_hashes(struct ip_conntrack *conntrack,
5389 +                      struct ip_nat_info *info)
5390 +{
5391 +       /* Source has changed, so replace in hashes. */
5392 +       unsigned int srchash
5393 +               = hash_by_src(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
5394 +                             .tuple.src,
5395 +                             conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
5396 +                             .tuple.dst.protonum);
5397 +       /* We place packet as seen OUTGOUNG in byips_proto hash
5398 +           (ie. reverse dst and src of reply packet. */
5399 +       unsigned int ipsprotohash
5400 +               = hash_by_ipsproto(conntrack->tuplehash[IP_CT_DIR_REPLY]
5401 +                                  .tuple.dst.ip,
5402 +                                  conntrack->tuplehash[IP_CT_DIR_REPLY]
5403 +                                  .tuple.src.ip,
5404 +                                  conntrack->tuplehash[IP_CT_DIR_REPLY]
5405 +                                  .tuple.dst.protonum);
5406 +
5407 +       IP_NF_ASSERT(info->bysource.conntrack == conntrack);
5408 +       MUST_BE_WRITE_LOCKED(&ip_nat_lock);
5409 +
5410 +       list_del(&info->bysource.list);
5411 +       list_del(&info->byipsproto.list);
5412 +
5413 +       list_prepend(&bysource[srchash], &info->bysource);
5414 +       list_prepend(&byipsproto[ipsprotohash], &info->byipsproto);
5415 +}
5416 +
5417 +void place_in_hashes(struct ip_conntrack *conntrack,
5418 +                    struct ip_nat_info *info)
5419 +{
5420 +       unsigned int srchash
5421 +               = hash_by_src(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
5422 +                             .tuple.src,
5423 +                             conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
5424 +                             .tuple.dst.protonum);
5425 +       /* We place packet as seen OUTGOUNG in byips_proto hash
5426 +           (ie. reverse dst and src of reply packet. */
5427 +       unsigned int ipsprotohash
5428 +               = hash_by_ipsproto(conntrack->tuplehash[IP_CT_DIR_REPLY]
5429 +                                  .tuple.dst.ip,
5430 +                                  conntrack->tuplehash[IP_CT_DIR_REPLY]
5431 +                                  .tuple.src.ip,
5432 +                                  conntrack->tuplehash[IP_CT_DIR_REPLY]
5433 +                                  .tuple.dst.protonum);
5434 +
5435 +       IP_NF_ASSERT(!info->bysource.conntrack);
5436 +
5437 +       MUST_BE_WRITE_LOCKED(&ip_nat_lock);
5438 +       info->byipsproto.conntrack = conntrack;
5439 +       info->bysource.conntrack = conntrack;
5440 +
5441 +       list_prepend(&bysource[srchash], &info->bysource);
5442 +       list_prepend(&byipsproto[ipsprotohash], &info->byipsproto);
5443 +}
5444 +
5445 +/* Returns true if succeeded. */
5446 +static int
5447 +manip_pkt(u_int16_t proto,
5448 +         struct sk_buff **pskb,
5449 +         unsigned int iphdroff,
5450 +         const struct ip_conntrack_manip *manip,
5451 +         enum ip_nat_manip_type maniptype)
5452 +{
5453 +       struct iphdr *iph;
5454 +
5455 +       (*pskb)->nfcache |= NFC_ALTERED;
5456 +       if (!skb_ip_make_writable(pskb, iphdroff+sizeof(iph)))
5457 +               return 0;
5458 +
5459 +       iph = (void *)(*pskb)->data + iphdroff;
5460 +
5461 +       /* Manipulate protcol part. */
5462 +       if (!find_nat_proto(proto)->manip_pkt(pskb,
5463 +                                             iphdroff + iph->ihl*4,
5464 +                                             manip, maniptype))
5465 +               return 0;
5466 +
5467 +       iph = (void *)(*pskb)->data + iphdroff;
5468 +
5469 +       if (maniptype == IP_NAT_MANIP_SRC) {
5470 +               iph->check = ip_nat_cheat_check(~iph->saddr, manip->ip,
5471 +                                               iph->check);
5472 +               iph->saddr = manip->ip;
5473 +       } else {
5474 +               iph->check = ip_nat_cheat_check(~iph->daddr, manip->ip,
5475 +                                               iph->check);
5476 +               iph->daddr = manip->ip;
5477 +       }
5478 +       return 1;
5479 +}
5480 +
5481 +static inline int exp_for_packet(struct ip_conntrack_expect *exp,
5482 +                                struct sk_buff *skb)
5483 +{
5484 +       struct ip_conntrack_protocol *proto;
5485 +       int ret = 1;
5486 +
5487 +       MUST_BE_READ_LOCKED(&ip_conntrack_lock);
5488 +       proto = __ip_ct_find_proto(skb->nh.iph->protocol);
5489 +       if (proto->exp_matches_pkt)
5490 +               ret = proto->exp_matches_pkt(exp, skb);
5491 +
5492 +       return ret;
5493 +}
5494 +
5495 +/* Do packet manipulations according to binding. */
5496 +unsigned int
5497 +do_bindings(struct ip_conntrack *ct,
5498 +           enum ip_conntrack_info ctinfo,
5499 +           struct ip_nat_info *info,
5500 +           unsigned int hooknum,
5501 +           struct sk_buff **pskb)
5502 +{
5503 +       unsigned int i;
5504 +       struct ip_nat_helper *helper;
5505 +       enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
5506 +       int proto = (*pskb)->nh.iph->protocol;
5507 +
5508 +       /* Need nat lock to protect against modification, but neither
5509 +          conntrack (referenced) and helper (deleted with
5510 +          synchronize_bh()) can vanish. */
5511 +       READ_LOCK(&ip_nat_lock);
5512 +       for (i = 0; i < info->num_manips; i++) {
5513 +               if (info->manips[i].direction == dir
5514 +                   && info->manips[i].hooknum == hooknum) {
5515 +                       DEBUGP("Mangling %p: %s to %u.%u.%u.%u %u\n",
5516 +                              *pskb,
5517 +                              info->manips[i].maniptype == IP_NAT_MANIP_SRC
5518 +                              ? "SRC" : "DST",
5519 +                              NIPQUAD(info->manips[i].manip.ip),
5520 +                              htons(info->manips[i].manip.u.all));
5521 +                       if (!manip_pkt(proto, pskb, 0,
5522 +                                      &info->manips[i].manip,
5523 +                                      info->manips[i].maniptype)) {
5524 +                               READ_UNLOCK(&ip_nat_lock);
5525 +                               return NF_DROP;
5526 +                       }
5527 +               }
5528 +       }
5529 +       helper = info->helper;
5530 +       READ_UNLOCK(&ip_nat_lock);
5531 +
5532 +       if (helper) {
5533 +               struct ip_conntrack_expect *exp = NULL;
5534 +               struct list_head *cur_item;
5535 +               int ret = NF_ACCEPT;
5536 +               int helper_called = 0;
5537 +
5538 +               DEBUGP("do_bindings: helper existing for (%p)\n", ct);
5539 +
5540 +               /* Always defragged for helpers */
5541 +               IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
5542 +                              & htons(IP_MF|IP_OFFSET)));
5543 +
5544 +               /* Have to grab read lock before sibling_list traversal */
5545 +               READ_LOCK(&ip_conntrack_lock);
5546 +               list_for_each_prev(cur_item, &ct->sibling_list) { 
5547 +                       exp = list_entry(cur_item, struct ip_conntrack_expect, 
5548 +                                        expected_list);
5549 +                                        
5550 +                       /* if this expectation is already established, skip */
5551 +                       if (exp->sibling)
5552 +                               continue;
5553 +
5554 +                       if (exp_for_packet(exp, *pskb)) {
5555 +                               /* FIXME: May be true multiple times in the
5556 +                                * case of UDP!! */
5557 +                               DEBUGP("calling nat helper (exp=%p) for packet\n", exp);
5558 +                               ret = helper->help(ct, exp, info, ctinfo, 
5559 +                                                  hooknum, pskb);
5560 +                               if (ret != NF_ACCEPT) {
5561 +                                       READ_UNLOCK(&ip_conntrack_lock);
5562 +                                       return ret;
5563 +                               }
5564 +                               helper_called = 1;
5565 +                       }
5566 +               }
5567 +               /* Helper might want to manip the packet even when there is no
5568 +                * matching expectation for this packet */
5569 +               if (!helper_called && helper->flags & IP_NAT_HELPER_F_ALWAYS) {
5570 +                       DEBUGP("calling nat helper for packet without expectation\n");
5571 +                       ret = helper->help(ct, NULL, info, ctinfo, 
5572 +                                          hooknum, pskb);
5573 +                       if (ret != NF_ACCEPT) {
5574 +                               READ_UNLOCK(&ip_conntrack_lock);
5575 +                               return ret;
5576 +                       }
5577 +               }
5578 +               READ_UNLOCK(&ip_conntrack_lock);
5579 +               
5580 +               /* Adjust sequence number only once per packet 
5581 +                * (helper is called at all hooks) */
5582 +               if (proto == IPPROTO_TCP
5583 +                   && (hooknum == NF_IP_POST_ROUTING
5584 +                       || hooknum == NF_IP_LOCAL_IN)) {
5585 +                       DEBUGP("ip_nat_core: adjusting sequence number\n");
5586 +                       /* future: put this in a l4-proto specific function,
5587 +                        * and call this function here. */
5588 +                       if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
5589 +                               ret = NF_DROP;
5590 +               }
5591 +
5592 +               return ret;
5593 +
5594 +       } else 
5595 +               return NF_ACCEPT;
5596 +
5597 +       /* not reached */
5598 +}
5599 +
5600 +int
5601 +icmp_reply_translation(struct sk_buff **pskb,
5602 +                      struct ip_conntrack *conntrack,
5603 +                      unsigned int hooknum,
5604 +                      int dir)
5605 +{
5606 +       struct {
5607 +               struct icmphdr icmp;
5608 +               struct iphdr ip;
5609 +       } *inside;
5610 +       unsigned int i;
5611 +       struct ip_nat_info *info = &conntrack->nat.info;
5612 +       int hdrlen;
5613 +
5614 +       if (!skb_ip_make_writable(pskb,(*pskb)->nh.iph->ihl*4+sizeof(*inside)))
5615 +               return 0;
5616 +       inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
5617 +
5618 +       /* We're actually going to mangle it beyond trivial checksum
5619 +          adjustment, so make sure the current checksum is correct. */
5620 +       if ((*pskb)->ip_summed != CHECKSUM_UNNECESSARY) {
5621 +               hdrlen = (*pskb)->nh.iph->ihl * 4;
5622 +               if ((u16)csum_fold(skb_checksum(*pskb, hdrlen,
5623 +                                               (*pskb)->len - hdrlen, 0)))
5624 +                       return 0;
5625 +       }
5626 +
5627 +       /* Must be RELATED */
5628 +       IP_NF_ASSERT((*pskb)->nfct
5629 +                    - (struct ip_conntrack *)(*pskb)->nfct->master
5630 +                    == IP_CT_RELATED
5631 +                    || (*pskb)->nfct
5632 +                    - (struct ip_conntrack *)(*pskb)->nfct->master
5633 +                    == IP_CT_RELATED+IP_CT_IS_REPLY);
5634 +
5635 +       /* Redirects on non-null nats must be dropped, else they'll
5636 +           start talking to each other without our translation, and be
5637 +           confused... --RR */
5638 +       if (inside->icmp.type == ICMP_REDIRECT) {
5639 +               /* Don't care about races here. */
5640 +               if (info->initialized
5641 +                   != ((1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST))
5642 +                   || info->num_manips != 0)
5643 +                       return 0;
5644 +       }
5645 +
5646 +       DEBUGP("icmp_reply_translation: translating error %p hook %u dir %s\n",
5647 +              *pskb, hooknum, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
5648 +       /* Note: May not be from a NAT'd host, but probably safest to
5649 +          do translation always as if it came from the host itself
5650 +          (even though a "host unreachable" coming from the host
5651 +          itself is a bit weird).
5652 +
5653 +          More explanation: some people use NAT for anonymizing.
5654 +          Also, CERT recommends dropping all packets from private IP
5655 +          addresses (although ICMP errors from internal links with
5656 +          such addresses are not too uncommon, as Alan Cox points
5657 +          out) */
5658 +
5659 +       READ_LOCK(&ip_nat_lock);
5660 +       for (i = 0; i < info->num_manips; i++) {
5661 +               DEBUGP("icmp_reply: manip %u dir %s hook %u\n",
5662 +                      i, info->manips[i].direction == IP_CT_DIR_ORIGINAL ?
5663 +                      "ORIG" : "REPLY", info->manips[i].hooknum);
5664 +
5665 +               if (info->manips[i].direction != dir)
5666 +                       continue;
5667 +
5668 +               /* Mapping the inner packet is just like a normal
5669 +                  packet, except it was never src/dst reversed, so
5670 +                  where we would normally apply a dst manip, we apply
5671 +                  a src, and vice versa. */
5672 +               if (info->manips[i].hooknum == hooknum) {
5673 +                       DEBUGP("icmp_reply: inner %s -> %u.%u.%u.%u %u\n",
5674 +                              info->manips[i].maniptype == IP_NAT_MANIP_SRC
5675 +                              ? "DST" : "SRC",
5676 +                              NIPQUAD(info->manips[i].manip.ip),
5677 +                              ntohs(info->manips[i].manip.u.udp.port));
5678 +                       if (!manip_pkt(inside->ip.protocol, pskb,
5679 +                                      (*pskb)->nh.iph->ihl*4
5680 +                                      + sizeof(inside->icmp),
5681 +                                      &info->manips[i].manip,
5682 +                                      !info->manips[i].maniptype))
5683 +                               goto unlock_fail;
5684 +
5685 +                       /* Outer packet needs to have IP header NATed like
5686 +                          it's a reply. */
5687 +
5688 +                       /* Use mapping to map outer packet: 0 give no
5689 +                           per-proto mapping */
5690 +                       DEBUGP("icmp_reply: outer %s -> %u.%u.%u.%u\n",
5691 +                              info->manips[i].maniptype == IP_NAT_MANIP_SRC
5692 +                              ? "SRC" : "DST",
5693 +                              NIPQUAD(info->manips[i].manip.ip));
5694 +                       if (!manip_pkt(0, pskb, 0,
5695 +                                      &info->manips[i].manip,
5696 +                                      info->manips[i].maniptype))
5697 +                               goto unlock_fail;
5698 +               }
5699 +       }
5700 +       READ_UNLOCK(&ip_nat_lock);
5701 +
5702 +       hdrlen = (*pskb)->nh.iph->ihl * 4;
5703 +
5704 +       inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
5705 +
5706 +       inside->icmp.checksum = 0;
5707 +       inside->icmp.checksum = csum_fold(skb_checksum(*pskb, hdrlen,
5708 +                                                      (*pskb)->len - hdrlen,
5709 +                                                      0));
5710 +       return 1;
5711 +
5712 + unlock_fail:
5713 +       READ_UNLOCK(&ip_nat_lock);
5714 +       return 0;
5715 +}
5716 +
5717 +int __init ip_nat_init(void)
5718 +{
5719 +       size_t i;
5720 +
5721 +       /* Leave them the same for the moment. */
5722 +       ip_nat_htable_size = ip_conntrack_htable_size;
5723 +
5724 +       /* One vmalloc for both hash tables */
5725 +       bysource = vmalloc(sizeof(struct list_head) * ip_nat_htable_size*2);
5726 +       if (!bysource) {
5727 +               return -ENOMEM;
5728 +       }
5729 +       byipsproto = bysource + ip_nat_htable_size;
5730 +
5731 +       /* Sew in builtin protocols. */
5732 +       WRITE_LOCK(&ip_nat_lock);
5733 +       list_append(&protos, &ip_nat_protocol_tcp);
5734 +       list_append(&protos, &ip_nat_protocol_udp);
5735 +       list_append(&protos, &ip_nat_protocol_icmp);
5736 +       WRITE_UNLOCK(&ip_nat_lock);
5737 +
5738 +       for (i = 0; i < ip_nat_htable_size; i++) {
5739 +               INIT_LIST_HEAD(&bysource[i]);
5740 +               INIT_LIST_HEAD(&byipsproto[i]);
5741 +       }
5742 +
5743 +       /* FIXME: Man, this is a hack.  <SIGH> */
5744 +       IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
5745 +       ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
5746 +
5747 +       return 0;
5748 +}
5749 +
5750 +/* Clear NAT section of all conntracks, in case we're loaded again. */
5751 +static int clean_nat(const struct ip_conntrack *i, void *data)
5752 +{
5753 +       memset((void *)&i->nat, 0, sizeof(i->nat));
5754 +       return 0;
5755 +}
5756 +
5757 +/* Not __exit: called from ip_nat_standalone.c:init_or_cleanup() --RR */
5758 +void ip_nat_cleanup(void)
5759 +{
5760 +       ip_ct_selective_cleanup(&clean_nat, NULL);
5761 +       ip_conntrack_destroyed = NULL;
5762 +       vfree(bysource);
5763 +}
5764 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.0-test9/net/ipv4/netfilter/ip_nat_rule.c
5765 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_nat_rule.c      2003-10-25 20:43:27.000000000 +0200
5766 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_nat_rule.c  2003-11-13 11:01:39.000000000 +0100
5767 @@ -67,7 +67,7 @@
5768                 0,
5769                 sizeof(struct ipt_entry),
5770                 sizeof(struct ipt_standard),
5771 -               0, { 0, 0 }, { } },
5772 +               0, NULL, 0, { 0, 0 }, { } },
5773               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
5774                 -NF_ACCEPT - 1 } },
5775             /* POST_ROUTING */
5776 @@ -75,7 +75,7 @@
5777                 0,
5778                 sizeof(struct ipt_entry),
5779                 sizeof(struct ipt_standard),
5780 -               0, { 0, 0 }, { } },
5781 +               0, NULL, 0, { 0, 0 }, { } },
5782               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
5783                 -NF_ACCEPT - 1 } },
5784             /* LOCAL_OUT */
5785 @@ -83,7 +83,7 @@
5786                 0,
5787                 sizeof(struct ipt_entry),
5788                 sizeof(struct ipt_standard),
5789 -               0, { 0, 0 }, { } },
5790 +               0, NULL, 0, { 0, 0 }, { } },
5791               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
5792                 -NF_ACCEPT - 1 } }
5793      },
5794 @@ -92,7 +92,7 @@
5795         0,
5796         sizeof(struct ipt_entry),
5797         sizeof(struct ipt_error),
5798 -       0, { 0, 0 }, { } },
5799 +       0, NULL, 0, { 0, 0 }, { } },
5800        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
5801           { } },
5802         "ERROR"
5803 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_nat_tftp.c linux-2.6.0-test9/net/ipv4/netfilter/ip_nat_tftp.c
5804 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_nat_tftp.c      2003-10-25 20:43:18.000000000 +0200
5805 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_nat_tftp.c  2003-11-13 11:01:08.000000000 +0100
5806 @@ -164,8 +164,6 @@
5807                 ports[0] = TFTP_PORT;
5808  
5809         for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5810 -               memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
5811 -
5812                 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
5813                 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
5814                 tftp[i].mask.dst.protonum = 0xFFFF;
5815 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ip_tables.c linux-2.6.0-test9/net/ipv4/netfilter/ip_tables.c
5816 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ip_tables.c        2003-10-25 20:43:11.000000000 +0200
5817 +++ linux-2.6.0-test9/net/ipv4/netfilter/ip_tables.c    2003-11-13 11:01:39.000000000 +0100
5818 @@ -11,6 +11,7 @@
5819  #include <linux/config.h>
5820  #include <linux/cache.h>
5821  #include <linux/skbuff.h>
5822 +#include <linux/socket.h>
5823  #include <linux/kmod.h>
5824  #include <linux/vmalloc.h>
5825  #include <linux/netdevice.h>
5826 @@ -23,8 +24,17 @@
5827  #include <asm/semaphore.h>
5828  #include <linux/proc_fs.h>
5829  
5830 +#include <linux/netfilter.h>
5831  #include <linux/netfilter_ipv4/ip_tables.h>
5832  
5833 +static const char *hooknames[] = { 
5834 +       [NF_IP_PRE_ROUTING] "PREROUTING",
5835 +       [NF_IP_LOCAL_IN] "INPUT",
5836 +       [NF_IP_FORWARD] "FORWARD",
5837 +       [NF_IP_LOCAL_OUT] "OUTPUT",
5838 +       [NF_IP_POST_ROUTING] "POSTROUTING",
5839 +};
5840
5841  MODULE_LICENSE("GPL");
5842  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
5843  MODULE_DESCRIPTION("IPv4 packet filter");
5844 @@ -322,6 +332,12 @@
5845  
5846                         t = ipt_get_target(e);
5847                         IP_NF_ASSERT(t->u.kernel.target);
5848 +
5849 +                       /* The packet traced and the rule isn't an unconditional return/END. */
5850 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {       
5851 +                               nf_log_packet(AF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
5852 +                                                table->name, e->chainname, e->rulenum);
5853 +                       }
5854                         /* Standard target? */
5855                         if (!t->u.kernel.target->target) {
5856                                 int v;
5857 @@ -474,6 +490,29 @@
5858         return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
5859  }
5860  
5861 +static inline int
5862 +find_error_target(struct ipt_entry *s, 
5863 +                 struct ipt_entry *e,
5864 +                 char **chainname)
5865 +{
5866 +       struct ipt_entry_target *t;
5867 +       static struct ipt_entry *found = NULL;
5868 +
5869 +       if (s == e) {
5870 +               if (!found)
5871 +                       return 0;
5872 +               t = ipt_get_target(found);
5873 +               if (strcmp(t->u.user.name, 
5874 +                          IPT_ERROR_TARGET) == 0) {
5875 +                       *chainname = t->data;
5876 +                       return 1;
5877 +               }
5878 +       } else
5879 +               found = s;
5880 +       
5881 +       return 0;
5882 +}
5883 +
5884  /* All zeroes == unconditional rule. */
5885  static inline int
5886  unconditional(const struct ipt_ip *ip)
5887 @@ -493,6 +532,8 @@
5888  mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
5889  {
5890         unsigned int hook;
5891 +       char *chainname = NULL;
5892 +       u_int32_t rulenum;
5893  
5894         /* No recursion; use packet counter to save back ptrs (reset
5895            to 0 as we leave), and comefrom to save source hook bitmask */
5896 @@ -506,6 +547,8 @@
5897  
5898                 /* Set initial back pointer. */
5899                 e->counters.pcnt = pos;
5900 +               rulenum = 1;
5901 +               chainname = (char *) hooknames[hook];
5902  
5903                 for (;;) {
5904                         struct ipt_standard_target *t
5905 @@ -518,6 +561,8 @@
5906                         }
5907                         e->comefrom
5908                                 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
5909 +                       e->rulenum = rulenum++;
5910 +                       e->chainname = chainname;
5911  
5912                         /* Unconditional return/END. */
5913                         if (e->target_offset == sizeof(struct ipt_entry)
5914 @@ -527,6 +572,10 @@
5915                             && unconditional(&e->ip)) {
5916                                 unsigned int oldpos, size;
5917  
5918 +                               /* Set unconditional rulenum to zero. */
5919 +                               e->rulenum = 0;
5920 +                               e->counters.bcnt = 0;
5921 +
5922                                 /* Return: backtrack through the last
5923                                    big jump. */
5924                                 do {
5925 @@ -552,6 +601,11 @@
5926                                                 (newinfo->entries + pos);
5927                                 } while (oldpos == pos + e->next_offset);
5928  
5929 +                               /* Restore chainname, rulenum. */
5930 +                               chainname = e->chainname;
5931 +                               rulenum = e->counters.bcnt;
5932 +                               e->counters.bcnt = 0;
5933 +
5934                                 /* Move along one */
5935                                 size = e->next_offset;
5936                                 e = (struct ipt_entry *)
5937 @@ -567,6 +621,17 @@
5938                                         /* This a jump; chase it. */
5939                                         duprintf("Jump rule %u -> %u\n",
5940                                                  pos, newpos);
5941 +                                       e->counters.bcnt = rulenum++;
5942 +                                       rulenum = 1;
5943 +                                       e = (struct ipt_entry *)
5944 +                                               (newinfo->entries + newpos);
5945 +                                       if (IPT_ENTRY_ITERATE(newinfo->entries,
5946 +                                                             newinfo->size,
5947 +                                                             find_error_target,
5948 +                                                             e, &chainname) == 0) {
5949 +                                               printk("ip_tables: table screwed up!\n");
5950 +                                               return 0;
5951 +                                       }
5952                                 } else {
5953                                         /* ... this is a fallthru */
5954                                         newpos = pos + e->next_offset;
5955 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_LOG.c linux-2.6.0-test9/net/ipv4/netfilter/ipt_LOG.c
5956 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_LOG.c  2003-10-25 20:44:37.000000000 +0200
5957 +++ linux-2.6.0-test9/net/ipv4/netfilter/ipt_LOG.c      2003-11-13 11:01:18.000000000 +0100
5958 @@ -4,12 +4,14 @@
5959  #include <linux/module.h>
5960  #include <linux/spinlock.h>
5961  #include <linux/skbuff.h>
5962 +#include <linux/socket.h>
5963  #include <linux/ip.h>
5964  #include <net/icmp.h>
5965  #include <net/udp.h>
5966  #include <net/tcp.h>
5967  #include <net/route.h>
5968  
5969 +#include <linux/netfilter.h>
5970  #include <linux/netfilter_ipv4/ip_tables.h>
5971  #include <linux/netfilter_ipv4/ipt_LOG.h>
5972  
5973 @@ -17,6 +19,10 @@
5974  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
5975  MODULE_DESCRIPTION("iptables syslog logging module");
5976  
5977 +static unsigned int nflog = 1;
5978 +MODULE_PARM(nflog, "i");
5979 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
5980 +
5981  #if 0
5982  #define DEBUGP printk
5983  #else
5984 @@ -315,28 +321,25 @@
5985         /* maxlen = 230+   91  + 230 + 252 = 803 */
5986  }
5987  
5988 -static unsigned int
5989 -ipt_log_target(struct sk_buff **pskb,
5990 +static void
5991 +ipt_log_packet(unsigned int hooknum,
5992 +              const struct sk_buff *skb,
5993                const struct net_device *in,
5994                const struct net_device *out,
5995 -              unsigned int hooknum,
5996 -              const void *targinfo,
5997 -              void *userinfo)
5998 +              const struct ipt_log_info *loginfo,
5999 +              const char *level_string,
6000 +              const char *prefix)
6001  {
6002 -       const struct ipt_log_info *loginfo = targinfo;
6003 -       char level_string[4] = "< >";
6004 -
6005 -       level_string[1] = '0' + (loginfo->level % 8);
6006         spin_lock_bh(&log_lock);
6007         printk(level_string);
6008         printk("%sIN=%s OUT=%s ",
6009 -              loginfo->prefix,
6010 +              prefix == NULL ? loginfo->prefix : prefix,
6011                in ? in->name : "",
6012                out ? out->name : "");
6013  #ifdef CONFIG_BRIDGE_NETFILTER
6014 -       if ((*pskb)->nf_bridge) {
6015 -               struct net_device *physindev = (*pskb)->nf_bridge->physindev;
6016 -               struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev;
6017 +       if (skb->nf_bridge) {
6018 +               struct net_device *physindev = skb->nf_bridge->physindev;
6019 +               struct net_device *physoutdev = skb->nf_bridge->physoutdev;
6020  
6021                 if (physindev && in != physindev)
6022                         printk("PHYSIN=%s ", physindev->name);
6023 @@ -348,25 +351,56 @@
6024         if (in && !out) {
6025                 /* MAC logging for input chain only. */
6026                 printk("MAC=");
6027 -               if ((*pskb)->dev && (*pskb)->dev->hard_header_len
6028 -                   && (*pskb)->mac.raw != (void*)(*pskb)->nh.iph) {
6029 +               if (skb->dev && skb->dev->hard_header_len
6030 +                   && skb->mac.raw != (void*)skb->nh.iph) {
6031                         int i;
6032 -                       unsigned char *p = (*pskb)->mac.raw;
6033 -                       for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
6034 +                       unsigned char *p = skb->mac.raw;
6035 +                       for (i = 0; i < skb->dev->hard_header_len; i++,p++)
6036                                 printk("%02x%c", *p,
6037 -                                      i==(*pskb)->dev->hard_header_len - 1
6038 +                                      i==skb->dev->hard_header_len - 1
6039                                        ? ' ':':');
6040                 } else
6041                         printk(" ");
6042         }
6043  
6044 -       dump_packet(loginfo, *pskb, 0);
6045 +       dump_packet(loginfo, skb, 0);
6046         printk("\n");
6047         spin_unlock_bh(&log_lock);
6048 +}
6049 +
6050 +static unsigned int
6051 +ipt_log_target(struct sk_buff **pskb,
6052 +              const struct net_device *in,
6053 +              const struct net_device *out,
6054 +              unsigned int hooknum,
6055 +              const void *targinfo,
6056 +              void *userinfo)
6057 +{
6058 +       const struct ipt_log_info *loginfo = targinfo;
6059 +       char level_string[4] = "< >";
6060 +
6061 +       level_string[1] = '0' + (loginfo->level % 8);
6062 +       ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
6063  
6064         return IPT_CONTINUE;
6065  }
6066  
6067 +static void
6068 +ipt_logfn(unsigned int hooknum,
6069 +         const struct sk_buff *skb,
6070 +         const struct net_device *in,
6071 +         const struct net_device *out,
6072 +         const char *prefix)
6073 +{
6074 +       struct ipt_log_info loginfo = { 
6075 +               .level = 0, 
6076 +               .logflags = IPT_LOG_MASK, 
6077 +               .prefix = "" 
6078 +       };
6079 +
6080 +       ipt_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
6081 +}
6082 +
6083  static int ipt_log_checkentry(const char *tablename,
6084                               const struct ipt_entry *e,
6085                               void *targinfo,
6086 @@ -406,12 +440,17 @@
6087  {
6088         if (ipt_register_target(&ipt_log_reg))
6089                 return -EINVAL;
6090 +       if (nflog)
6091 +               nf_log_register(PF_INET, &ipt_logfn);
6092  
6093         return 0;
6094  }
6095  
6096  static void __exit fini(void)
6097  {
6098 +       if (nflog)
6099 +               nf_log_unregister(PF_INET, &ipt_logfn);
6100 +
6101         ipt_unregister_target(&ipt_log_reg);
6102  }
6103  
6104 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_NOTRACK.c linux-2.6.0-test9/net/ipv4/netfilter/ipt_NOTRACK.c
6105 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_NOTRACK.c      1970-01-01 01:00:00.000000000 +0100
6106 +++ linux-2.6.0-test9/net/ipv4/netfilter/ipt_NOTRACK.c  2003-11-13 11:01:39.000000000 +0100
6107 @@ -0,0 +1,79 @@
6108 +/* This is a module which is used for setting up fake conntracks
6109 + * on packets so that they are not seen by the conntrack/NAT code.
6110 + */
6111 +#include <linux/module.h>
6112 +#include <linux/skbuff.h>
6113 +
6114 +#include <linux/netfilter_ipv4/ip_tables.h>
6115 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6116 +
6117 +static unsigned int
6118 +target(struct sk_buff **pskb,
6119 +       const struct net_device *in,
6120 +       const struct net_device *out,
6121 +       unsigned int hooknum,
6122 +       const void *targinfo,
6123 +       void *userinfo)
6124 +{
6125 +       /* Previously seen (loopback)? Ignore. */
6126 +       if ((*pskb)->nfct != NULL)
6127 +               return IPT_CONTINUE;
6128 +
6129 +       /* Attach fake conntrack entry. 
6130 +          If there is a real ct entry correspondig to this packet, 
6131 +          it'll hang aroun till timing out. We don't deal with it
6132 +          for performance reasons. JK */
6133 +       (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
6134 +       nf_conntrack_get((*pskb)->nfct);
6135 +
6136 +       return IPT_CONTINUE;
6137 +}
6138 +
6139 +static int
6140 +checkentry(const char *tablename,
6141 +          const struct ipt_entry *e,
6142 +           void *targinfo,
6143 +           unsigned int targinfosize,
6144 +           unsigned int hook_mask)
6145 +{
6146 +       if (targinfosize != 0) {
6147 +               printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
6148 +                      targinfosize);
6149 +               return 0;
6150 +       }
6151 +
6152 +       if (strcmp(tablename, "raw") != 0) {
6153 +               printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
6154 +               return 0;
6155 +       }
6156 +
6157 +       return 1;
6158 +}
6159 +
6160 +static struct ipt_target ipt_notrack_reg = { 
6161 +       .name           = "NOTRACK", 
6162 +       .target         = target, 
6163 +       .checkentry     = checkentry, 
6164 +       .destroy        = NULL, 
6165 +       .me             = THIS_MODULE,
6166 +};
6167 +
6168 +static int __init init(void)
6169 +{
6170 +       if (ipt_register_target(&ipt_notrack_reg))
6171 +               return -EINVAL;
6172 +
6173 +       return 0;
6174 +}
6175 +
6176 +static void __exit fini(void)
6177 +{
6178 +       ipt_unregister_target(&ipt_notrack_reg);
6179 +}
6180 +
6181 +module_init(init);
6182 +module_exit(fini);
6183 +
6184 +MODULE_LICENSE("GPL");
6185 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
6186 +MODULE_DESCRIPTION("IPv4 NOTRACK target");
6187 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.0-test9/net/ipv4/netfilter/ipt_TRACE.c
6188 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_TRACE.c        1970-01-01 01:00:00.000000000 +0100
6189 +++ linux-2.6.0-test9/net/ipv4/netfilter/ipt_TRACE.c    2003-11-13 11:01:39.000000000 +0100
6190 @@ -0,0 +1,67 @@
6191 +/* This is a module which is used for setting 
6192 + * the NFC_TRACE flag in the nfcache field of an skb. 
6193 + */
6194 +#include <linux/module.h>
6195 +#include <linux/skbuff.h>
6196 +
6197 +#include <linux/netfilter_ipv4/ip_tables.h>
6198 +
6199 +static unsigned int
6200 +target(struct sk_buff **pskb,
6201 +       const struct net_device *in,
6202 +       const struct net_device *out,
6203 +       unsigned int hooknum,
6204 +       const void *targinfo,
6205 +       void *userinfo)
6206 +{
6207 +       (*pskb)->nfcache |= NFC_TRACE;
6208 +       return IPT_CONTINUE;
6209 +}
6210 +
6211 +static int
6212 +checkentry(const char *tablename,
6213 +          const struct ipt_entry *e,
6214 +           void *targinfo,
6215 +           unsigned int targinfosize,
6216 +           unsigned int hook_mask)
6217 +{
6218 +       if (targinfosize != 0) {
6219 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
6220 +                      targinfosize);
6221 +               return 0;
6222 +       }
6223 +
6224 +       if (strcmp(tablename, "raw") != 0) {
6225 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
6226 +               return 0;
6227 +       }
6228 +
6229 +       return 1;
6230 +}
6231 +
6232 +static struct ipt_target ipt_trace_reg = { 
6233 +       .name           = "TRACE", 
6234 +       .target         = target, 
6235 +       .checkentry     = checkentry, 
6236 +       .destroy        = NULL, 
6237 +       .me             = THIS_MODULE,
6238 +};
6239 +
6240 +static int __init init(void)
6241 +{
6242 +       if (ipt_register_target(&ipt_trace_reg))
6243 +               return -EINVAL;
6244 +
6245 +       return 0;
6246 +}
6247 +
6248 +static void __exit fini(void)
6249 +{
6250 +       ipt_unregister_target(&ipt_trace_reg);
6251 +}
6252 +
6253 +module_init(init);
6254 +module_exit(fini);
6255 +MODULE_LICENSE("GPL");
6256 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
6257 +MODULE_DESCRIPTION("IPv4 TRACE target");
6258 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_ULOG.c linux-2.6.0-test9/net/ipv4/netfilter/ipt_ULOG.c
6259 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_ULOG.c 2003-10-25 20:43:22.000000000 +0200
6260 +++ linux-2.6.0-test9/net/ipv4/netfilter/ipt_ULOG.c     2003-11-13 11:01:18.000000000 +0100
6261 @@ -45,6 +45,7 @@
6262  #include <linux/netlink.h>
6263  #include <linux/netdevice.h>
6264  #include <linux/mm.h>
6265 +#include <linux/netfilter.h>
6266  #include <linux/netfilter_ipv4/ip_tables.h>
6267  #include <linux/netfilter_ipv4/ipt_ULOG.h>
6268  #include <linux/netfilter_ipv4/lockhelp.h>
6269 @@ -75,6 +76,10 @@
6270  MODULE_PARM(flushtimeout, "i");
6271  MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
6272  
6273 +static unsigned int nflog = 1;
6274 +MODULE_PARM(nflog, "i");
6275 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
6276 +
6277  /* global data structures */
6278  
6279  typedef struct {
6280 @@ -152,17 +157,17 @@
6281         return skb;
6282  }
6283  
6284 -static unsigned int ipt_ulog_target(struct sk_buff **pskb,
6285 -                                   const struct net_device *in,
6286 -                                   const struct net_device *out,
6287 -                                   unsigned int hooknum,
6288 -                                   const void *targinfo, void *userinfo)
6289 +static void ipt_ulog_packet(unsigned int hooknum,
6290 +                           const struct sk_buff *skb,
6291 +                           const struct net_device *in,
6292 +                           const struct net_device *out,
6293 +                           const struct ipt_ulog_info *loginfo,
6294 +                           const char *prefix)
6295  {
6296         ulog_buff_t *ub;
6297         ulog_packet_msg_t *pm;
6298         size_t size, copy_len;
6299         struct nlmsghdr *nlh;
6300 -       struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
6301  
6302         /* ffs == find first bit set, necessary because userspace
6303          * is already shifting groupnumber, but we need unshifted.
6304 @@ -171,8 +176,8 @@
6305  
6306         /* calculate the size of the skb needed */
6307         if ((loginfo->copy_range == 0) ||
6308 -           (loginfo->copy_range > (*pskb)->len)) {
6309 -               copy_len = (*pskb)->len;
6310 +           (loginfo->copy_range > skb->len)) {
6311 +               copy_len = skb->len;
6312         } else {
6313                 copy_len = loginfo->copy_range;
6314         }
6315 @@ -209,19 +214,21 @@
6316  
6317         /* copy hook, prefix, timestamp, payload, etc. */
6318         pm->data_len = copy_len;
6319 -       pm->timestamp_sec = (*pskb)->stamp.tv_sec;
6320 -       pm->timestamp_usec = (*pskb)->stamp.tv_usec;
6321 -       pm->mark = (*pskb)->nfmark;
6322 +       pm->timestamp_sec = skb->stamp.tv_sec;
6323 +       pm->timestamp_usec = skb->stamp.tv_usec;
6324 +       pm->mark = skb->nfmark;
6325         pm->hook = hooknum;
6326 -       if (loginfo->prefix[0] != '\0')
6327 +       if (prefix != NULL)
6328 +               strncpy(pm->prefix, prefix, sizeof(pm->prefix));
6329 +       else if (loginfo->prefix[0] != '\0')
6330                 strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
6331         else
6332                 *(pm->prefix) = '\0';
6333  
6334         if (in && in->hard_header_len > 0
6335 -           && (*pskb)->mac.raw != (void *) (*pskb)->nh.iph
6336 +           && skb->mac.raw != (void *) skb->nh.iph
6337             && in->hard_header_len <= ULOG_MAC_LEN) {
6338 -               memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len);
6339 +               memcpy(pm->mac, skb->mac.raw, in->hard_header_len);
6340                 pm->mac_len = in->hard_header_len;
6341         } else
6342                 pm->mac_len = 0;
6343 @@ -236,8 +243,8 @@
6344         else
6345                 pm->outdev_name[0] = '\0';
6346  
6347 -       /* copy_len <= (*pskb)->len, so can't fail. */
6348 -       if (skb_copy_bits(*pskb, 0, pm->payload, copy_len) < 0)
6349 +       /* copy_len <= skb->len, so can't fail. */
6350 +       if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
6351                 BUG();
6352         
6353         /* check if we are building multi-part messages */
6354 @@ -261,8 +268,7 @@
6355  
6356         UNLOCK_BH(&ulog_lock);
6357  
6358 -       return IPT_CONTINUE;
6359 -
6360 +       return;
6361  
6362  nlmsg_failure:
6363         PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
6364 @@ -271,8 +277,35 @@
6365         PRINTR("ipt_ULOG: Error building netlink message\n");
6366  
6367         UNLOCK_BH(&ulog_lock);
6368 +}
6369 +
6370 +static unsigned int ipt_ulog_target(struct sk_buff **pskb,
6371 +                                   const struct net_device *in,
6372 +                                   const struct net_device *out,
6373 +                                   unsigned int hooknum,
6374 +                                   const void *targinfo, void *userinfo)
6375 +{
6376 +       struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
6377  
6378 -       return IPT_CONTINUE;
6379 +       ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
6380
6381 +       return IPT_CONTINUE;
6382 +}
6383
6384 +static void ipt_logfn(unsigned int hooknum,
6385 +                     const struct sk_buff *skb,
6386 +                     const struct net_device *in,
6387 +                     const struct net_device *out,
6388 +                     const char *prefix)
6389 +{
6390 +       struct ipt_ulog_info loginfo = { 
6391 +               .nl_group = NFLOG_DEFAULT_NLGROUP,
6392 +               .copy_range = 0,
6393 +               .qthreshold = NFLOG_DEFAULT_QTHRESHOLD,
6394 +               .prefix = ""
6395 +       };
6396 +
6397 +       ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
6398  }
6399  
6400  static int ipt_ulog_checkentry(const char *tablename,
6401 @@ -337,6 +370,9 @@
6402                 return -EINVAL;
6403         }
6404  
6405 +       if (nflog)
6406 +               nf_log_register(PF_INET, &ipt_logfn);
6407 +       
6408         return 0;
6409  }
6410  
6411 @@ -347,6 +383,9 @@
6412  
6413         DEBUGP("ipt_ULOG: cleanup_module\n");
6414  
6415 +       if (nflog)
6416 +               nf_log_unregister(PF_INET, &ipt_logfn);
6417 +       
6418         ipt_unregister_target(&ipt_ulog_reg);
6419         sock_release(nflognl->sk_socket);
6420  
6421 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_conntrack.c linux-2.6.0-test9/net/ipv4/netfilter/ipt_conntrack.c
6422 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_conntrack.c    2003-10-25 20:44:42.000000000 +0200
6423 +++ linux-2.6.0-test9/net/ipv4/netfilter/ipt_conntrack.c        2003-11-13 11:01:39.000000000 +0100
6424 @@ -29,7 +29,9 @@
6425  
6426  #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
6427  
6428 -       if (ct)
6429 +       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
6430 +               statebit = IPT_CONNTRACK_STATE_UNTRACKED;
6431 +       else if (ct)
6432                 statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
6433         else
6434                 statebit = IPT_CONNTRACK_STATE_INVALID;
6435 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.0-test9/net/ipv4/netfilter/ipt_sctp.c
6436 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 01:00:00.000000000 +0100
6437 +++ linux-2.6.0-test9/net/ipv4/netfilter/ipt_sctp.c     2003-11-13 11:01:48.000000000 +0100
6438 @@ -0,0 +1,125 @@
6439 +/* IP tables module for matching the SCTP header
6440 + *
6441 + * $ipt_sctp.c,v 1.3 2002/05/29 15:09:00 laforge Exp$
6442 + *
6443 + * (C) 2003 by Harald Welte <laforge@gnumonks.org>
6444 + *
6445 + * This software is distributed under the terms GNU GPL v2
6446 + */
6447 +
6448 +#include <linux/module.h>
6449 +#include <linux/skbuff.h>
6450 +#include <linux/sctp.h>
6451 +
6452 +#include <linux/netfilter_ipv4/ip_tables.h>
6453 +#include <linux/netfilter_ipv4/ipt_sctp.h>
6454 +
6455 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
6456 +MODULE_DESCRIPTION("IP tables SCTP matching module");
6457 +MODULE_LICENSE("GPL");
6458 +
6459 +/* Returns 1 if the port is matched by the range, 0 otherwise */
6460 +static inline int
6461 +port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
6462 +{
6463 +       int ret;
6464 +
6465 +       ret = (port >= min && port <= max) ^ invert;
6466 +       return ret;
6467 +}
6468 +
6469 +static int chunk_match(const struct sk_buff *skb, u_int32_t chunks, u_int32_t chunk_mask)
6470 +{
6471 +       sctp_chunkhdr_t *ch = (sctp_chunkhdr_t *) skb->data;
6472 +
6473 +       u_int32_t chunks_present = 0;
6474 +
6475 +       do {
6476 +               u_int8_t *ch_end;
6477 +               ch_end = ((u_int8_t *) ch) + WORD_ROUND(ntohs(ch->length));
6478 +
6479 +               if (ch->type < 32)
6480 +                       chunks_present |= (1 << ch_type);
6481 +               else if (ch->type == SCTP_CID_ASCONF)
6482 +                       chunks_present |= (1 << 31);
6483 +               else if (ch->type == SCTP_CID_ASCONF_ACK)
6484 +                       chunks_present |= (1 << 30);
6485 +
6486 +               ch = (sctp_chunkhdr_t *) ch_end;
6487 +       } while (ch_end < skb->tail);
6488 +
6489 +       return ((chunks_present& chunk_mask) == chunks);
6490 +}
6491 +
6492 +static int match(const struct sk_buff *skb, const struct net_device *in,
6493 +                const struct net_device *out, const void *matchinfo,
6494 +                int offset, const void *hdr, u_int16_t datalen,
6495 +                int *hotdrop)
6496 +{
6497 +       const struct ipt_sctp_info *info = matchinfo;
6498 +       const struct iphdr *iph = skb->nh.iph;
6499 +       const struct sctphdr *sh = (struct sctphdr *) skb->h.raw;
6500 +
6501 +       if (iph->protocol != IPPROTO_SCTP)
6502 +               return 0;
6503 +
6504 +       if (offset == 1) {
6505 +               duprintf("Dropping evil SCTP offset=1 frag.\n");
6506 +               *hotdrop = 1;
6507 +               return 0;
6508 +       } else if (offset == 0 && datalen < sizeof(struct sctphdr)) {
6509 +               /* We've been askd o examine this packet, and we can't.
6510 +                * Hence, no choice but to drop. */
6511 +               duprintf("Dropping evil SCTP offset=0 tinygram.\n");
6512 +               *hotdrop = 1;
6513 +               return 0;
6514 +       }
6515 +
6516 +       return (!offset
6517 +               && port_match(info->spts[0], info->spts[1],
6518 +                             ntohs(sh->source),
6519 +                             !!(info->invflags & IPT_SCTP_INV_SRCPT))
6520 +               && port_match(info->dpts[0], info->dpts[1],
6521 +                             ntohs(sh->dest),
6522 +                             !!(info->invflags & IPT_SCTP_INV_DSTPT))
6523 +               && chunk_match(skb, info->chunks, info->chunk_mask)
6524 +              );
6525 +}
6526 +
6527 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
6528 +                     void *matchinfo, unsigned int matchsize,
6529 +                     unsigned int hook_mask)
6530 +{
6531 +       const struct ipt_sctp_info *info = matchinfo;
6532 +
6533 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_sctp_info)))
6534 +               return 0;
6535 +
6536 +       if (ip->proto != IPPROTO_SCTP && !(ip->invflags & IPT_INV_PROTO))
6537 +               return 0;
6538 +
6539 +       if !(info->invflags & ~IPT_SCTP_INV_MASK)
6540 +               return 0;
6541 +
6542 +       return 1;
6543 +}
6544 +
6545 +static struct ipt_match sctp_match = {
6546 +       .name           = "sctp",
6547 +       .match          = &match,
6548 +       .checkentry     = &checkentry,
6549 +       .me             = THIS_MODULE,
6550 +};
6551 +
6552 +static int __init init(void)
6553 +{
6554 +       return ipt_register_match(&sctp_match);
6555 +}
6556 +
6557 +static void __exit fini(void)
6558 +{
6559 +       ipt_unregister_match(&sctp_match);
6560 +}
6561 +
6562 +module_init(init);
6563 +module_exit(fini);
6564 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_state.c linux-2.6.0-test9/net/ipv4/netfilter/ipt_state.c
6565 --- linux-2.6.0-test9.org/net/ipv4/netfilter/ipt_state.c        2003-10-25 20:44:59.000000000 +0200
6566 +++ linux-2.6.0-test9/net/ipv4/netfilter/ipt_state.c    2003-11-13 11:01:39.000000000 +0100
6567 @@ -23,10 +23,12 @@
6568         enum ip_conntrack_info ctinfo;
6569         unsigned int statebit;
6570  
6571 -       if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
6572 -               statebit = IPT_STATE_INVALID;
6573 -       else
6574 +       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
6575 +               statebit = IPT_STATE_UNTRACKED;
6576 +       else if (ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
6577                 statebit = IPT_STATE_BIT(ctinfo);
6578 +       else
6579 +               statebit = IPT_STATE_INVALID;
6580  
6581         return (sinfo->statemask & statebit);
6582  }
6583 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.0-test9/net/ipv4/netfilter/iptable_filter.c
6584 --- linux-2.6.0-test9.org/net/ipv4/netfilter/iptable_filter.c   2003-10-25 20:43:23.000000000 +0200
6585 +++ linux-2.6.0-test9/net/ipv4/netfilter/iptable_filter.c       2003-11-13 11:01:39.000000000 +0100
6586 @@ -52,7 +52,7 @@
6587                 0,
6588                 sizeof(struct ipt_entry),
6589                 sizeof(struct ipt_standard),
6590 -               0, { 0, 0 }, { } },
6591 +               0, NULL, 0, { 0, 0 }, { } },
6592               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
6593                 -NF_ACCEPT - 1 } },
6594             /* FORWARD */
6595 @@ -60,7 +60,7 @@
6596                 0,
6597                 sizeof(struct ipt_entry),
6598                 sizeof(struct ipt_standard),
6599 -               0, { 0, 0 }, { } },
6600 +               0, NULL, 0, { 0, 0 }, { } },
6601               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
6602                 -NF_ACCEPT - 1 } },
6603             /* LOCAL_OUT */
6604 @@ -68,7 +68,7 @@
6605                 0,
6606                 sizeof(struct ipt_entry),
6607                 sizeof(struct ipt_standard),
6608 -               0, { 0, 0 }, { } },
6609 +               0, NULL, 0, { 0, 0 }, { } },
6610               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
6611                 -NF_ACCEPT - 1 } }
6612      },
6613 @@ -77,7 +77,7 @@
6614         0,
6615         sizeof(struct ipt_entry),
6616         sizeof(struct ipt_error),
6617 -       0, { 0, 0 }, { } },
6618 +       0, NULL, 0, { 0, 0 }, { } },
6619        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
6620           { } },
6621         "ERROR"
6622 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.0-test9/net/ipv4/netfilter/iptable_mangle.c
6623 --- linux-2.6.0-test9.org/net/ipv4/netfilter/iptable_mangle.c   2003-10-25 20:44:37.000000000 +0200
6624 +++ linux-2.6.0-test9/net/ipv4/netfilter/iptable_mangle.c       2003-11-13 11:01:39.000000000 +0100
6625 @@ -69,7 +69,7 @@
6626                 0,
6627                 sizeof(struct ipt_entry),
6628                 sizeof(struct ipt_standard),
6629 -               0, { 0, 0 }, { } },
6630 +               0, NULL, 0, { 0, 0 }, { } },
6631               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
6632                 -NF_ACCEPT - 1 } },
6633             /* LOCAL_IN */
6634 @@ -77,7 +77,7 @@
6635                 0,
6636                 sizeof(struct ipt_entry),
6637                 sizeof(struct ipt_standard),
6638 -               0, { 0, 0 }, { } },
6639 +               0, NULL, 0, { 0, 0 }, { } },
6640               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
6641                 -NF_ACCEPT - 1 } },
6642             /* FORWARD */
6643 @@ -85,7 +85,7 @@
6644                 0,
6645                 sizeof(struct ipt_entry),
6646                 sizeof(struct ipt_standard),
6647 -               0, { 0, 0 }, { } },
6648 +               0, NULL, 0, { 0, 0 }, { } },
6649               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
6650                 -NF_ACCEPT - 1 } },
6651             /* LOCAL_OUT */
6652 @@ -93,7 +93,7 @@
6653                 0,
6654                 sizeof(struct ipt_entry),
6655                 sizeof(struct ipt_standard),
6656 -               0, { 0, 0 }, { } },
6657 +               0, NULL, 0, { 0, 0 }, { } },
6658               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
6659                 -NF_ACCEPT - 1 } },
6660             /* POST_ROUTING */
6661 @@ -101,7 +101,7 @@
6662                 0,
6663                 sizeof(struct ipt_entry),
6664                 sizeof(struct ipt_standard),
6665 -               0, { 0, 0 }, { } },
6666 +               0, NULL, 0, { 0, 0 }, { } },
6667               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
6668                 -NF_ACCEPT - 1 } },
6669      },
6670 @@ -110,7 +110,7 @@
6671         0,
6672         sizeof(struct ipt_entry),
6673         sizeof(struct ipt_error),
6674 -       0, { 0, 0 }, { } },
6675 +       0, NULL, 0, { 0, 0 }, { } },
6676        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
6677           { } },
6678         "ERROR"
6679 diff -Nur linux-2.6.0-test9.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.0-test9/net/ipv4/netfilter/iptable_raw.c
6680 --- linux-2.6.0-test9.org/net/ipv4/netfilter/iptable_raw.c      1970-01-01 01:00:00.000000000 +0100
6681 +++ linux-2.6.0-test9/net/ipv4/netfilter/iptable_raw.c  2003-11-13 11:01:39.000000000 +0100
6682 @@ -0,0 +1,153 @@
6683 +/* 
6684 + * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
6685 + *
6686 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6687 + */
6688 +#include <linux/module.h>
6689 +#include <linux/netfilter_ipv4/ip_tables.h>
6690 +
6691 +#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
6692 +
6693 +/* Standard entry. */
6694 +struct ipt_standard
6695 +{
6696 +       struct ipt_entry entry;
6697 +       struct ipt_standard_target target;
6698 +};
6699 +
6700 +struct ipt_error_target
6701 +{
6702 +       struct ipt_entry_target target;
6703 +       char errorname[IPT_FUNCTION_MAXNAMELEN];
6704 +};
6705 +
6706 +struct ipt_error
6707 +{
6708 +       struct ipt_entry entry;
6709 +       struct ipt_error_target target;
6710 +};
6711 +
6712 +static struct
6713 +{
6714 +       struct ipt_replace repl;
6715 +       struct ipt_standard entries[2];
6716 +       struct ipt_error term;
6717 +} initial_table __initdata
6718 += { { "raw", RAW_VALID_HOOKS, 3,
6719 +      sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
6720 +      { [NF_IP_PRE_ROUTING] 0,
6721 +       [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
6722 +      { [NF_IP_PRE_ROUTING] 0,
6723 +       [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
6724 +      0, NULL, { } },
6725 +    {
6726 +           /* PRE_ROUTING */
6727 +           { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
6728 +               0,
6729 +               sizeof(struct ipt_entry),
6730 +               sizeof(struct ipt_standard),
6731 +               0, NULL, 0, { 0, 0 }, { } },
6732 +             { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
6733 +               -NF_ACCEPT - 1 } },
6734 +           /* LOCAL_OUT */
6735 +           { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
6736 +               0,
6737 +               sizeof(struct ipt_entry),
6738 +               sizeof(struct ipt_standard),
6739 +               0, NULL, 0, { 0, 0 }, { } },
6740 +             { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
6741 +               -NF_ACCEPT - 1 } }
6742 +    },
6743 +    /* ERROR */
6744 +    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
6745 +       0,
6746 +       sizeof(struct ipt_entry),
6747 +       sizeof(struct ipt_error),
6748 +       0, NULL, 0, { 0, 0 }, { } },
6749 +      { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
6750 +         { } },
6751 +       "ERROR"
6752 +      }
6753 +    }
6754 +};
6755 +
6756 +static struct ipt_table packet_raw = {
6757 +       .name = "raw",
6758 +       .table = &initial_table.repl,
6759 +       .valid_hooks =  RAW_VALID_HOOKS,
6760 +       .lock = RW_LOCK_UNLOCKED,
6761 +       .me = THIS_MODULE,
6762 +};
6763 +
6764 +/* The work comes in here from netfilter.c. */
6765 +static unsigned int
6766 +ipt_hook(unsigned int hook,
6767 +        struct sk_buff **pskb,
6768 +        const struct net_device *in,
6769 +        const struct net_device *out,
6770 +        int (*okfn)(struct sk_buff *))
6771 +{
6772 +       return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
6773 +}
6774 +
6775 +/* 'raw' is the very first table. */
6776 +static struct nf_hook_ops ipt_ops[] = {
6777 +       {       /* PRE_ROUTING hook */
6778 +               .hook           = ipt_hook, 
6779 +               .owner          = THIS_MODULE,
6780 +               .pf             = PF_INET, 
6781 +               .hooknum        = NF_IP_PRE_ROUTING, 
6782 +               .priority       = NF_IP_PRI_RAW,
6783 +       },
6784 +       {       /* LOCAL_OUT hook */
6785 +               .hook           = ipt_hook,
6786 +               .owner          = THIS_MODULE,
6787 +               .pf             = PF_INET,
6788 +               .hooknum        = NF_IP_LOCAL_OUT,
6789 +               .priority       = NF_IP_PRI_RAW,
6790 +       },
6791 +};
6792 +
6793 +static int __init init(void)
6794 +{
6795 +       int ret;
6796 +
6797 +       /* Register table */
6798 +       ret = ipt_register_table(&packet_raw);
6799 +       if (ret < 0)
6800 +               return ret;
6801 +
6802 +       /* Register hooks */
6803 +       ret = nf_register_hook(&ipt_ops[0]);
6804 +       if (ret < 0)
6805 +               goto cleanup_table;
6806 +
6807 +       ret = nf_register_hook(&ipt_ops[1]);
6808 +       if (ret < 0)
6809 +               goto cleanup_hook0;
6810 +
6811 +       return ret;
6812 +
6813 + cleanup_hook0:
6814 +       nf_unregister_hook(&ipt_ops[0]);
6815 + cleanup_table:
6816 +       ipt_unregister_table(&packet_raw);
6817 +
6818 +       return ret;
6819 +}
6820 +
6821 +static void __exit fini(void)
6822 +{
6823 +       unsigned int i;
6824 +
6825 +       for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
6826 +               nf_unregister_hook(&ipt_ops[i]);
6827 +
6828 +       ipt_unregister_table(&packet_raw);
6829 +}
6830 +
6831 +module_init(init);
6832 +module_exit(fini);
6833 +MODULE_LICENSE("GPL");
6834 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
6835 +MODULE_DESCRIPTION("IPv4 raw table");
6836 diff -Nur linux-2.6.0-test9.org/net/ipv6/netfilter/Kconfig linux-2.6.0-test9/net/ipv6/netfilter/Kconfig
6837 --- linux-2.6.0-test9.org/net/ipv6/netfilter/Kconfig    2003-10-25 20:44:37.000000000 +0200
6838 +++ linux-2.6.0-test9/net/ipv6/netfilter/Kconfig        2003-11-13 11:01:39.000000000 +0100
6839 @@ -217,6 +217,31 @@
6840  
6841           To compile it as a module, choose M here.  If unsure, say N.
6842  
6843 +config IP6_NF_RAW
6844 +       tristate "Raw table"
6845 +       depends on IP6_NF_IPTABLES
6846 +       help
6847 +         This option adds a `raw' table to iptables: see the man page for
6848 +         iptables(8).  This table is the very first in the netfilter
6849 +         framework and hooks in at the PREROUTING and OUTPUT chains.
6850 +         The TRACE target can be used in this table only.
6851 +
6852 +         To compile it as a module, choose M here.  If unsure, say N.
6853 +
6854 +config IP6_NF_TARGET_TRACE
6855 +       tristate "TRACE target support"
6856 +       depends on IP6_NF_RAW
6857 +       help
6858 +         The TRACE target allows packets to be traced as those matches
6859 +         any subsequent rule in any IPv6 netfilter table/rule. The matched 
6860 +         rule and the packet is logged with the prefix
6861 +         
6862 +         TRACE: tablename/chainname/rulenum
6863 +         
6864 +         if the ip6t_LOG target is loaded in.
6865 +
6866 +         To compile it as a module, choose M here.  If unsure, say N.
6867 +
6868  #dep_tristate '  LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
6869  endmenu
6870  
6871 diff -Nur linux-2.6.0-test9.org/net/ipv6/netfilter/Makefile linux-2.6.0-test9/net/ipv6/netfilter/Makefile
6872 --- linux-2.6.0-test9.org/net/ipv6/netfilter/Makefile   2003-10-25 20:43:53.000000000 +0200
6873 +++ linux-2.6.0-test9/net/ipv6/netfilter/Makefile       2003-11-13 11:01:39.000000000 +0100
6874 @@ -18,7 +18,9 @@
6875  obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
6876  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
6877  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
6878 +obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
6879  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
6880  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
6881  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
6882 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
6883  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
6884 diff -Nur linux-2.6.0-test9.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.0-test9/net/ipv6/netfilter/ip6_tables.c
6885 --- linux-2.6.0-test9.org/net/ipv6/netfilter/ip6_tables.c       2003-10-25 20:44:39.000000000 +0200
6886 +++ linux-2.6.0-test9/net/ipv6/netfilter/ip6_tables.c   2003-11-13 11:01:39.000000000 +0100
6887 @@ -12,6 +12,7 @@
6888   */
6889  #include <linux/config.h>
6890  #include <linux/skbuff.h>
6891 +#include <linux/socket.h>
6892  #include <linux/kmod.h>
6893  #include <linux/vmalloc.h>
6894  #include <linux/netdevice.h>
6895 @@ -24,8 +25,17 @@
6896  #include <asm/semaphore.h>
6897  #include <linux/proc_fs.h>
6898  
6899 +#include <linux/netfilter.h>
6900  #include <linux/netfilter_ipv6/ip6_tables.h>
6901  
6902 +static const char *hook6names[] = { 
6903 +       [NF_IP6_PRE_ROUTING] "PREROUTING",
6904 +       [NF_IP6_LOCAL_IN] "INPUT",
6905 +       [NF_IP6_FORWARD] "FORWARD",
6906 +       [NF_IP6_LOCAL_OUT] "OUTPUT",
6907 +       [NF_IP6_POST_ROUTING] "POSTROUTING",
6908 +};
6909 +
6910  MODULE_LICENSE("GPL");
6911  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
6912  MODULE_DESCRIPTION("IPv6 packet filter");
6913 @@ -403,6 +413,12 @@
6914  
6915                         t = ip6t_get_target(e);
6916                         IP_NF_ASSERT(t->u.kernel.target);
6917 +
6918 +                       /* The packet traced and the rule isn't an unconditional return/END. */
6919 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
6920 +                               nf_log_packet(AF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
6921 +                                                 table->name, e->chainname, e->rulenum);
6922 +                       }
6923                         /* Standard target? */
6924                         if (!t->u.kernel.target->target) {
6925                                 int v;
6926 @@ -556,6 +572,29 @@
6927         return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
6928  }
6929  
6930 +static inline int
6931 +find_error_target(struct ip6t_entry *s, 
6932 +                 struct ip6t_entry *e,
6933 +                 char **chainname)
6934 +{
6935 +       struct ip6t_entry_target *t;
6936 +       static struct ip6t_entry *found = NULL;
6937 +
6938 +       if (s == e) {
6939 +               if (!found)
6940 +                       return 0;
6941 +               t = ip6t_get_target(found);
6942 +               if (strcmp(t->u.user.name, 
6943 +                          IP6T_ERROR_TARGET) == 0) {
6944 +                       *chainname = t->data;
6945 +                       return 1;
6946 +               }
6947 +       } else
6948 +               found = s;
6949 +       
6950 +       return 0;
6951 +}
6952 +
6953  /* All zeroes == unconditional rule. */
6954  static inline int
6955  unconditional(const struct ip6t_ip6 *ipv6)
6956 @@ -575,6 +614,8 @@
6957  mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
6958  {
6959         unsigned int hook;
6960 +       char *chainname = NULL;
6961 +       u_int32_t rulenum;
6962  
6963         /* No recursion; use packet counter to save back ptrs (reset
6964            to 0 as we leave), and comefrom to save source hook bitmask */
6965 @@ -588,6 +629,8 @@
6966  
6967                 /* Set initial back pointer. */
6968                 e->counters.pcnt = pos;
6969 +               rulenum = 1;
6970 +               chainname = (char *) hook6names[hook];
6971  
6972                 for (;;) {
6973                         struct ip6t_standard_target *t
6974 @@ -600,6 +643,8 @@
6975                         }
6976                         e->comefrom
6977                                 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
6978 +                       e->rulenum = rulenum++;
6979 +                       e->chainname = chainname;
6980  
6981                         /* Unconditional return/END. */
6982                         if (e->target_offset == sizeof(struct ip6t_entry)
6983 @@ -609,6 +654,10 @@
6984                             && unconditional(&e->ipv6)) {
6985                                 unsigned int oldpos, size;
6986  
6987 +                               /* Set unconditional rulenum to zero. */
6988 +                               e->rulenum = 0;
6989 +                               e->counters.bcnt = 0;
6990 +
6991                                 /* Return: backtrack through the last
6992                                    big jump. */
6993                                 do {
6994 @@ -634,6 +683,11 @@
6995                                                 (newinfo->entries + pos);
6996                                 } while (oldpos == pos + e->next_offset);
6997  
6998 +                               /* Restore chainname, rulenum. */
6999 +                               chainname = e->chainname;
7000 +                               rulenum = e->counters.bcnt;
7001 +                               e->counters.bcnt = 0;
7002 +
7003                                 /* Move along one */
7004                                 size = e->next_offset;
7005                                 e = (struct ip6t_entry *)
7006 @@ -649,6 +703,17 @@
7007                                         /* This a jump; chase it. */
7008                                         duprintf("Jump rule %u -> %u\n",
7009                                                  pos, newpos);
7010 +                                       e->counters.bcnt = rulenum++;
7011 +                                       rulenum = 1;
7012 +                                       e = (struct ip6t_entry *)
7013 +                                               (newinfo->entries + newpos);
7014 +                                       if (IP6T_ENTRY_ITERATE(newinfo->entries,
7015 +                                                              newinfo->size,
7016 +                                                              find_error_target,
7017 +                                                              e, &chainname) == 0) {
7018 +                                               printk("ip6_tables: table screwed up!\n");
7019 +                                               return 0;
7020 +                                       }
7021                                 } else {
7022                                         /* ... this is a fallthru */
7023                                         newpos = pos + e->next_offset;
7024 diff -Nur linux-2.6.0-test9.org/net/ipv6/netfilter/ip6t_LOG.c linux-2.6.0-test9/net/ipv6/netfilter/ip6t_LOG.c
7025 --- linux-2.6.0-test9.org/net/ipv6/netfilter/ip6t_LOG.c 2003-10-25 20:43:18.000000000 +0200
7026 +++ linux-2.6.0-test9/net/ipv6/netfilter/ip6t_LOG.c     2003-11-13 11:01:18.000000000 +0100
7027 @@ -3,18 +3,24 @@
7028   */
7029  #include <linux/module.h>
7030  #include <linux/skbuff.h>
7031 +#include <linux/socket.h>
7032  #include <linux/ip.h>
7033  #include <linux/spinlock.h>
7034  #include <linux/icmpv6.h>
7035  #include <net/udp.h>
7036  #include <net/tcp.h>
7037  #include <net/ipv6.h>
7038 +#include <linux/netfilter.h>
7039  #include <linux/netfilter_ipv6/ip6_tables.h>
7040  
7041  MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
7042  MODULE_DESCRIPTION("IP6 tables LOG target module");
7043  MODULE_LICENSE("GPL");
7044  
7045 +static unsigned int nflog = 1;
7046 +MODULE_PARM(nflog, "i");
7047 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
7048 +
7049  struct in_device;
7050  #include <net/route.h>
7051  #include <linux/netfilter_ipv6/ip6t_LOG.h>
7052 @@ -256,40 +262,38 @@
7053         }
7054  }
7055  
7056 -static unsigned int
7057 -ip6t_log_target(struct sk_buff **pskb,
7058 -               unsigned int hooknum,
7059 -               const struct net_device *in,
7060 -               const struct net_device *out,
7061 -               const void *targinfo,
7062 -               void *userinfo)
7063 +static void
7064 +ip6t_log_packet(unsigned int hooknum,
7065 +               const struct sk_buff *skb,
7066 +               const struct net_device *in,
7067 +               const struct net_device *out,
7068 +               const struct ip6t_log_info *loginfo,
7069 +               const char *level_string,
7070 +               const char *prefix)
7071  {
7072 -       struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
7073 -       const struct ip6t_log_info *loginfo = targinfo;
7074 -       char level_string[4] = "< >";
7075 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
7076  
7077 -       level_string[1] = '0' + (loginfo->level % 8);
7078         spin_lock_bh(&log_lock);
7079         printk(level_string);
7080         printk("%sIN=%s OUT=%s ",
7081 -               loginfo->prefix,
7082 +               prefix == NULL ? loginfo->prefix : prefix,
7083                 in ? in->name : "",
7084                 out ? out->name : "");
7085         if (in && !out) {
7086                 /* MAC logging for input chain only. */
7087                 printk("MAC=");
7088 -               if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) {
7089 -                       if ((*pskb)->dev->type != ARPHRD_SIT){
7090 +               if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
7091 +                       if (skb->dev->type != ARPHRD_SIT){
7092                           int i;
7093 -                         unsigned char *p = (*pskb)->mac.raw;
7094 -                         for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
7095 +                         unsigned char *p = skb->mac.raw;
7096 +                         for (i = 0; i < skb->dev->hard_header_len; i++,p++)
7097                                 printk("%02x%c", *p,
7098 -                                       i==(*pskb)->dev->hard_header_len - 1
7099 +                                       i==skb->dev->hard_header_len - 1
7100                                         ? ' ':':');
7101                         } else {
7102                           int i;
7103 -                         unsigned char *p = (*pskb)->mac.raw;
7104 -                         if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){
7105 +                         unsigned char *p = skb->mac.raw;
7106 +                         if ( p - (ETH_ALEN*2+2) > skb->head ){
7107                             p -= (ETH_ALEN+2);
7108                             for (i = 0; i < (ETH_ALEN); i++,p++)
7109                                 printk("%02x%s", *p,
7110 @@ -300,10 +304,10 @@
7111                                         i == ETH_ALEN-1 ? ' ' : ':');
7112                           }
7113                           
7114 -                         if (((*pskb)->dev->addr_len == 4) &&
7115 -                             (*pskb)->dev->hard_header_len > 20){
7116 +                         if ((skb->dev->addr_len == 4) &&
7117 +                             skb->dev->hard_header_len > 20){
7118                             printk("TUNNEL=");
7119 -                           p = (*pskb)->mac.raw + 12;
7120 +                           p = skb->mac.raw + 12;
7121                             for (i = 0; i < 4; i++,p++)
7122                                 printk("%3d%s", *p,
7123                                         i == 3 ? "->" : ".");
7124 @@ -319,10 +323,41 @@
7125         dump_packet(loginfo, ipv6h, 1);
7126         printk("\n");
7127         spin_unlock_bh(&log_lock);
7128 +}
7129 +
7130 +static unsigned int
7131 +ip6t_log_target(struct sk_buff **pskb,
7132 +               unsigned int hooknum,
7133 +               const struct net_device *in,
7134 +               const struct net_device *out,
7135 +               const void *targinfo,
7136 +               void *userinfo)
7137 +{
7138 +       const struct ip6t_log_info *loginfo = targinfo;
7139 +       char level_string[4] = "< >";
7140 +
7141 +       level_string[1] = '0' + (loginfo->level % 8);
7142 +       ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
7143  
7144         return IP6T_CONTINUE;
7145  }
7146  
7147 +static void
7148 +ip6t_logfn(unsigned int hooknum,
7149 +          const struct sk_buff *skb,
7150 +          const struct net_device *in,
7151 +          const struct net_device *out,
7152 +          const char *prefix)
7153 +{
7154 +       struct ip6t_log_info loginfo = { 
7155 +               .level = 0, 
7156 +               .logflags = IP6T_LOG_MASK, 
7157 +               .prefix = "" 
7158 +       };
7159 +
7160 +       ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
7161 +}
7162 +
7163  static int ip6t_log_checkentry(const char *tablename,
7164                                const struct ip6t_entry *e,
7165                                void *targinfo,
7166 @@ -359,12 +394,17 @@
7167  {
7168         if (ip6t_register_target(&ip6t_log_reg))
7169                 return -EINVAL;
7170 +       if (nflog)
7171 +               nf_log_register(PF_INET6, &ip6t_logfn);
7172  
7173         return 0;
7174  }
7175  
7176  static void __exit fini(void)
7177  {
7178 +       if (nflog)
7179 +               nf_log_register(PF_INET6, &ip6t_logfn);
7180 +
7181         ip6t_unregister_target(&ip6t_log_reg);
7182  }
7183  
7184 diff -Nur linux-2.6.0-test9.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.0-test9/net/ipv6/netfilter/ip6t_TRACE.c
7185 --- linux-2.6.0-test9.org/net/ipv6/netfilter/ip6t_TRACE.c       1970-01-01 01:00:00.000000000 +0100
7186 +++ linux-2.6.0-test9/net/ipv6/netfilter/ip6t_TRACE.c   2003-11-13 11:01:39.000000000 +0100
7187 @@ -0,0 +1,69 @@
7188 +/* This is a module which is used for setting
7189 + * the NFC_TRACE flag in the nfcache field of an skb. 
7190 + */
7191 +#include <linux/module.h>
7192 +#include <linux/skbuff.h>
7193 +
7194 +#include <linux/netfilter_ipv6/ip6_tables.h>
7195 +
7196 +static unsigned int
7197 +target(struct sk_buff **pskb,
7198 +       unsigned int hooknum,
7199 +       const struct net_device *in,
7200 +       const struct net_device *out,
7201 +       const void *targinfo,
7202 +       void *userinfo)
7203 +{
7204 +       (*pskb)->nfcache |= NFC_TRACE;
7205 +       return IP6T_CONTINUE;
7206 +}
7207 +
7208 +static int 
7209 +checkentry(const char *tablename,
7210 +                  const struct ip6t_entry *e,
7211 +           void *targinfo,
7212 +           unsigned int targinfosize,
7213 +           unsigned int hook_mask)
7214 +{
7215 +       if (targinfosize != 0) {
7216 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
7217 +                      targinfosize);
7218 +               return 0;
7219 +       }
7220 +
7221 +       if (strcmp(tablename, "raw") != 0) {
7222 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
7223 +               return 0;
7224 +       }
7225 +
7226 +       return 1;
7227 +}
7228 +
7229 +static struct ip6t_target ip6t_trace_reg = {
7230 +       .name = "TRACE",
7231 +       .target = target,
7232 +       .checkentry = checkentry,
7233 +       .destroy = NULL,
7234 +       .me = THIS_MODULE,
7235 +};
7236 +
7237 +static int __init init(void)
7238 +{
7239 +       if (ip6t_register_target(&ip6t_trace_reg))
7240 +               return -EINVAL;
7241 +
7242 +       return 0;
7243 +}
7244 +
7245 +static void __exit fini(void)
7246 +{
7247 +       ip6t_unregister_target(&ip6t_trace_reg);
7248 +}
7249 +
7250 +module_init(init);
7251 +module_exit(fini);
7252 +
7253 +MODULE_LICENSE("GPL");
7254 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
7255 +MODULE_DESCRIPTION("IPv6 TRACE target");
7256
7257 \ No newline at end of file
7258 diff -Nur linux-2.6.0-test9.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.0-test9/net/ipv6/netfilter/ip6table_filter.c
7259 --- linux-2.6.0-test9.org/net/ipv6/netfilter/ip6table_filter.c  2003-10-25 20:42:53.000000000 +0200
7260 +++ linux-2.6.0-test9/net/ipv6/netfilter/ip6table_filter.c      2003-11-13 11:01:39.000000000 +0100
7261 @@ -52,7 +52,7 @@
7262                 0,
7263                 sizeof(struct ip6t_entry),
7264                 sizeof(struct ip6t_standard),
7265 -               0, { 0, 0 }, { } },
7266 +               0, NULL, 0, { 0, 0 }, { } },
7267               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
7268                 -NF_ACCEPT - 1 } },
7269             /* FORWARD */
7270 @@ -60,7 +60,7 @@
7271                 0,
7272                 sizeof(struct ip6t_entry),
7273                 sizeof(struct ip6t_standard),
7274 -               0, { 0, 0 }, { } },
7275 +               0, NULL, 0, { 0, 0 }, { } },
7276               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
7277                 -NF_ACCEPT - 1 } },
7278             /* LOCAL_OUT */
7279 @@ -68,7 +68,7 @@
7280                 0,
7281                 sizeof(struct ip6t_entry),
7282                 sizeof(struct ip6t_standard),
7283 -               0, { 0, 0 }, { } },
7284 +               0, NULL, 0, { 0, 0 }, { } },
7285               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
7286                 -NF_ACCEPT - 1 } }
7287      },
7288 @@ -77,7 +77,7 @@
7289         0,
7290         sizeof(struct ip6t_entry),
7291         sizeof(struct ip6t_error),
7292 -       0, { 0, 0 }, { } },
7293 +       0, NULL, 0, { 0, 0 }, { } },
7294        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
7295           { } },
7296         "ERROR"
7297 diff -Nur linux-2.6.0-test9.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.0-test9/net/ipv6/netfilter/ip6table_mangle.c
7298 --- linux-2.6.0-test9.org/net/ipv6/netfilter/ip6table_mangle.c  2003-10-25 20:43:26.000000000 +0200
7299 +++ linux-2.6.0-test9/net/ipv6/netfilter/ip6table_mangle.c      2003-11-13 11:01:39.000000000 +0100
7300 @@ -66,7 +66,7 @@
7301                 0,
7302                 sizeof(struct ip6t_entry),
7303                 sizeof(struct ip6t_standard),
7304 -               0, { 0, 0 }, { } },
7305 +               0, NULL, 0, { 0, 0 }, { } },
7306               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
7307                 -NF_ACCEPT - 1 } },
7308             /* LOCAL_IN */
7309 @@ -74,7 +74,7 @@
7310                 0,
7311                 sizeof(struct ip6t_entry),
7312                 sizeof(struct ip6t_standard),
7313 -               0, { 0, 0 }, { } },
7314 +               0, NULL, 0, { 0, 0 }, { } },
7315               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
7316                 -NF_ACCEPT - 1 } },
7317             /* FORWARD */
7318 @@ -82,7 +82,7 @@
7319                 0,
7320                 sizeof(struct ip6t_entry),
7321                 sizeof(struct ip6t_standard),
7322 -               0, { 0, 0 }, { } },
7323 +               0, NULL, 0, { 0, 0 }, { } },
7324               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
7325                 -NF_ACCEPT - 1 } },
7326             /* LOCAL_OUT */
7327 @@ -90,7 +90,7 @@
7328                 0,
7329                 sizeof(struct ip6t_entry),
7330                 sizeof(struct ip6t_standard),
7331 -               0, { 0, 0 }, { } },
7332 +               0, NULL, 0, { 0, 0 }, { } },
7333               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
7334                 -NF_ACCEPT - 1 } },
7335             /* POST_ROUTING */
7336 @@ -98,7 +98,7 @@
7337                 0,
7338                 sizeof(struct ip6t_entry),
7339                 sizeof(struct ip6t_standard),
7340 -               0, { 0, 0 }, { } },
7341 +               0, NULL, 0, { 0, 0 }, { } },
7342               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
7343                 -NF_ACCEPT - 1 } }
7344      },
7345 @@ -107,7 +107,7 @@
7346         0,
7347         sizeof(struct ip6t_entry),
7348         sizeof(struct ip6t_error),
7349 -       0, { 0, 0 }, { } },
7350 +       0, NULL, 0, { 0, 0 }, { } },
7351        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
7352           { } },
7353         "ERROR"
7354 diff -Nur linux-2.6.0-test9.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.0-test9/net/ipv6/netfilter/ip6table_raw.c
7355 --- linux-2.6.0-test9.org/net/ipv6/netfilter/ip6table_raw.c     1970-01-01 01:00:00.000000000 +0100
7356 +++ linux-2.6.0-test9/net/ipv6/netfilter/ip6table_raw.c 2003-11-13 11:01:39.000000000 +0100
7357 @@ -0,0 +1,158 @@
7358 +/*
7359 + * IPv6 raw table, a port of the IPv4 raw table to IPv6
7360 + *
7361 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7362 + */
7363 +#include <linux/module.h>
7364 +#include <linux/netfilter_ipv6/ip6_tables.h>
7365 +
7366 +#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
7367 +
7368 +#if 0
7369 +#define DEBUGP(x, args...)     printk(KERN_DEBUG x, ## args)
7370 +#else
7371 +#define DEBUGP(x, args...)
7372 +#endif
7373 +
7374 +/* Standard entry. */
7375 +struct ip6t_standard
7376 +{
7377 +       struct ip6t_entry entry;
7378 +       struct ip6t_standard_target target;
7379 +};
7380 +
7381 +struct ip6t_error_target
7382 +{
7383 +       struct ip6t_entry_target target;
7384 +       char errorname[IP6T_FUNCTION_MAXNAMELEN];
7385 +};
7386 +
7387 +struct ip6t_error
7388 +{
7389 +       struct ip6t_entry entry;
7390 +       struct ip6t_error_target target;
7391 +};
7392 +
7393 +static struct
7394 +{
7395 +       struct ip6t_replace repl;
7396 +       struct ip6t_standard entries[2];
7397 +       struct ip6t_error term;
7398 +} initial_table __initdata 
7399 += { { "raw", RAW_VALID_HOOKS, 3,
7400 +      sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
7401 +      { [NF_IP6_PRE_ROUTING]   0,
7402 +       [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) },
7403 +      { [NF_IP6_PRE_ROUTING]   0,
7404 +       [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) },
7405 +      0, NULL, { } },
7406 +    {
7407 +           /* PRE_ROUTING */
7408 +            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
7409 +               0,
7410 +               sizeof(struct ip6t_entry),
7411 +               sizeof(struct ip6t_standard),
7412 +               0, NULL, 0, { 0, 0 }, { } },
7413 +             { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
7414 +               -NF_ACCEPT - 1 } },
7415 +           /* LOCAL_OUT */
7416 +            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
7417 +               0,
7418 +               sizeof(struct ip6t_entry),
7419 +               sizeof(struct ip6t_standard),
7420 +               0, NULL, 0, { 0, 0 }, { } },
7421 +             { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
7422 +               -NF_ACCEPT - 1 } },
7423 +    },
7424 +    /* ERROR */
7425 +    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
7426 +       0,
7427 +       sizeof(struct ip6t_entry),
7428 +       sizeof(struct ip6t_error),
7429 +       0, NULL, 0, { 0, 0 }, { } },
7430 +      { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
7431 +         { } },
7432 +       "ERROR"
7433 +      }
7434 +    }
7435 +};
7436 +
7437 +static struct ip6t_table packet_raw = { 
7438 +       .name = "raw",
7439 +       .table = &initial_table.repl,
7440 +       .valid_hooks = RAW_VALID_HOOKS,
7441 +       .lock = RW_LOCK_UNLOCKED,
7442 +       .me = THIS_MODULE
7443 +};
7444 +
7445 +/* The work comes in here from netfilter.c. */
7446 +static unsigned int
7447 +ip6t_hook(unsigned int hook,
7448 +        struct sk_buff **pskb,
7449 +        const struct net_device *in,
7450 +        const struct net_device *out,
7451 +        int (*okfn)(struct sk_buff *))
7452 +{
7453 +       return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
7454 +}
7455 +
7456 +static struct nf_hook_ops ip6t_ops[] = { 
7457 +       { /* PRE_ROUTING */
7458 +               .hook = ip6t_hook,
7459 +               .owner = THIS_MODULE,
7460 +               .pf = PF_INET6,
7461 +               .hooknum = NF_IP6_PRE_ROUTING,
7462 +               .priority = NF_IP6_PRI_FIRST,
7463 +       },
7464 +       { /* LOCAL_OUT */
7465 +               .hook = ip6t_hook, 
7466 +               .owner = THIS_MODULE,
7467 +               .pf = PF_INET6, 
7468 +               .hooknum = NF_IP6_LOCAL_OUT,
7469 +               .priority = NF_IP6_PRI_FIRST,
7470 +       },
7471 +};
7472 +
7473 +static int __init init(void)
7474 +{
7475 +       int ret;
7476 +
7477 +       /* Register table */
7478 +       ret = ip6t_register_table(&packet_raw);
7479 +       if (ret < 0)
7480 +               return ret;
7481 +
7482 +       /* Register hooks */
7483 +       ret = nf_register_hook(&ip6t_ops[0]);
7484 +       if (ret < 0)
7485 +               goto cleanup_table;
7486 +
7487 +       ret = nf_register_hook(&ip6t_ops[1]);
7488 +       if (ret < 0)
7489 +               goto cleanup_hook0;
7490 +
7491 +       return ret;
7492 +
7493 + cleanup_hook0:
7494 +       nf_unregister_hook(&ip6t_ops[0]);
7495 + cleanup_table:
7496 +       ip6t_unregister_table(&packet_raw);
7497 +
7498 +       return ret;
7499 +}
7500 +
7501 +static void __exit fini(void)
7502 +{
7503 +       unsigned int i;
7504 +
7505 +       for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
7506 +               nf_unregister_hook(&ip6t_ops[i]);
7507 +
7508 +       ip6t_unregister_table(&packet_raw);
7509 +}
7510 +
7511 +module_init(init);
7512 +module_exit(fini);
7513 +MODULE_LICENSE("GPL");
7514 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
7515 +MODULE_DESCRIPTION("IPv6 raw table");
7516 diff -Nur linux-2.6.0-test9.org/netfilter-patch-o-matic/patches linux-2.6.0-test9/netfilter-patch-o-matic/patches
7517 --- linux-2.6.0-test9.org/netfilter-patch-o-matic/patches       1970-01-01 01:00:00.000000000 +0100
7518 +++ linux-2.6.0-test9/netfilter-patch-o-matic/patches   2003-11-13 11:02:28.000000000 +0100
7519 @@ -0,0 +1,30 @@
7520 +./base/01_sctp_match.patch
7521 +./pending/23_REJECT-headroom-tcprst.patch
7522 +./pending/24_rcu.patch
7523 +./pending/25-err-ptr.patch
7524 +./pending/26-memsets.patch
7525 +./pending/40_nf-log.patch
7526 +./pending/70_expect-evict-order.patch
7527 +./pending/71_raw.patch
7528 +./submitted/02_REJECT-headroom-tcprst.patch
7529 +./submitted/03_260t4-mirror-remove.patch
7530 +./submitted/03_physdev_bridged.patch
7531 +./submitted/04_260t4-unclean-remove.patch
7532 +./submitted/05_260t4-unexperimental.patch
7533 +./submitted/06_260t4-cosmetic.patch
7534 +./submitted/07_260t4-newmodules_iprange_SAME_NETMAP_CLASSIFY.patch
7535 +./submitted/07_nonlinear_skb.patch
7536 +./submitted/08_260t4_ipt-helper-kconfig.patch
7537 +./submitted/09_260t4-cosmetic-physdev-author.patch
7538 +./submitted/75_nathelper-udp-csum.patch
7539 +./submitted/76_mangle_udp-sizecheck.patch
7540 +./submitted/77_destroy-conntrack.patch
7541 +./submitted/78_reject-localout.patch
7542 +./submitted/80_ip_conntrack-proc.patch
7543 +./submitted/82_irc-conntrack-mirc-serverlookup.patch
7544 +./submitted/83_nolocalout.patch
7545 +./submitted/84_local-nullbinding.patch
7546 +./submitted/85_ipv6header.patch
7547 +./submitted/86_getorigdst-tuple-zero.patch
7548 +./submitted/87_compat-nat_setup_info.patch
7549 +./submitted/89_ip_queue-maxlen.patch
This page took 0.610095 seconds and 3 git commands to generate.